]> Git trees. - libqmvoc.git/commitdiff
Adding ExtDate library to libkdeedu. ExtDate is a replacement for
authorJason Harris <kstars@30doradus.org>
Sun, 18 Apr 2004 07:58:44 +0000 (07:58 +0000)
committerJason Harris <kstars@30doradus.org>
Sun, 18 Apr 2004 07:58:44 +0000 (07:58 +0000)
QDate that eliminates its arbitrary date-range limits (QDate cannot
accept dates prior to year 1752 or after year 8000).  There is no
theoretical limit to the range of dates that ExtDate can accept, but
I have imposed a range of -50000 to +50000 for now.

The ExtDate library is based on the initial work of Michel Guitel, who
wrote the original ExtDate class.  I have added the following classes:

ExtDateTime (replaces QDateTime)
ExtCalendarSystem (replaces KCalendarSystem)
ExtCalendarSystemGregorian (replaces KCalendarSystemGregorian)
ExtDateTable (replaces KDateTable)
ExtDatePicker (replaces KDatePicker)
ExtDateTimeEdit (replaces QDateTimeEdit)
ExtDateWidget (replaces KDateWidget)

Most of the work was simply pasting in the class to be replaced, and
global-replacing QDate with ExtDate.  However, there are some
remaining issues:

+ currently, only the Gregorian calendar is supported
+ using KLocale to set the date string format does not work
+ API docs are needed

Once the issues have been worked out, I would like to propose to
kde-core-devel that these classes be added to kdelibs for KDE4.
However, I am not sure if any other apps besides KStars really need
very remote dates.

The library includes two test-programs for verifying the performance
of ExtDate.  The first (test_extdate) is a command-line program that
simply outputs the results of 9 tests comparing the performance of
ExtDate and QDate.  If ExtDate is working correctly, then the only
differences will be for dates outside of QDate's valid range.  The
second (test_extdatepicker) is a GUI app showing a KDatePicker and an
ExtDatePicker side-by-side (there is a slight rendering difference
between ExtDatePicker and KDatePicker on my system; I don't know
why this is happening).

The other way to test it is to run kstars; I am going to commit the
ExtDate code in kstars shortly...

CCMAIL: kde-edu@kde.org
CCMAIL: kstars-devel@kde.org
CCMAIL: michel.guitel@free.fr

svn path=/trunk/kdeedu/libkdeedu/; revision=304574

21 files changed:
Makefile.am
extdate/Makefile.am [new file with mode: 0644]
extdate/README [new file with mode: 0644]
extdate/extcalendarsystem.cpp [new file with mode: 0644]
extdate/extcalendarsystem.h [new file with mode: 0644]
extdate/extcalendarsystemgregorian.cpp [new file with mode: 0644]
extdate/extcalendarsystemgregorian.h [new file with mode: 0644]
extdate/extdatepicker.cpp [new file with mode: 0644]
extdate/extdatepicker.h [new file with mode: 0644]
extdate/extdatetbl.cpp [new file with mode: 0644]
extdate/extdatetbl.h [new file with mode: 0644]
extdate/extdatetime.cpp [new file with mode: 0644]
extdate/extdatetime.h [new file with mode: 0644]
extdate/extdatetimeedit.cpp [new file with mode: 0644]
extdate/extdatetimeedit.h [new file with mode: 0644]
extdate/extdatewidget.cpp [new file with mode: 0644]
extdate/extdatewidget.h [new file with mode: 0644]
extdate/main.cpp [new file with mode: 0644]
extdate/test_extdate.cc [new file with mode: 0644]
extdate/testwidget.cpp [new file with mode: 0644]
extdate/testwidget.h [new file with mode: 0644]

index d22b161927ba3337583af93422c3d3826a6811f9..112b95d1634aed28d0b835144095da0e86e0dd74 100644 (file)
@@ -1 +1 @@
-SUBDIRS = kdeeducore kdeeduui kdeeduplot
+SUBDIRS = kdeeducore kdeeduui kdeeduplot extdate
diff --git a/extdate/Makefile.am b/extdate/Makefile.am
new file mode 100644 (file)
index 0000000..fbf4148
--- /dev/null
@@ -0,0 +1,20 @@
+bin_PROGRAMS = test_extdate test_extdatepicker
+
+INCLUDES= $(all_includes)
+SUBDIRS = . 
+
+lib_LTLIBRARIES = libextdate.la
+
+libextdate_la_SOURCES = extdatetime.cpp extcalendarsystem.cpp extcalendarsystemgregorian.cpp extdatetbl.cpp extdatepicker.cpp extdatetimeedit.cpp extdatewidget.cpp
+
+libextdate_la_LDFLAGS = $(all_libraries) -no-undefined -version-info 3:0:2
+libextdate_la_LIBADD = $(LIB_KDECORE) $(LIB_QT) $(LIB_KDEUI)
+
+test_extdate_SOURCES = test_extdate.cc
+test_extdate_LDADD = libextdate.la
+
+test_extdatepicker_SOURCES = testwidget.cpp main.cpp
+test_extdatepicker_LDADD = libextdate.la
+
+METASOURCES = AUTO
+
diff --git a/extdate/README b/extdate/README
new file mode 100644 (file)
index 0000000..fc9b21b
--- /dev/null
@@ -0,0 +1,43 @@
+This libray consists of a group of classes which allow KDE 
+applications to access calendar dates outside of the limited range 
+of years imposed by QDate.
+
+The QDate class has a limited range of valid dates.  It does not 
+recognize dates prior to 14 Oct 1752 (when the Gregorian calendar 
+was adopted by England), nor dates after 31 Dec 8000.  Both of these 
+limits are arbitrary.
+
+
+The following classes are included:
+
+ExtDate:  Replaces QDate.  There is no restriction on what dates 
+may be entered.  For dates in the valid QDate range, it is 
+completely equivalent to QDate.
+
+ExtDateTime:  Replaces QDateTime.  Consists of a QTime object
+and an ExtDate object.
+
+ExtCalendarSystem:  Replaces KCalendarSystem.  Uses ExtDate instead
+of QDate.  ExtCalendarSystem is a baseclass foundation for several 
+different calendar systems.  A "calendar system" is just a method for
+hierarchically subdividing the long count of days known as the Julian 
+Day Calendar into groups (weeks, months, years).  
+
+ExtCalendarSystemGregorian:  Replaces KCalendarSystemGregorian.
+The most common calendar system in modern western societies is the 
+Gregorian calendar.  This class implements the Gregorian calendar 
+as a ExtCalendarSystem.
+
+ExtDateTable:  Replaces KDateTable.
+ExtDatePicker:  Replaces KDatePicker.
+ExtDateTimeEdit: Replaces QDateTimeEdit.
+ExtDateWidget:  Replaces KDateWidget.
+
+There are two test programs with the library, to verify the 
+functionality of the ExtDate classes:
+
+test_extdate tests the non-GUI functionality, comparing results of 
+several operations with the results from QDate.
+
+test_extdatepicker presents a KDatePicker widget and an ExtDatePicker
+widget side-by-side.
diff --git a/extdate/extcalendarsystem.cpp b/extdate/extcalendarsystem.cpp
new file mode 100644 (file)
index 0000000..1f49b9f
--- /dev/null
@@ -0,0 +1,151 @@
+/*
+   Copyright (c) 2002 Carlos Moro <cfmoro@correo.uniovi.es>
+   Copyright (c) 2002 Hans Petter Bieker <bieker@kde.org>
+   Copyright (c) 2004 Jason Harris <jharris@30doradus.org>
+
+        This class has been derived from ExtCalendarSystem;
+        the changesd made just replace QDate objects with ExtDate objects.
+        These changes by Jason Harris <jharris@30doradus.org>
+
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public
+   License as published by the Free Software Foundation; either
+   version 2 of the License, or (at your option) any later version.
+
+   This library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public License
+   along with this library; see the file COPYING.LIB.  If not, write to
+   the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.
+*/
+
+// Gregorian calendar system implementation factory for creation of kde calendar
+// systems.
+// Also default gregorian and factory classes
+
+#include <kglobal.h>
+
+#include "extcalendarsystem.h"
+#include "klocale.h"
+
+class ExtCalendarSystemPrivate
+{
+public:
+  const KLocale * locale;
+};
+
+ExtCalendarSystem::ExtCalendarSystem(const KLocale * locale)
+  : d(new ExtCalendarSystemPrivate)
+{
+  d->locale = locale;
+}
+
+ExtCalendarSystem::~ExtCalendarSystem()
+{
+  delete d;
+}
+
+const KLocale * ExtCalendarSystem::locale() const
+{
+  if ( d->locale )
+    return d->locale;
+
+  return KGlobal::locale();
+}
+
+QString ExtCalendarSystem::dayString(const ExtDate & pDate, bool bShort) const
+{
+  QString sResult;
+
+  sResult.setNum(day(pDate));
+  if (!bShort && sResult.length() == 1 )
+    sResult.prepend('0');
+
+  return sResult;
+}
+
+QString ExtCalendarSystem::monthString(const ExtDate & pDate, bool bShort) const
+{
+  QString sResult;
+
+  sResult.setNum(month(pDate));
+  if (!bShort && sResult.length() == 1 )
+    sResult.prepend('0');
+
+  return sResult;
+}
+
+QString ExtCalendarSystem::yearString(const ExtDate & pDate, bool bShort) const
+{
+  QString sResult;
+
+  sResult.setNum(year(pDate));
+  if (bShort && sResult.length() == 4 )
+    sResult = sResult.right(2);
+
+  return sResult;
+}
+
+static int stringToInteger(const QString & sNum, int & iLength)
+{
+  unsigned int iPos = 0;
+
+  int result = 0;
+  for (; sNum.length() > iPos && sNum.at(iPos).isDigit(); iPos++)
+    {
+      result *= 10;
+      result += sNum.at(iPos).digitValue();
+    }
+
+  iLength = iPos;
+  return result;
+}
+
+
+int ExtCalendarSystem::dayStringToInteger(const QString & sNum, int & iLength) const
+{
+  return stringToInteger(sNum, iLength);
+}
+
+int ExtCalendarSystem::monthStringToInteger(const QString & sNum, int & iLength) const
+{
+  return stringToInteger(sNum, iLength);
+}
+
+int ExtCalendarSystem::yearStringToInteger(const QString & sNum, int & iLength) const
+{
+  return stringToInteger(sNum, iLength);
+}
+
+QString ExtCalendarSystem::weekDayName (int weekDay, bool shortName) const
+{
+  if ( shortName )
+    switch ( weekDay )
+      {
+      case 1:  return locale()->translate("Monday", "Mon");
+      case 2:  return locale()->translate("Tuesday", "Tue");
+      case 3:  return locale()->translate("Wednesday", "Wed");
+      case 4:  return locale()->translate("Thursday", "Thu");
+      case 5:  return locale()->translate("Friday", "Fri");
+      case 6:  return locale()->translate("Saturday", "Sat");
+      case 7:  return locale()->translate("Sunday", "Sun");
+      }
+  else
+    switch ( weekDay )
+      {
+      case 1:  return locale()->translate("Monday");
+      case 2:  return locale()->translate("Tuesday");
+      case 3:  return locale()->translate("Wednesday");
+      case 4:  return locale()->translate("Thursday");
+      case 5:  return locale()->translate("Friday");
+      case 6:  return locale()->translate("Saturday");
+      case 7:  return locale()->translate("Sunday");
+      }
+
+  return QString::null;
+}
+
diff --git a/extdate/extcalendarsystem.h b/extdate/extcalendarsystem.h
new file mode 100644 (file)
index 0000000..7b0915a
--- /dev/null
@@ -0,0 +1,358 @@
+/*
+   Copyright (c) 2002 Carlos Moro <cfmoro@correo.uniovi.es>
+   Copyright (c) 2002-2003 Hans Petter Bieker <bieker@kde.org>
+   Copyright (c) 2004 Jason Harris <jharris@30doradus.org>
+
+        This class has been derived from KCalendarSystem;
+        the changesd made just replace QDate objects with ExtDate objects.
+        These changes by Jason Harris <jharris@30doradus.org>
+
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public
+   License as published by the Free Software Foundation; either
+   version 2 of the License, or (at your option) any later version.
+
+   This library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public License
+   along with this library; see the file COPYING.LIB.  If not, write to
+   the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.
+*/
+
+#ifndef EXTCALENDARSYSTEM_H
+#define EXTCALENDARSYSTEM_H
+
+#include "extdatetime.h"
+#include <qstring.h>
+
+class KLocale;
+
+class ExtCalendarSystemPrivate;
+
+/**
+ * CalendarSystem abstract class, default derived kde gregorian class and
+ * factory class. Provides support for different calendar types for kde
+ * calendar widget and related stuff.
+ *
+ * Derived classes must be created through ExtCalendarFactory class
+ *
+ * @author Carlos Moro <cfmoro@correo.uniovi.es>
+ * @version $Id$
+ * @since 3.2
+ */
+class ExtCalendarSystem
+{
+public:
+  /**
+   * Constructor of abstract calendar class. This will be called by the derived classes.
+   *
+   * @param locale It will use this locale for translations, 0 means global.
+   */
+  ExtCalendarSystem(const KLocale * locale = 0);
+
+  /**
+   * Descructor.
+   */
+  virtual ~ExtCalendarSystem();
+
+  /**
+   * Gets specific calendar type year for a given gregorian date
+   *
+   * @param date gregorian date
+   * @return year
+   */
+  virtual int year (const ExtDate & date) const = 0;
+
+  /**
+   * Converts a date into a year literal
+   *
+   * @param pDate The date to convert
+   * @param bShort If the short version of should be used
+   * @return The year literal of the date
+   */
+  virtual QString yearString(const ExtDate & pDate, bool bShort) const;
+
+  /**
+   * Converts a year literal of a part of a string into a integer starting at the beginning of the string
+   *
+   * @param sNum The string to parse
+   * @param iLength The number of QChars used, and 0 if no valid symbols was found in the string
+   * @return An integer corresponding to the year
+   */
+  virtual int yearStringToInteger(const QString & sNum, int & iLength) const;
+
+  /**
+   * Gets specific calendar type month for a given gregorian date
+   *
+   * @param date gregorian date
+   * @return month number
+   */
+  virtual int month (const ExtDate & date) const = 0;
+
+  /**
+   * Converts a date into a month literal
+   *
+   * @param pDate The date to convert
+   * @param bShort If the short version of should be used
+   * @return The month literal of the date
+   */
+  virtual QString monthString(const ExtDate & pDate, bool bShort) const;
+
+  /**
+   * Converts a month literal of a part of a string into a integer starting at the beginning of the string
+   *
+   * @param sNum The string to parse
+   * @param iLength The number of QChars used, and 0 if no valid symbols was found in the string
+   * @return An integer corresponding to the month
+   */
+  virtual int monthStringToInteger(const QString & sNum, int & iLength) const;
+
+  /**
+   * Gets specific calendar type day number of month for a given date
+   *
+   * @param date gregorian date equivalent to the specific one
+   * @return day of the month
+   */
+  virtual int day (const ExtDate & date) const = 0;
+
+  /**
+   * Converts a date into a day literal
+   *
+   * @param pDate The date to convert
+   * @param bShort If the short version of should be used
+   * @return The day literal of the date
+   */
+  virtual QString dayString(const ExtDate & pDate, bool bShort) const;
+
+  /**
+   * Converts a day literal of a part of a string into a integer starting at the beginning of the string
+   *
+   * @param sNum The string to parse
+   * @param iLength The number of QChars used, and 0 if no valid symbols was found in the string
+   * @return An integer corresponding to the day
+   */
+  virtual int dayStringToInteger(const QString & sNum, int & iLength) const;
+
+  /**
+   * Gets specific calendar type number of day of week number for a given
+   * date
+   *
+   * @param date gregorian date
+   * @return day of week
+   */
+  virtual int dayOfWeek (const ExtDate & date) const = 0;
+
+  /**
+   * Gets specific calendar type day number of year for a given date
+   *
+   * @param date gregorian date equivalent to the specific one
+   * @return day number
+   */
+  virtual int dayOfYear (const ExtDate & date) const = 0;
+
+  /**
+   * Changes the date's year, month and day. The range of the year, month
+   * and day depends on which calendar is being used.
+   *
+   * @param date Date to change
+   * @param y Year
+   * @param m Month number
+   * @param d Day of month
+   * @return true if the date is valid; otherwise returns false.
+   */
+  virtual bool setYMD(ExtDate & date, int y, int m, int d) const = 0;
+
+  /**
+   * Returns a QDate object containing a date nyears later.
+   *
+   * @param date The old date
+   * @param nyears The number of years to add
+   * @return The new date
+   */
+  virtual ExtDate addYears(const ExtDate & date, int nyears) const = 0;
+
+  /**
+   * Returns a QDate object containing a date nmonths later.
+   *
+   * @param date The old date
+   * @param nmonths The number of months to add
+   * @return The new date
+   */
+  virtual ExtDate addMonths(const ExtDate & date, int nmonths) const = 0;
+
+  /**
+   * Returns a QDate object containing a date ndays later.
+   *
+   * @param date The old date
+   * @param ndays The number of days to add
+   * @return The new date
+   */
+  virtual ExtDate addDays(const ExtDate & date, int ndays) const = 0;
+
+  /**
+   * Gets specific calendar type number of month for a given year
+   *
+   * @param date The date whose year to use
+   * @return The number of months in that year
+   */
+  virtual int monthsInYear (const ExtDate & date) const = 0;
+
+  /**
+   * Gets the number of days in date whose years specified.
+   *
+   * @param date Gregorian date equivalent to the specific one
+   * @return The number of days in year
+   */
+  virtual int daysInYear (const ExtDate & date) const = 0;
+
+  /**
+   * Gets specific calendar type number of days in month for a given date
+   *
+   * @param date gregorian date
+   * @return number of days for month in date
+   */
+  virtual int daysInMonth (const ExtDate & date) const = 0;
+
+  /**
+   * Gets the number of weeks in a specified year
+   *
+   * @param year the year
+   * @return number of weeks in year
+   */
+  virtual int weeksInYear(int year) const = 0;
+
+  /**
+   * Gets specific calendar type week number for a given date
+   *
+   * @param date gregorian date
+   * @param yearNum The year the date belongs to
+   * @return week number
+   */
+  virtual int weekNumber(const ExtDate& date, int * yearNum = 0) const = 0;
+
+  /**
+   * Gets specific calendar type month name for a given month number
+   * If an invalid month is specified, QString::null is returned.
+   *
+   * @param month The month number
+   * @param year The year the month belongs to
+   * @param shortName Specifies if the short month name should be used
+   * @return The name of the month
+   */
+  virtual QString monthName (int month, int year, bool shortName = false) const = 0;
+
+  /**
+   * Gets specific calendar type month name for a given gregorian date
+   *
+   * @param date Gregorian date
+   * @param shortName Specifies if the short month name should be used
+   * @return The name of the month
+   */
+  virtual QString monthName (const ExtDate & date, bool shortName = false ) const = 0;
+
+  /**
+   * Returns a string containing the possessive form of the month name.
+   * ("of January", "of February", etc.)
+   * It's needed in long format dates in some languages.
+   * If an invalid month is specified, QString::null is returned.
+   *
+   * @param month The month number
+   * @param year The year the month belongs to
+   * @param shortName Specifies if the short month name should be used
+   *
+   * @return The possessive form of the name of the month
+   */
+  virtual QString monthNamePossessive(int month, int year, bool shortName = false) const = 0;
+
+  /**
+   * Returns a string containing the possessive form of the month name.
+   * ("of January", "of February", etc.)
+   * It's needed in long format dates in some languages.
+   *
+   * @param date Gregorian date
+   * @param shortName Specifies if the short month name should be used
+   *
+   * @return The possessive form of the name of the month
+   */
+  virtual QString monthNamePossessive(const ExtDate & date, bool shortName = false) const = 0;
+
+  /**
+   * Gets specific calendar type week day name
+   * If an invalid week day is specified, QString::null is returned.
+   *
+   * @param weekDay number of day in week (1 -> Monday)
+   * @param shortName short or complete day name
+   * @return day name
+   */
+  virtual QString weekDayName (int weekDay, bool shortName = false) const = 0;
+
+  /**
+   * Gets specific calendar type week day name
+   *
+   * @param date the date
+   * @param shortName short or complete day name
+   * @return day name
+   */
+  virtual QString weekDayName (const ExtDate & date, bool shortName = false) const = 0;
+
+  /**
+   * Gets the first year value supported by specific calendar type
+   * algorithms.
+   *
+   * @return first year supported
+   */
+  virtual int minValidYear () const = 0;
+
+  /**
+   * Gets the maximum year value supported by specific calendar type
+   * algorithms (QDate, 8000)
+   *
+   * @return maximum year supported
+   */
+  virtual int maxValidYear () const = 0;
+
+  /**
+   * Gets the day of the week traditionaly associated with pray
+   *
+   * @return day number
+   */
+  virtual int weekDayOfPray () const = 0;
+
+  /**
+   * Gets the string representing the calendar
+   */
+  virtual QString calendarName() const = 0;
+
+  /**
+   * Gets if the calendar is lunar based
+   *
+   * @return if the calendar is lunar based
+   */
+  virtual bool isLunar() const = 0;
+
+  /**
+   * Gets if the calendar is lunisolar based
+   *
+   * @return if the calendar is lunisolar based
+   */
+  virtual bool isLunisolar() const = 0;
+
+  /**
+   * Gets if the calendar is solar based
+   *
+   * @return if the calendar is solar based
+   */
+  virtual bool isSolar() const = 0;
+
+protected:
+  const KLocale * locale() const;
+
+private:
+  ExtCalendarSystemPrivate * d;
+};
+
+#endif
diff --git a/extdate/extcalendarsystemgregorian.cpp b/extdate/extcalendarsystemgregorian.cpp
new file mode 100644 (file)
index 0000000..99427b3
--- /dev/null
@@ -0,0 +1,330 @@
+/*
+   Copyright (c) 2002 Carlos Moro <cfmoro@correo.uniovi.es>
+   Copyright (c) 2002-2003 Hans Petter Bieker <bieker@kde.org>
+   Copyright (c) 2004 Jason Harris <jharris@30doradus.org>
+
+        This class has been derived from KCalendarSystemGregorian;
+        the changesd made just replace QDate objects with ExtDate objects.
+        These changes by Jason Harris <jharris@30doradus.org>
+
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public
+   License as published by the Free Software Foundation; either
+   version 2 of the License, or (at your option) any later version.
+
+   This library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public License
+   along with this library; see the file COPYING.LIB.  If not, write to
+   the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.
+*/
+
+// Derived gregorian kde calendar class
+// Just a schema.
+
+#include <qdatetime.h>
+#include <qstring.h>
+
+#include <klocale.h>
+#include <kdebug.h>
+
+#include "extcalendarsystemgregorian.h"
+
+ExtCalendarSystemGregorian::ExtCalendarSystemGregorian(const KLocale * locale)
+  : ExtCalendarSystem(locale)
+{
+}
+
+ExtCalendarSystemGregorian::~ExtCalendarSystemGregorian()
+{
+}
+
+int ExtCalendarSystemGregorian::year(const ExtDate& date) const
+{
+  return date.year();
+}
+
+int ExtCalendarSystemGregorian::monthsInYear( const ExtDate & date ) const
+{
+  Q_UNUSED( date )
+
+  return 12;
+}
+
+int ExtCalendarSystemGregorian::weeksInYear(int year) const
+{
+  ExtDate temp;
+  temp.setYMD(year, 12, 31);
+
+  // If the last day of the year is in the first week, we have to check the
+  // week before
+  if ( temp.weekNumber() == 1 )
+    temp = temp.addDays(-7);
+
+  return temp.weekNumber();
+}
+
+int ExtCalendarSystemGregorian::weekNumber(const ExtDate& date,
+                                         int * yearNum) const
+{
+  return date.weekNumber(yearNum);
+}
+
+QString ExtCalendarSystemGregorian::monthName(const ExtDate& date,
+                                            bool shortName) const
+{
+  return monthName(month(date), shortName);
+}
+
+QString ExtCalendarSystemGregorian::monthNamePossessive(const ExtDate& date, bool shortName) const
+{
+  return monthNamePossessive(month(date), shortName);
+}
+
+QString ExtCalendarSystemGregorian::monthName(int month, int year, bool shortName) const
+{
+  Q_UNUSED(year);
+
+  if ( shortName )
+    switch ( month )
+      {
+      case 1:
+        return locale()->translate("January", "Jan");
+      case 2:
+        return locale()->translate("February", "Feb");
+      case 3:
+        return locale()->translate("March", "Mar");
+      case 4:
+        return locale()->translate("April", "Apr");
+      case 5:
+        return locale()->translate("May short", "May");
+      case 6:
+        return locale()->translate("June", "Jun");
+      case 7:
+        return locale()->translate("July", "Jul");
+      case 8:
+        return locale()->translate("August", "Aug");
+      case 9:
+        return locale()->translate("September", "Sep");
+      case 10:
+        return locale()->translate("October", "Oct");
+      case 11:
+        return locale()->translate("November", "Nov");
+      case 12:
+        return locale()->translate("December", "Dec");
+      }
+  else
+    switch ( month )
+      {
+      case 1:
+        return locale()->translate("January");
+      case 2:
+        return locale()->translate("February");
+      case 3:
+        return locale()->translate("March");
+      case 4:
+        return locale()->translate("April");
+      case 5:
+        return locale()->translate("May long", "May");
+      case 6:
+        return locale()->translate("June");
+      case 7:
+        return locale()->translate("July");
+      case 8:
+        return locale()->translate("August");
+      case 9:
+        return locale()->translate("September");
+      case 10:
+        return locale()->translate("October");
+      case 11:
+        return locale()->translate("November");
+      case 12:
+        return locale()->translate("December");
+      }
+
+  return QString::null;
+}
+
+QString ExtCalendarSystemGregorian::monthNamePossessive(int month, int year,
+                                                      bool shortName) const
+{
+  Q_UNUSED(year);
+
+  if ( shortName )
+    switch ( month )
+      {
+      case 1:
+        return locale()->translate("of January", "of Jan");
+      case 2:
+        return locale()->translate("of February", "of Feb");
+      case 3:
+        return locale()->translate("of March", "of Mar");
+      case 4:
+        return locale()->translate("of April", "of Apr");
+      case 5:
+        return locale()->translate("of May short", "of May");
+      case 6:
+        return locale()->translate("of June", "of Jun");
+      case 7:
+        return locale()->translate("of July", "of Jul");
+      case 8:
+        return locale()->translate("of August", "of Aug");
+      case 9:
+        return locale()->translate("of September", "of Sep");
+      case 10:
+        return locale()->translate("of October", "of Oct");
+      case 11:
+       return locale()->translate("of November", "of Nov");
+      case 12:
+        return locale()->translate("of December", "of Dec");
+      }
+  else
+    switch ( month )
+      {
+      case 1:
+        return locale()->translate("of January");
+      case 2:
+        return locale()->translate("of February");
+      case 3:
+        return locale()->translate("of March");
+      case 4:
+        return locale()->translate("of April");
+      case 5:
+        return locale()->translate("of May long", "of May");
+      case 6:
+        return locale()->translate("of June");
+      case 7:
+        return locale()->translate("of July");
+      case 8:
+        return locale()->translate("of August");
+      case 9:
+        return locale()->translate("of September");
+      case 10:
+        return locale()->translate("of October");
+      case 11:
+        return locale()->translate("of November");
+      case 12:
+        return locale()->translate("of December");
+      }
+
+  return QString::null;
+}
+
+bool ExtCalendarSystemGregorian::setYMD(ExtDate & date, int y, int m, int d) const
+{
+  // ExtDate supports gregorian internally
+  return date.setYMD(y, m, d);
+}
+
+ExtDate ExtCalendarSystemGregorian::addYears(const ExtDate & date, int nyears) const
+{
+  return date.addYears(nyears);
+}
+
+ExtDate ExtCalendarSystemGregorian::addMonths(const ExtDate & date, int nmonths) const
+{
+  return date.addMonths(nmonths);
+}
+
+ExtDate ExtCalendarSystemGregorian::addDays(const ExtDate & date, int ndays) const
+{
+  return date.addDays(ndays);
+}
+
+QString ExtCalendarSystemGregorian::weekDayName(int col, bool shortName) const
+{
+  // ### Should this really be different to each calendar system? Or are we
+  //     only going to support weeks with 7 days?
+
+  return ExtCalendarSystem::weekDayName(col, shortName);
+}
+
+QString ExtCalendarSystemGregorian::weekDayName(const ExtDate& date, bool shortName) const
+{
+  return weekDayName(dayOfWeek(date), shortName);
+}
+
+
+int ExtCalendarSystemGregorian::dayOfWeek(const ExtDate& date) const
+{
+  return date.dayOfWeek();
+}
+
+int ExtCalendarSystemGregorian::dayOfYear(const ExtDate & date) const
+{
+  return date.dayOfYear();
+}
+
+int ExtCalendarSystemGregorian::daysInMonth(const ExtDate& date) const
+{
+  return date.daysInMonth();
+}
+
+int ExtCalendarSystemGregorian::minValidYear() const
+{
+  return -50000;
+}
+
+int ExtCalendarSystemGregorian::maxValidYear() const
+{
+  return 50000;
+}
+
+int ExtCalendarSystemGregorian::day(const ExtDate& date) const
+{
+  return date.day();
+}
+
+int ExtCalendarSystemGregorian::month(const ExtDate& date) const
+{
+  return date.month();
+}
+
+int ExtCalendarSystemGregorian::daysInYear(const ExtDate& date) const
+{
+  return date.daysInYear();
+}
+
+int ExtCalendarSystemGregorian::weekDayOfPray() const
+{
+  return 7; // sunday
+}
+
+QString ExtCalendarSystemGregorian::calendarName() const
+{
+  return QString::fromLatin1("gregorian");
+}
+
+bool ExtCalendarSystemGregorian::isLunar() const
+{
+  return false;
+}
+
+bool ExtCalendarSystemGregorian::isLunisolar() const
+{
+  return false;
+}
+
+bool ExtCalendarSystemGregorian::isSolar() const
+{
+  return true;
+}
+
+int ExtCalendarSystemGregorian::yearStringToInteger(const QString & sNum, int & iLength) const
+{
+  int iYear;
+  iYear = ExtCalendarSystem::yearStringToInteger(sNum, iLength);
+
+  // Qt treats a year in the range 0-100 as 1900-1999.
+  // It is nicer for the user if we treat 0-68 as 2000-2068
+  if (iYear < 69)
+    iYear += 2000;
+  else if (iYear < 100)
+    iYear += 1900;
+
+  return iYear;
+}
diff --git a/extdate/extcalendarsystemgregorian.h b/extdate/extcalendarsystemgregorian.h
new file mode 100644 (file)
index 0000000..67c48fc
--- /dev/null
@@ -0,0 +1,98 @@
+/*
+   Copyright (c) 2002 Carlos Moro <cfmoro@correo.uniovi.es>
+   Copyright (c) 2002 Hans Petter Bieker <bieker@kde.org>
+   Copyright (c) 2004 Jason Harris <jharris@30doradus.org>
+
+        This class has been derived from KCalendarSystemGregorian;
+        the changesd made just replace QDate objects with ExtDate objects.
+        These changes by Jason Harris <jharris@30doradus.org>
+
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Library General Public
+   License as published by the Free Software Foundation; either
+   version 2 of the License, or (at your option) any later version.
+
+   This library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Library General Public License for more details.
+
+   You should have received a copy of the GNU Library General Public License
+   along with this library; see the file COPYING.LIB.  If not, write to
+   the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+   Boston, MA 02111-1307, USA.
+*/
+
+#ifndef EXTCALENDARSYSTEMGREGORIAN_H
+#define EXTCALENDARSYSTEMGREGORIAN_H
+
+#include <extdatetime.h>
+#include <qstring.h>
+
+#include "extcalendarsystem.h"
+
+class ExtCalendarSystemGregorianPrivate;
+
+/**
+ * @internal
+ * This is the Gregorian calendar implementation.
+ *
+ * The Gregorian calender is the most used calendar today. The first year in
+ * the calendar is set to the birth of Christ.
+ *
+ * @see KLocale,ExtCalendarSystem,ExtCalendarSystemFactory
+ *
+ * @author Carlos Moro <cfmoro@correo.uniovi.es>
+ * @license GNU-GPL v.2
+ * @version $Id$
+ * @since 3.2
+ */
+class ExtCalendarSystemGregorian: public ExtCalendarSystem
+{
+public:
+  ExtCalendarSystemGregorian (const KLocale * locale = 0);
+  virtual ~ExtCalendarSystemGregorian ();
+
+  virtual int year (const ExtDate & date) const;
+  virtual int month (const ExtDate & date) const;
+  virtual int day (const ExtDate & date) const;
+  virtual int dayOfWeek (const ExtDate & date) const;
+  virtual int dayOfYear (const ExtDate & date) const;
+
+  virtual bool setYMD(ExtDate & date, int y, int m, int d) const;
+
+  virtual ExtDate addYears(const ExtDate & date, int nyears) const;
+  virtual ExtDate addMonths(const ExtDate & date, int nmonths) const;
+  virtual ExtDate addDays(const ExtDate & date, int ndays) const;
+
+  virtual int monthsInYear (const ExtDate & date) const;
+
+  virtual int daysInYear (const ExtDate & date) const;
+  virtual int daysInMonth (const ExtDate & date) const;
+  virtual int weeksInYear(int year) const;
+  virtual int weekNumber(const ExtDate& date, int * yearNum = 0) const;
+
+  virtual int yearStringToInteger(const QString & sNum, int & iLength) const;
+
+  virtual QString monthName (int month, int year, bool shortName = false) const;
+  virtual QString monthName (const ExtDate & date, bool shortName = false ) const;
+  virtual QString monthNamePossessive(int month, int year, bool shortName = false) const;
+  virtual QString monthNamePossessive(const ExtDate & date, bool shortName = false ) const;
+  virtual QString weekDayName (int weekDay, bool shortName = false) const;
+  virtual QString weekDayName (const ExtDate & date, bool shortName = false) const;
+
+  virtual int minValidYear () const;
+  virtual int maxValidYear () const;
+  virtual int weekDayOfPray () const;
+
+  virtual QString calendarName() const;
+
+  virtual bool isLunar() const;
+  virtual bool isLunisolar() const;
+  virtual bool isSolar() const;
+
+private:
+  ExtCalendarSystemGregorianPrivate * d;
+};
+
+#endif
diff --git a/extdate/extdatepicker.cpp b/extdate/extdatepicker.cpp
new file mode 100644 (file)
index 0000000..d0fac80
--- /dev/null
@@ -0,0 +1,540 @@
+/*  -*- C++ -*-
+    This file is part of the KDE libraries
+    Copyright (C) 1997 Tim D. Gilman (tdgilman@best.org)
+              (C) 1998-2001 Mirko Boehm (mirko@kde.org)
+              (C) 2004 Jason Harris (jharris@30doradus.org)
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Library General Public
+    License as published by the Free Software Foundation; either
+    version 2 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Library General Public License for more details.
+
+    You should have received a copy of the GNU Library General Public License
+    along with this library; see the file COPYING.LIB.  If not, write to
+    the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+    Boston, MA 02111-1307, USA.
+*/
+
+#include <qlayout.h>
+#include <qframe.h>
+#include <qpainter.h>
+#include <qdialog.h>
+#include <qstyle.h>
+#include <qtoolbutton.h>
+#include <qcombobox.h>
+#include <qtooltip.h>
+#include <qfont.h>
+#include <qvalidator.h>
+#include <qpopupmenu.h>
+
+#include <kglobal.h>
+#include <kapplication.h>
+#include <kdialog.h>
+#include <klocale.h>
+#include <kiconloader.h>
+#include <ktoolbar.h>
+#include <klineedit.h>
+#include <kdebug.h>
+#include <knotifyclient.h>
+
+#include "extdatepicker.h"
+#include "extdatetbl.h"
+#include "extcalendarsystem.h"
+#include "extdatepicker.moc"
+
+// Week numbers are defined by ISO 8601
+// See http://www.merlyn.demon.co.uk/weekinfo.htm for details
+
+class ExtDatePicker::ExtDatePickerPrivate
+{
+public:
+    ExtDatePickerPrivate() : closeButton(0L), selectWeek(0L), todayButton(0),
+      navigationLayout(0), calendar(0) {}
+
+    void fillWeeksCombo(const ExtDate &date);
+
+    QToolButton *closeButton;
+    QComboBox *selectWeek;
+    QToolButton *todayButton;
+    QBoxLayout *navigationLayout;
+    ExtCalendarSystem *calendar;
+};
+
+void ExtDatePicker::fillWeeksCombo(const ExtDate &date)
+{
+  // every year can have a different number of weeks
+
+//must remain commented unless ExtDate stuff gets added to kdelibs
+//  const ExtCalendarSystem * calendar = KGlobal::locale()->calendar();
+
+  // it could be that we had 53,1..52 and now 1..53 which is the same number but different
+  // so always fill with new values
+
+  d->selectWeek->clear();
+
+  // We show all week numbers for all weeks between first day of year to last day of year
+  // This of course can be a list like 53,1,2..52
+
+  ExtDate day(date.year(), 1, 1);
+  int lastMonth = d->calendar->monthsInYear(day);
+  ExtDate lastDay(date.year(), lastMonth, d->calendar->daysInMonth(ExtDate(date.year(), lastMonth, 1)));
+
+  for (; day <= lastDay; day = d->calendar->addDays(day, 7 /*calendar->daysOfWeek()*/) )
+  {
+    int year = 0;
+    QString week = i18n("Week %1").arg(d->calendar->weekNumber(day, &year));
+    if ( year != date.year() ) week += "*";  // show that this is a week from a different year
+    d->selectWeek->insertItem(week);
+  }
+}
+
+ExtDatePicker::ExtDatePicker(QWidget *parent, ExtDate dt, const char *name)
+  : QFrame(parent,name)
+{
+  init( dt );
+}
+
+ExtDatePicker::ExtDatePicker(QWidget *parent, ExtDate dt, const char *name, WFlags f)
+  : QFrame(parent,name, f)
+{
+  init( dt );
+}
+
+ExtDatePicker::ExtDatePicker( QWidget *parent, const char *name )
+  : QFrame(parent,name)
+{
+  init( ExtDate::currentDate() );
+}
+
+void ExtDatePicker::init( const ExtDate &dt )
+{
+  d = new ExtDatePickerPrivate();
+
+  d->calendar = new ExtCalendarSystemGregorian();
+
+  QBoxLayout * topLayout = new QVBoxLayout(this);
+
+  d->navigationLayout = new QHBoxLayout(topLayout);
+  d->navigationLayout->addStretch();
+  yearBackward = new QToolButton(this);
+  yearBackward->setAutoRaise(true);
+  d->navigationLayout->addWidget(yearBackward);
+  monthBackward = new QToolButton(this);
+  monthBackward ->setAutoRaise(true);
+  d->navigationLayout->addWidget(monthBackward);
+  d->navigationLayout->addSpacing(KDialog::spacingHint());
+
+  selectMonth = new QToolButton(this);
+  selectMonth ->setAutoRaise(true);
+  d->navigationLayout->addWidget(selectMonth);
+  selectYear = new QToolButton(this);
+  selectYear->setToggleButton(true);
+  selectYear->setAutoRaise(true);
+  d->navigationLayout->addWidget(selectYear);
+  d->navigationLayout->addSpacing(KDialog::spacingHint());
+
+  monthForward = new QToolButton(this);
+  monthForward ->setAutoRaise(true);
+  d->navigationLayout->addWidget(monthForward);
+  yearForward = new QToolButton(this);
+  yearForward ->setAutoRaise(true);
+  d->navigationLayout->addWidget(yearForward);
+  d->navigationLayout->addStretch();
+
+  line = new KLineEdit(this);
+  val = new ExtDateValidator(this);
+  table = new ExtDateTable(this);
+  fontsize = KGlobalSettings::generalFont().pointSize();
+  if (fontsize == -1)
+     fontsize = QFontInfo(KGlobalSettings::generalFont()).pointSize();
+
+  fontsize++; // Make a little bigger
+
+  d->selectWeek = new QComboBox(false, this);  // read only week selection
+  d->todayButton = new QToolButton(this);
+  d->todayButton->setIconSet(SmallIconSet("today"));
+
+  QToolTip::add(yearForward, i18n("Next year"));
+  QToolTip::add(yearBackward, i18n("Previous year"));
+  QToolTip::add(monthForward, i18n("Next month"));
+  QToolTip::add(monthBackward, i18n("Previous month"));
+  QToolTip::add(d->selectWeek, i18n("Select a week"));
+  QToolTip::add(selectMonth, i18n("Select a month"));
+  QToolTip::add(selectYear, i18n("Select a year"));
+  QToolTip::add(d->todayButton, i18n("Select the current day"));
+
+  // -----
+  setFontSize(fontsize);
+  line->setValidator(val);
+  line->installEventFilter( this );
+  if (  QApplication::reverseLayout() )
+  {
+      yearForward->setIconSet(BarIconSet(QString::fromLatin1("2leftarrow")));
+      yearBackward->setIconSet(BarIconSet(QString::fromLatin1("2rightarrow")));
+      monthForward->setIconSet(BarIconSet(QString::fromLatin1("1leftarrow")));
+      monthBackward->setIconSet(BarIconSet(QString::fromLatin1("1rightarrow")));
+  }
+  else
+  {
+      yearForward->setIconSet(BarIconSet(QString::fromLatin1("2rightarrow")));
+      yearBackward->setIconSet(BarIconSet(QString::fromLatin1("2leftarrow")));
+      monthForward->setIconSet(BarIconSet(QString::fromLatin1("1rightarrow")));
+      monthBackward->setIconSet(BarIconSet(QString::fromLatin1("1leftarrow")));
+  }
+  connect(table, SIGNAL(dateChanged(const ExtDate&)), SLOT(dateChangedSlot(const ExtDate&)));
+  connect(table, SIGNAL(tableClicked()), SLOT(tableClickedSlot()));
+  connect(monthForward, SIGNAL(clicked()), SLOT(monthForwardClicked()));
+  connect(monthBackward, SIGNAL(clicked()), SLOT(monthBackwardClicked()));
+  connect(yearForward, SIGNAL(clicked()), SLOT(yearForwardClicked()));
+  connect(yearBackward, SIGNAL(clicked()), SLOT(yearBackwardClicked()));
+  connect(d->selectWeek, SIGNAL(activated(int)), SLOT(weekSelected(int)));
+  connect(d->todayButton, SIGNAL(clicked()), SLOT(todayButtonClicked()));
+  connect(selectMonth, SIGNAL(clicked()), SLOT(selectMonthClicked()));
+  connect(selectYear, SIGNAL(toggled(bool)), SLOT(selectYearClicked()));
+  connect(line, SIGNAL(returnPressed()), SLOT(lineEnterPressed()));
+  table->setFocus();
+
+
+  topLayout->addWidget(table);
+
+  QBoxLayout * bottomLayout = new QHBoxLayout(topLayout);
+  bottomLayout->addWidget(d->todayButton);
+  bottomLayout->addWidget(line);
+  bottomLayout->addWidget(d->selectWeek);
+
+  table->setDate(dt);
+  dateChangedSlot(dt);  // needed because table emits changed only when newDate != oldDate
+}
+
+ExtDatePicker::~ExtDatePicker()
+{
+  delete d;
+}
+
+bool
+ExtDatePicker::eventFilter(QObject *o, QEvent *e )
+{
+   if ( e->type() == QEvent::KeyPress ) {
+      QKeyEvent *k = (QKeyEvent *)e;
+
+      if ( (k->key() == Qt::Key_Prior) ||
+           (k->key() == Qt::Key_Next)  ||
+           (k->key() == Qt::Key_Up)    ||
+           (k->key() == Qt::Key_Down) )
+       {
+          QApplication::sendEvent( table, e );
+          table->setFocus();
+          return true; // eat event
+       }
+   }
+   return QFrame::eventFilter( o, e );
+}
+
+void
+ExtDatePicker::resizeEvent(QResizeEvent* e)
+{
+  QWidget::resizeEvent(e);
+}
+
+void
+ExtDatePicker::dateChangedSlot(const ExtDate &date)
+{
+    kdDebug(298) << "ExtDatePicker::dateChangedSlot: date changed (" << date.year() << "/" << date.month() << "/" << date.day() << ")." << endl;
+
+
+//must remain commented unless ExtDate gets added to kdelibs
+//    const ExtCalendarSystem * calendar = KGlobal::locale()->calendar();
+
+//    line->setText(KGlobal::locale()->formatDate(date, true));
+    line->setText( date.toString("MM/dd/yyyy") );
+    selectMonth->setText(d->calendar->monthName(date, false));
+    fillWeeksCombo(date);
+
+    // calculate the item num in the week combo box; normalize selected day so as if 1.1. is the first day of the week
+    ExtDate firstDay(date.year(), 1, 1);
+    d->selectWeek->setCurrentItem((d->calendar->dayOfYear(date) + d->calendar->dayOfWeek(firstDay) - 2) / 7/*calendar->daysInWeek()*/);
+
+    selectYear->setText(d->calendar->yearString(date, false));
+
+    emit(dateChanged(date));
+}
+
+void
+ExtDatePicker::tableClickedSlot()
+{
+  kdDebug(298) << "ExtDatePicker::tableClickedSlot: table clicked." << endl;
+  emit(dateSelected(table->getDate()));
+  emit(tableClicked());
+}
+
+const ExtDate&
+ExtDatePicker::getDate() const
+{
+  return table->getDate();
+}
+
+const ExtDate &
+ExtDatePicker::date() const
+{
+    return table->getDate();
+}
+
+bool
+ExtDatePicker::setDate(const ExtDate& date)
+{
+    if(date.isValid())
+    {
+        table->setDate(date);  // this also emits dateChanged() which then calls our dateChangedSlot()
+        return true;
+    }
+    else
+    {
+        kdDebug(298) << "ExtDatePicker::setDate: refusing to set invalid date." << endl;
+        return false;
+    }
+}
+
+void
+ExtDatePicker::monthForwardClicked()
+{
+    ExtDate temp;
+//    temp = KGlobal::locale()->calendar()->addMonths( table->getDate(), 1 );
+    temp = d->calendar->addMonths( table->getDate(), 1 );
+    setDate( temp );
+}
+
+void
+ExtDatePicker::monthBackwardClicked()
+{
+    ExtDate temp;
+//    temp = KGlobal::locale()->calendar()->addMonths( table->getDate(), -1 );
+    temp = d->calendar->addMonths( table->getDate(), -1 );
+    setDate( temp );
+}
+
+void
+ExtDatePicker::yearForwardClicked()
+{
+    ExtDate temp;
+//    temp = KGlobal::locale()->calendar()->addYears( table->getDate(), 1 );
+    temp = d->calendar->addYears( table->getDate(), 1 );
+    setDate( temp );
+}
+
+void
+ExtDatePicker::yearBackwardClicked()
+{
+    ExtDate temp;
+//    temp = KGlobal::locale()->calendar()->addYears( table->getDate(), -1 );
+    temp = d->calendar->addYears( table->getDate(), -1 );
+    setDate( temp );
+}
+
+void ExtDatePicker::selectWeekClicked() {}  // ### in 3.2 obsolete; kept for binary compatibility
+
+void
+ExtDatePicker::weekSelected(int week)
+{
+//  const ExtCalendarSystem * calendar = KGlobal::locale()->calendar();
+
+  ExtDate date = table->getDate();
+  int year = d->calendar->year(date);
+
+  d->calendar->setYMD(date, year, 1, 1);  // first day of selected year
+
+  // calculate the first day in the selected week (day 1 is first day of week)
+  date = d->calendar->addDays(date, week * 7/*calendar->daysOfWeek()*/ -d->calendar->dayOfWeek(date) + 1);
+
+  setDate(date);
+}
+
+void
+ExtDatePicker::selectMonthClicked()
+{
+  // every year can have different month names (in some calendar systems)
+//  const ExtCalendarSystem * calendar = KGlobal::locale()->calendar();
+  ExtDate date = table->getDate();
+  int i, month, months = d->calendar->monthsInYear(date);
+
+  QPopupMenu popup(selectMonth);
+
+  for (i = 1; i <= months; i++)
+    popup.insertItem(d->calendar->monthName(i, d->calendar->year(date)), i);
+
+  popup.setActiveItem(d->calendar->month(date) - 1);
+
+  if ( (month = popup.exec(selectMonth->mapToGlobal(QPoint(0, 0)), d->calendar->month(date) - 1)) == -1 ) return;  // canceled
+
+  int day = d->calendar->day(date);
+  // ----- construct a valid date in this month:
+  //date.setYMD(date.year(), month, 1);
+  //date.setYMD(date.year(), month, QMIN(day, date.daysInMonth()));
+  d->calendar->setYMD(date, d->calendar->year(date), month,
+                   QMIN(day, d->calendar->daysInMonth(date)));
+  // ----- set this month
+  setDate(date);
+}
+
+void
+ExtDatePicker::selectYearClicked()
+{
+//  const ExtCalendarSystem * calendar = KGlobal::locale()->calendar();
+
+  if (selectYear->state() == QButton::Off)
+  {
+    return;
+  }
+
+  int year;
+  KPopupFrame* popup = new KPopupFrame(this);
+  ExtDateInternalYearSelector* picker = new ExtDateInternalYearSelector(popup);
+  // -----
+  picker->resize(picker->sizeHint());
+  popup->setMainWidget(picker);
+  connect(picker, SIGNAL(closeMe(int)), popup, SLOT(close(int)));
+  picker->setFocus();
+  if(popup->exec(selectYear->mapToGlobal(QPoint(0, selectMonth->height()))))
+    {
+      ExtDate date;
+      int day;
+      // -----
+      year=picker->getYear();
+      date=table->getDate();
+      day=d->calendar->day(date);
+      // ----- construct a valid date in this month:
+      //date.setYMD(year, date.month(), 1);
+      //date.setYMD(year, date.month(), QMIN(day, date.daysInMonth()));
+      d->calendar->setYMD(date, year, d->calendar->month(date),
+                       QMIN(day, d->calendar->daysInMonth(date)));
+      // ----- set this month
+      setDate(date);
+    } else {
+      KNotifyClient::beep();
+    }
+  delete popup;
+}
+
+void
+ExtDatePicker::setEnabled(bool enable)
+{
+  QWidget *widgets[]= {
+    yearForward, yearBackward, monthForward, monthBackward,
+    selectMonth, selectYear,
+    line, table, d->selectWeek, d->todayButton };
+  const int Size=sizeof(widgets)/sizeof(widgets[0]);
+  int count;
+  // -----
+  for(count=0; count<Size; ++count)
+    {
+      widgets[count]->setEnabled(enable);
+    }
+}
+
+void
+ExtDatePicker::lineEnterPressed()
+{
+  ExtDate temp;
+  // -----
+  if(val->date(line->text(), temp)==QValidator::Acceptable)
+    {
+        kdDebug(298) << "ExtDatePicker::lineEnterPressed: valid date entered." << endl;
+        emit(dateEntered(temp));
+        setDate(temp);
+    } else {
+      KNotifyClient::beep();
+      kdDebug(298) << "ExtDatePicker::lineEnterPressed: invalid date entered." << endl;
+    }
+}
+
+void
+ExtDatePicker::todayButtonClicked()
+{
+  setDate(ExtDate::currentDate());
+}
+
+QSize
+ExtDatePicker::sizeHint() const
+{
+  return QWidget::sizeHint();
+}
+
+void
+ExtDatePicker::setFontSize(int s)
+{
+  QWidget *buttons[]= {
+    // yearBackward,
+    // monthBackward,
+    selectMonth,
+    selectYear,
+    // monthForward,
+    // yearForward
+  };
+  const int NoOfButtons=sizeof(buttons)/sizeof(buttons[0]);
+  int count;
+  QFont font;
+  QRect r;
+  // -----
+  fontsize=s;
+  for(count=0; count<NoOfButtons; ++count)
+    {
+      font=buttons[count]->font();
+      font.setPointSize(s);
+      buttons[count]->setFont(font);
+    }
+  QFontMetrics metrics(selectMonth->fontMetrics());
+
+  for (int i = 1; ; ++i)
+    {
+      QString str = d->calendar->monthName(i,
+         d->calendar->year(table->getDate()), false);
+      if (str.isNull()) break;
+      r=metrics.boundingRect(str);
+      maxMonthRect.setWidth(QMAX(r.width(), maxMonthRect.width()));
+      maxMonthRect.setHeight(QMAX(r.height(),  maxMonthRect.height()));
+    }
+
+  QSize metricBound = style().sizeFromContents(QStyle::CT_ToolButton,
+                                               selectMonth,
+                                               maxMonthRect);
+  selectMonth->setMinimumSize(metricBound);
+
+  table->setFontSize(s);
+}
+
+void
+ExtDatePicker::setCloseButton( bool enable )
+{
+    if ( enable == (d->closeButton != 0L) )
+        return;
+
+    if ( enable ) {
+        d->closeButton = new QToolButton( this );
+        d->closeButton->setAutoRaise(true);
+        d->navigationLayout->addSpacing(KDialog::spacingHint());
+        d->navigationLayout->addWidget(d->closeButton);
+        QToolTip::add(d->closeButton, i18n("Close"));
+        d->closeButton->setPixmap( SmallIcon("remove") );
+        connect( d->closeButton, SIGNAL( clicked() ),
+                 topLevelWidget(), SLOT( close() ) );
+    }
+    else {
+        delete d->closeButton;
+        d->closeButton = 0L;
+    }
+
+    updateGeometry();
+}
+
+bool ExtDatePicker::hasCloseButton() const
+{
+    return (d->closeButton != 0L);
+}
+
+void ExtDatePicker::virtual_hook( int /*id*/, void* /*data*/ )
+{ /*BASE::virtual_hook( id, data );*/ }
+
diff --git a/extdate/extdatepicker.h b/extdate/extdatepicker.h
new file mode 100644 (file)
index 0000000..289333d
--- /dev/null
@@ -0,0 +1,255 @@
+/*  -*- C++ -*-
+    This file is part of the KDE libraries
+    Copyright (C) 1997 Tim D. Gilman (tdgilman@best.org)
+              (C) 1998-2001 Mirko Boehm (mirko@kde.org)
+              (C) 2004 Jason Harris (jharris@30doradus.org)
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Library General Public
+    License as published by the Free Software Foundation; either
+    version 2 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Library General Public License for more details.
+
+    You should have received a copy of the GNU Library General Public License
+    along with this library; see the file COPYING.LIB.  If not, write to
+    the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+    Boston, MA 02111-1307, USA.
+*/
+#ifndef EXTDATEPICKER_H
+#define EXTDATEPICKER_H
+
+#include <qframe.h>
+#include <kdemacros.h>
+
+#include "extdatetime.h"
+
+class QLineEdit;
+class QToolButton;
+class ExtDateValidator;
+class ExtDateTable;
+
+/**
+ * Provides a widget for calendar date input.
+ *
+ *     Different from the
+ *     previous versions, it now emits two types of signals, either
+ * dateSelected() or dateEntered() (see documentation for both
+ *     signals).
+ *
+ *     A line edit has been added in the newer versions to allow the user
+ *     to select a date directly by entering numbers like 19990101
+ *     or 990101.
+ *
+ * \image html kdatepicker.png "KDE Date Widget"
+ *
+ *     @version $Id$
+ *     @author Tim Gilman, Mirko Boehm
+ *
+ * @short A date selection widget.
+ **/
+class ExtDatePicker: public QFrame
+{
+  Q_OBJECT
+//  Q_PROPERTY( ExtDate date READ date WRITE setDate)
+  Q_PROPERTY( bool closeButton READ hasCloseButton WRITE setCloseButton )
+  Q_PROPERTY( int fontSize READ fontSize WRITE setFontSize )
+
+public:
+  /** The usual constructor.  The given date will be displayed
+   * initially.
+   **/
+  ExtDatePicker(QWidget *parent=0,
+             ExtDate=ExtDate::currentDate(),
+             const char *name=0);
+
+  /** The usual constructor.  The given date will be displayed
+   * initially.
+   * @since 3.1
+   **/
+  ExtDatePicker(QWidget *parent,
+             ExtDate,
+             const char *name,
+             WFlags f); // ### KDE 4.0: Merge
+
+  /**
+   * Standard qt widget constructor. The initial date will be the
+   * current date.
+   * @since 3.1
+   */
+  ExtDatePicker( QWidget *parent, const char *name );
+
+  /**
+   * The destructor.
+   **/
+  virtual ~ExtDatePicker();
+
+  /** The size hint for date pickers. The size hint recommends the
+   *   minimum size of the widget so that all elements may be placed
+   *  without clipping. This sometimes looks ugly, so when using the
+   *  size hint, try adding 28 to each of the reported numbers of
+   *  pixels.
+   **/
+  QSize sizeHint() const;
+
+  /**
+   * Sets the date.
+   *
+   *  @returns @p false and does not change anything
+   *      if the date given is invalid.
+   **/
+  bool setDate(const ExtDate&);
+
+  /**
+   * Returns the selected date.
+   * @deprecated
+   **/
+  const ExtDate& getDate() const KDE_DEPRECATED;
+
+  /**
+   * @returns the selected date.
+   */
+  const ExtDate &date() const;
+
+  /**
+   * Enables or disables the widget.
+   **/
+  void setEnabled(bool);
+
+  /**
+   * @returns the ExtDateTable widget child of this ExtDatePicker
+   * widget.
+   * @since 3.2
+   */
+  ExtDateTable *dateTable() const { return table; };
+
+  /**
+   * Sets the font size of the widgets elements.
+   **/
+  void setFontSize(int);
+  /**
+   * Returns the font size of the widget elements.
+   */
+  int fontSize() const
+    { return fontsize; }
+
+  /**
+   * By calling this method with @p enable = true, ExtDatePicker will show
+   * a little close-button in the upper button-row. Clicking the
+   * close-button will cause the ExtDatePicker's topLevelWidget()'s close()
+   * method being called. This is mostly useful for toplevel datepickers
+   * without a window manager decoration.
+   * @see hasCloseButton
+   * @since 3.1
+   */
+  void setCloseButton( bool enable );
+
+  /**
+   * @returns true if a ExtDatePicker shows a close-button.
+   * @see setCloseButton
+   * @since 3.1
+   */
+  bool hasCloseButton() const;
+
+protected:
+  /// to catch move keyEvents when QLineEdit has keyFocus
+  virtual bool eventFilter(QObject *o, QEvent *e );
+  /// the resize event
+  virtual void resizeEvent(QResizeEvent*);
+  /// the year forward button
+  QToolButton *yearForward;
+  /// the year backward button
+  QToolButton *yearBackward;
+  /// the month forward button
+  QToolButton *monthForward;
+  /// the month backward button
+  QToolButton *monthBackward;
+  /// the button for selecting the month directly
+  QToolButton *selectMonth;
+  /// the button for selecting the year directly
+  QToolButton *selectYear;
+  /// the line edit to enter the date directly
+  QLineEdit *line;
+  /// the validator for the line edit:
+  ExtDateValidator *val;
+  /// the date table
+  ExtDateTable *table;
+  /// the size calculated during resize events
+    //  QSize sizehint;
+  /// the widest month string in pixels:
+  QSize maxMonthRect;
+protected slots:
+  void dateChangedSlot(const ExtDate&);
+  void tableClickedSlot();
+  void monthForwardClicked();
+  void monthBackwardClicked();
+  void yearForwardClicked();
+  void yearBackwardClicked();
+  /**
+   * @since 3.1
+   * @deprecated in 3.2
+   */
+  void selectWeekClicked();
+  /**
+   * @since 3.1
+   */
+  void selectMonthClicked();
+  /**
+   * @since 3.1
+   */
+  void selectYearClicked();
+  /**
+   * @since 3.1
+   */
+  void lineEnterPressed();
+  /**
+   * @since 3.2
+   */
+  void todayButtonClicked();
+  /**
+   * @since 3.2
+   */
+  void weekSelected(int);
+
+signals:
+  /** This signal is emitted each time the selected date is changed.
+   *  Usually, this does not mean that the date has been entered,
+   *  since the date also changes, for example, when another month is
+   *  selected.
+   *  @see dateSelected
+   */
+  void dateChanged(const ExtDate&);
+  /** This signal is emitted each time a day has been selected by
+   *  clicking on the table (hitting a day in the current month). It
+   *  has the same meaning as dateSelected() in older versions of
+   *  ExtDatePicker.
+   */
+  void dateSelected(const ExtDate&);
+  /** This signal is emitted when enter is pressed and a VALID date
+   *  has been entered before into the line edit. Connect to both
+   *  dateEntered() and dateSelected() to receive all events where the
+   *  user really enters a date.
+   */
+  void dateEntered(const ExtDate&);
+  /** This signal is emitted when the day has been selected by
+   *  clicking on it in the table.
+   */
+  void tableClicked();
+
+private:
+  /// the font size for the widget
+  int fontsize;
+
+protected:
+  virtual void virtual_hook( int id, void* data );
+private:
+  void init( const ExtDate &dt );
+  void fillWeeksCombo(const ExtDate &date);
+  class ExtDatePickerPrivate;
+  ExtDatePickerPrivate *d;
+};
+
+#endif //  EXTDATEPICKER_H
diff --git a/extdate/extdatetbl.cpp b/extdate/extdatetbl.cpp
new file mode 100644 (file)
index 0000000..c774c6a
--- /dev/null
@@ -0,0 +1,976 @@
+/*  -*- C++ -*-
+    This file is part of the KDE libraries
+    Copyright (C) 1997 Tim D. Gilman (tdgilman@best.org)
+              (C) 1998-2001 Mirko Boehm (mirko@kde.org)
+              (C) 2004 Jason Harris (jharris@30doradus.org)
+
+    These classes has been derived from those in kdatetbl.[h|cpp].
+    The only differences are adaptations to use ExtDate instead of QDate,
+    to allow for more remote dates.  These changes by Jason Harris.
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Library General Public
+    License as published by the Free Software Foundation; either
+    version 2 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Library General Public License for more details.
+
+    You should have received a copy of the GNU Library General Public License
+    along with this library; see the file COPYING.LIB.  If not, write to
+    the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+    Boston, MA 02111-1307, USA.
+*/
+
+/////////////////// ExtDateTable widget class //////////////////////
+//
+// Copyright (C) 1997 Tim D. Gilman
+//           (C) 1998-2001 Mirko Boehm
+// Written using Qt (http://www.troll.no) for the
+// KDE project (http://www.kde.org)
+//
+// This is a support class for the ExtDatePicker class.  It just
+// draws the calender table without titles, but could theoretically
+// be used as a standalone.
+//
+// When a date is selected by the user, it emits a signal:
+//      dateSelected(ExtDate)
+
+#include "extcalendarsystem.h"
+#include "extcalendarsystemgregorian.h"
+//#include "extdatepicker.h"
+#include "extdatetbl.h"
+#include "extdatetime.h"
+
+#include <kconfig.h>
+#include <kglobal.h>
+#include <kglobalsettings.h>
+#include <kapplication.h>
+#include <klocale.h>
+#include <kdebug.h>
+#include <knotifyclient.h>
+#include "kpopupmenu.h"
+#include <qdatetime.h>
+#include <qstring.h>
+#include <qpen.h>
+#include <qpainter.h>
+#include <qdialog.h>
+#include <qdict.h>
+#include <assert.h>
+
+
+class ExtDateTable::ExtDateTablePrivate
+{
+public:
+   ExtDateTablePrivate()
+   {
+      popupMenuEnabled=false;
+      useCustomColors=false;
+      calendar = new ExtCalendarSystemGregorian();
+
+   }
+
+   ~ExtDateTablePrivate()
+   {
+      delete calendar;
+   }
+
+   bool popupMenuEnabled;
+   bool useCustomColors;
+
+   struct DatePaintingMode
+   {
+     QColor fgColor;
+     QColor bgColor;
+     BackgroundMode bgMode;
+   };
+   QDict <DatePaintingMode> customPaintingModes;
+   ExtCalendarSystem *calendar;
+};
+
+
+ExtDateValidator::ExtDateValidator(QWidget* parent, const char* name)
+    : QValidator(parent, name)
+{
+}
+
+QValidator::State
+ExtDateValidator::validate(QString& text, int&) const
+{
+  ExtDate temp;
+  // ----- everything is tested in date():
+  return date(text, temp);
+}
+
+QValidator::State
+ExtDateValidator::date(const QString& text, ExtDate& ed) const
+{
+       //FIXME: Can't uncomment unless ExtDate is adopted by KDE
+       //ExtDate tmp = KGlobal::locale()->readDate(text);
+  ExtDate tmp = ExtDate::fromString( text );
+
+  if (!tmp.isNull())
+    {
+      ed = tmp;
+      return Acceptable;
+    } else
+      return Valid;
+}
+
+void
+ExtDateValidator::fixup( QString& ) const
+{
+
+}
+
+ExtDateTable::ExtDateTable(QWidget *parent, ExtDate date_, const char* name, WFlags f)
+  : QGridView(parent, name, f)
+{
+  d = new ExtDateTablePrivate;
+  setFontSize(10);
+  if(!date_.isValid())
+    {
+      kdDebug() << "ExtDateTable ctor: WARNING: Given date is invalid, using current date." << endl;
+      date_=ExtDate::currentDate();
+    }
+  setFocusPolicy( QWidget::StrongFocus );
+  setNumRows(7); // 6 weeks max + headline
+  setNumCols(7); // 7 days a week
+  setHScrollBarMode(AlwaysOff);
+  setVScrollBarMode(AlwaysOff);
+  viewport()->setEraseColor(KGlobalSettings::baseColor());
+  setDate(date_); // this initializes firstday, numdays, numDaysPrevMonth
+}
+
+ExtDateTable::~ExtDateTable()
+{
+  delete d;
+}
+
+int ExtDateTable::posFromDate( const ExtDate &dt )
+{
+//FIXME: Can't uncomment unless ExtDate is added to kdelibs
+//  const ExtCalendarSystem * calendar = KGlobal::locale()->calendar();
+//  const int firstWeekDay = KGlobal::locale()->weekStartDay();
+
+  const int firstWeekDay = 7;
+
+  int pos = d->calendar->day( dt );
+  int offset = (firstday - firstWeekDay + 7) % 7;
+  // make sure at least one day of the previous month is visible.
+  // adjust this <1 if more days should be forced visible:
+  if ( offset < 1 ) offset += 7;
+  return pos + offset;
+}
+
+ExtDate ExtDateTable::dateFromPos( int pos )
+{
+  ExtDate pCellDate;
+
+//FIXME: Can't uncomment unless ExtDate is added to kdelibs
+//  const ExtCalendarSystem * calendar = KGlobal::locale()->calendar();
+//  int firstWeekDay = KGlobal::locale()->weekStartDay();
+  const int firstWeekDay = 7;
+
+  d->calendar->setYMD(pCellDate, d->calendar->year(date), d->calendar->month(date), 1);
+
+  int offset = (firstday - firstWeekDay + 7) % 7;
+  // make sure at least one day of the previous month is visible.
+  // adjust this <1 if more days should be forced visible:
+  if ( offset < 1 ) offset += 7;
+  pCellDate = d->calendar->addDays( pCellDate, pos - offset );
+  return pCellDate;
+}
+
+void
+ExtDateTable::paintCell(QPainter *painter, int row, int col)
+{
+//FIXME: Can't uncomment unless ExtDate is added to kdelibs
+//  const ExtCalendarSystem * calendar = KGlobal::locale()->calendar();
+//  int firstWeekDay = KGlobal::locale()->weekStartDay();
+  const int firstWeekDay = 7;
+
+  QRect rect;
+  QString text;
+  QPen pen;
+  int w=cellWidth();
+  int h=cellHeight();
+  QFont font=KGlobalSettings::generalFont();
+  // -----
+
+  if(row==0)
+    { // we are drawing the headline
+      font.setBold(true);
+      painter->setFont(font);
+      bool normalday = true;
+      int daynum = ( col+firstWeekDay < 8 ) ? col+firstWeekDay :
+                                              col+firstWeekDay-7;
+      if ( daynum == d->calendar->weekDayOfPray() ||
+         ( daynum == 6 && d->calendar->calendarName() == "gregorian" ) )
+          normalday=false;
+
+                       QBrush brushTitle();
+                       QBrush brushInvertTitle(colorGroup().base());
+                       QColor titleColor(isEnabled()?( KGlobalSettings::activeTitleColor() ):( KGlobalSettings::inactiveTitleColor() ) );
+                       QColor textColor(isEnabled()?( KGlobalSettings::activeTextColor() ):( KGlobalSettings::inactiveTextColor() ) );
+      if (!normalday)
+        {
+          painter->setPen(textColor);
+          painter->setBrush(textColor);
+          painter->drawRect(0, 0, w, h);
+          painter->setPen(titleColor);
+        } else {
+          painter->setPen(titleColor);
+          painter->setBrush(titleColor);
+          painter->drawRect(0, 0, w, h);
+          painter->setPen(textColor);
+        }
+      painter->drawText(0, 0, w, h-1, AlignCenter,
+                        d->calendar->weekDayName(daynum, true), -1, &rect);
+      painter->setPen(colorGroup().text());
+      painter->moveTo(0, h-1);
+      painter->lineTo(w-1, h-1);
+      // ----- draw the weekday:
+    } else {
+      bool paintRect=true;
+      painter->setFont(font);
+      int pos=7*(row-1)+col;
+
+      ExtDate pCellDate = dateFromPos( pos );
+      // First day of month
+      text = d->calendar->dayString(pCellDate, true);
+      if( d->calendar->month(pCellDate) != d->calendar->month(date) )
+        { // we are either
+          // Â° painting a day of the previous month or
+          // Â° painting a day of the following month
+          // TODO: don't hardcode gray here! Use a color with less contrast to the background than normal text.
+          painter->setPen( colorGroup().mid() );
+//          painter->setPen(gray);
+        } else { // paint a day of the current month
+          if ( d->useCustomColors )
+          {
+            ExtDateTablePrivate::DatePaintingMode *mode=d->customPaintingModes[pCellDate.toString()];
+            if (mode)
+            {
+              if (mode->bgMode != NoBgMode)
+              {
+                QBrush oldbrush=painter->brush();
+                painter->setBrush( mode->bgColor );
+                switch(mode->bgMode)
+                {
+                  case(CircleMode) : painter->drawEllipse(0,0,w,h);break;
+                  case(RectangleMode) : painter->drawRect(0,0,w,h);break;
+                  case(NoBgMode) : // Should never be here, but just to get one
+                                   // less warning when compiling
+                  default: break;
+                }
+                painter->setBrush( oldbrush );
+                paintRect=false;
+              }
+              painter->setPen( mode->fgColor );
+            } else
+              painter->setPen(colorGroup().text());
+          } else //if ( firstWeekDay < 4 ) // <- this doesn' make sense at all!
+          painter->setPen(colorGroup().text());
+        }
+
+      pen=painter->pen();
+      int offset=firstday-firstWeekDay;
+      if(offset<1)
+        offset+=7;
+      int dy = d->calendar->day(date);
+      if( ((offset+dy) == (pos+1)) && hasFocus())
+        {
+           // draw the currently selected date
+           painter->setPen(colorGroup().highlight());
+           painter->setBrush(colorGroup().highlight());
+           pen=colorGroup().highlightedText();
+        } else {
+          painter->setBrush(paletteBackgroundColor());
+          painter->setPen(paletteBackgroundColor());
+//          painter->setBrush(colorGroup().base());
+//          painter->setPen(colorGroup().base());
+        }
+
+      if ( pCellDate == ExtDate::currentDate() )
+      {
+         painter->setPen(colorGroup().text());
+      }
+
+      if ( paintRect ) painter->drawRect(0, 0, w, h);
+      painter->setPen(pen);
+      painter->drawText(0, 0, w, h, AlignCenter, text, -1, &rect);
+    }
+  if(rect.width()>maxCell.width()) maxCell.setWidth(rect.width());
+  if(rect.height()>maxCell.height()) maxCell.setHeight(rect.height());
+}
+
+void
+ExtDateTable::keyPressEvent( QKeyEvent *e )
+{
+//FIXME: Can't uncomment unless ExtDate is added to kdelibs
+//    const ExtCalendarSystem * calendar = KGlobal::locale()->calendar();
+
+    ExtDate temp = date;
+
+    switch( e->key() ) {
+    case Key_Prior:
+        temp = d->calendar->addMonths( date, -1 );
+        setDate(temp);
+        return;
+    case Key_Next:
+        temp = d->calendar->addMonths( date, 1 );
+        setDate(temp);
+        return;
+    case Key_Up:
+        if ( d->calendar->day(date) > 7 ) {
+            setDate(date.addDays(-7));
+            return;
+        }
+        break;
+    case Key_Down:
+        if ( d->calendar->day(date) <= d->calendar->daysInMonth(date)-7 ) {
+            setDate(date.addDays(7));
+            return;
+        }
+        break;
+    case Key_Left:
+        if ( d->calendar->day(date) > 1 ) {
+            setDate(date.addDays(-1));
+            return;
+        }
+        break;
+    case Key_Right:
+        if ( d->calendar->day(date) < d->calendar->daysInMonth(date) ) {
+            setDate(date.addDays(1));
+            return;
+        }
+        break;
+    case Key_Minus:
+        setDate(date.addDays(-1));
+        return;
+    case Key_Plus:
+        setDate(date.addDays(1));
+        return;
+    case Key_N:
+        setDate(ExtDate::currentDate());
+        return;
+    case Key_Return:
+    case Key_Enter:
+        emit tableClicked();
+        return;
+    default:
+        break;
+    }
+
+    KNotifyClient::beep();
+}
+
+void
+ExtDateTable::viewportResizeEvent(QResizeEvent * e)
+{
+  QGridView::viewportResizeEvent(e);
+
+  setCellWidth(viewport()->width()/7);
+  setCellHeight(viewport()->height()/7);
+}
+
+void
+ExtDateTable::setFontSize(int size)
+{
+//FIXME: Can't uncomment unless ExtDate is added to kdelibs
+//  const ExtCalendarSystem * calendar = KGlobal::locale()->calendar();
+
+  int count;
+  QFontMetrics metrics(fontMetrics());
+  QRect rect;
+  // ----- store rectangles:
+  fontsize=size;
+  // ----- find largest day name:
+  maxCell.setWidth(0);
+  maxCell.setHeight(0);
+  for(count=0; count<7; ++count)
+    {
+      rect=metrics.boundingRect(d->calendar->weekDayName(count+1, true));
+      maxCell.setWidth(QMAX(maxCell.width(), rect.width()));
+      maxCell.setHeight(QMAX(maxCell.height(), rect.height()));
+    }
+  // ----- compare with a real wide number and add some space:
+  rect=metrics.boundingRect(QString::fromLatin1("88"));
+  maxCell.setWidth(QMAX(maxCell.width()+2, rect.width()));
+  maxCell.setHeight(QMAX(maxCell.height()+4, rect.height()));
+}
+
+void
+ExtDateTable::wheelEvent ( QWheelEvent * e )
+{
+    setDate(date.addMonths( -(int)(e->delta()/120)) );
+    e->accept();
+}
+
+void
+ExtDateTable::contentsMousePressEvent(QMouseEvent *e)
+{
+
+  if(e->type()!=QEvent::MouseButtonPress)
+    { // the ExtDatePicker only reacts on mouse press events:
+      return;
+    }
+  if(!isEnabled())
+    {
+      KNotifyClient::beep();
+      return;
+    }
+
+  // -----
+  int row, col, pos, temp;
+  QPoint mouseCoord;
+  // -----
+  mouseCoord = e->pos();
+  row=rowAt(mouseCoord.y());
+  col=columnAt(mouseCoord.x());
+  if(row<1 || col<0)
+    { // the user clicked on the frame of the table
+      return;
+    }
+
+  // Rows and columns are zero indexed.  The (row - 1) below is to avoid counting
+  // the row with the days of the week in the calculation.
+
+  // old selected date:
+  temp = posFromDate( date );
+  // new position and date
+  pos = (7 * (row - 1)) + col;
+  ExtDate clickedDate = dateFromPos( pos );
+
+  // set the new date. If it is in the previous or next month, the month will
+  // automatically be changed, no need to do that manually...
+  setDate( clickedDate );
+
+  // call updateCell on the old and new selection. If setDate switched to a different
+  // month, these cells will be painted twice, but that's no problem.
+  updateCell( temp/7+1, temp%7 );
+  updateCell( row, col );
+
+  emit tableClicked();
+
+  if (  e->button() == Qt::RightButton && d->popupMenuEnabled )
+  {
+        KPopupMenu *menu = new KPopupMenu();
+
+//FIXME: Uncomment the following line (and remove the one after it)
+//       if ExtDate is added to kdelibs
+//        menu->insertTitle( KGlobal::locale()->formatDate(clickedDate) );
+        menu->insertTitle( clickedDate.toString() );
+
+        emit aboutToShowContextMenu( menu, clickedDate );
+        menu->popup(e->globalPos());
+  }
+}
+
+bool
+ExtDateTable::setDate(const ExtDate& date_)
+{
+  bool changed=false;
+  ExtDate temp;
+  // -----
+  if(!date_.isValid())
+    {
+      kdDebug() << "ExtDateTable::setDate: refusing to set invalid date." << endl;
+      return false;
+    }
+  if(date!=date_)
+    {
+      emit(dateChanged(date, date_));
+      date=date_;
+      emit(dateChanged(date));
+      changed=true;
+    }
+
+//FIXME: Can't uncomment the following unless ExtDate is moved to kdelibs
+//  const ExtCalendarSystem * calendar = KGlobal::locale()->calendar();
+
+  d->calendar->setYMD(temp, d->calendar->year(date), d->calendar->month(date), 1);
+  //temp.setYMD(date.year(), date.month(), 1);
+  //kdDebug() << "firstDayInWeek: " << temp.toString() << endl;
+  firstday=temp.dayOfWeek();
+  numdays=d->calendar->daysInMonth(date);
+
+  temp = d->calendar->addMonths(temp, -1);
+  numDaysPrevMonth=d->calendar->daysInMonth(temp);
+  if(changed)
+    {
+      repaintContents(false);
+    }
+  return true;
+}
+
+const ExtDate&
+ExtDateTable::getDate() const
+{
+  return date;
+}
+
+// what are those repaintContents() good for? (pfeiffer)
+void ExtDateTable::focusInEvent( QFocusEvent *e )
+{
+//    repaintContents(false);
+    QGridView::focusInEvent( e );
+}
+
+void ExtDateTable::focusOutEvent( QFocusEvent *e )
+{
+//    repaintContents(false);
+    QGridView::focusOutEvent( e );
+}
+
+QSize
+ExtDateTable::sizeHint() const
+{
+  if(maxCell.height()>0 && maxCell.width()>0)
+    {
+      return QSize(maxCell.width()*numCols()+2*frameWidth(),
+             (maxCell.height()+2)*numRows()+2*frameWidth());
+    } else {
+      kdDebug() << "ExtDateTable::sizeHint: obscure failure - " << endl;
+      return QSize(-1, -1);
+    }
+}
+
+void ExtDateTable::setPopupMenuEnabled( bool enable )
+{
+   d->popupMenuEnabled=enable;
+}
+
+bool ExtDateTable::popupMenuEnabled() const
+{
+   return d->popupMenuEnabled;
+}
+
+void ExtDateTable::setCustomDatePainting(const ExtDate &date, const QColor &fgColor, BackgroundMode bgMode, const QColor &bgColor)
+{
+    if (!fgColor.isValid())
+    {
+        unsetCustomDatePainting( date );
+        return;
+    }
+
+    ExtDateTablePrivate::DatePaintingMode *mode=new ExtDateTablePrivate::DatePaintingMode;
+    mode->bgMode=bgMode;
+    mode->fgColor=fgColor;
+    mode->bgColor=bgColor;
+
+    d->customPaintingModes.replace( date.toString(), mode );
+    d->useCustomColors=true;
+    update();
+}
+
+void ExtDateTable::unsetCustomDatePainting( const ExtDate &date )
+{
+    d->customPaintingModes.remove( date.toString() );
+}
+
+ExtDateInternalWeekSelector::ExtDateInternalWeekSelector
+(QWidget* parent, const char* name)
+  : KLineEdit(parent, name),
+    val(new QIntValidator(this)),
+    result(0)
+{
+  QFont font;
+  // -----
+  font=KGlobalSettings::generalFont();
+  setFont(font);
+  setFrameStyle(QFrame::NoFrame);
+  setValidator(val);
+  connect(this, SIGNAL(returnPressed()), SLOT(weekEnteredSlot()));
+}
+
+void
+ExtDateInternalWeekSelector::weekEnteredSlot()
+{
+  bool ok;
+  int week;
+  // ----- check if this is a valid week:
+  week=text().toInt(&ok);
+  if(!ok)
+    {
+      KNotifyClient::beep();
+      return;
+    }
+  result=week;
+  emit(closeMe(1));
+}
+
+int
+ExtDateInternalWeekSelector::getWeek()
+{
+  return result;
+}
+
+void
+ExtDateInternalWeekSelector::setWeek(int week)
+{
+  QString temp;
+  // -----
+  temp.setNum(week);
+  setText(temp);
+}
+
+void
+ExtDateInternalWeekSelector::setMaxWeek(int max)
+{
+  val->setRange(1, max);
+}
+
+// ### CFM To avoid binary incompatibility.
+//     In future releases, remove this and replace by  a ExtDate
+//     private member, needed in ExtDateInternalMonthPicker::paintCell
+class ExtDateInternalMonthPicker::ExtDateInternalMonthPrivate {
+public:
+        ExtDateInternalMonthPrivate (int y, int m, int d)
+        : year(y), month(m), day(d)
+        { calendar = new ExtCalendarSystemGregorian(); }
+        ~ExtDateInternalMonthPrivate()
+        { delete calendar; }
+
+        ExtCalendarSystem *calendar;
+        int year;
+        int month;
+        int day;
+};
+
+ExtDateInternalMonthPicker::~ExtDateInternalMonthPicker() {
+   delete d;
+}
+
+ExtDateInternalMonthPicker::ExtDateInternalMonthPicker
+(const ExtDate & date, QWidget* parent, const char* name)
+  : QGridView(parent, name),
+    result(0) // invalid
+{
+//FIXME: Can't uncomment the following unless ExtDate is moved to kdelibs
+//  ExtCalendarSystem *calendar = KGlobal::locale()->calendar();
+
+  QRect rect;
+  QFont font;
+  // -----
+  activeCol = -1;
+  activeRow = -1;
+  font=KGlobalSettings::generalFont();
+  setFont(font);
+  setHScrollBarMode(AlwaysOff);
+  setVScrollBarMode(AlwaysOff);
+  setFrameStyle(QFrame::NoFrame);
+  setNumCols(3);
+  d = new ExtDateInternalMonthPrivate(date.year(), date.month(), date.day());
+  // For monthsInYear != 12
+  setNumRows( (d->calendar->monthsInYear(date) + 2) / 3);
+  // enable to find drawing failures:
+  // setTableFlags(Tbl_clipCellPainting);
+  viewport()->setEraseColor(KGlobalSettings::baseColor()); // for consistency with the datepicker
+  // ----- find the preferred size
+  //       (this is slow, possibly, but unfortunately it is needed here):
+  QFontMetrics metrics(font);
+  for(int i = 1; ; ++i)
+    {
+      QString str = d->calendar->monthName(i,
+         d->calendar->year(date), false);
+      if (str.isNull()) break;
+      rect=metrics.boundingRect(str);
+      if(max.width()<rect.width()) max.setWidth(rect.width());
+      if(max.height()<rect.height()) max.setHeight(rect.height());
+    }
+}
+
+QSize
+ExtDateInternalMonthPicker::sizeHint() const
+{
+  return QSize((max.width()+6)*numCols()+2*frameWidth(),
+         (max.height()+6)*numRows()+2*frameWidth());
+}
+
+int
+ExtDateInternalMonthPicker::getResult() const
+{
+  return result;
+}
+
+void
+ExtDateInternalMonthPicker::setupPainter(QPainter *p)
+{
+  p->setPen(KGlobalSettings::textColor());
+}
+
+void
+ExtDateInternalMonthPicker::viewportResizeEvent(QResizeEvent*)
+{
+  setCellWidth(width() / numCols());
+  setCellHeight(height() / numRows());
+}
+
+void
+ExtDateInternalMonthPicker::paintCell(QPainter* painter, int row, int col)
+{
+  int index;
+  QString text;
+  // ----- find the number of the cell:
+  index=3*row+col+1;
+  text=d->calendar->monthName(index,
+    d->calendar->year(ExtDate(d->year, d->month,
+    d->day)), false);
+  painter->drawText(0, 0, cellWidth(), cellHeight(), AlignCenter, text);
+  if ( activeCol == col && activeRow == row )
+      painter->drawRect( 0, 0, cellWidth(), cellHeight() );
+}
+
+void
+ExtDateInternalMonthPicker::contentsMousePressEvent(QMouseEvent *e)
+{
+  if(!isEnabled() || e->button() != LeftButton)
+    {
+      KNotifyClient::beep();
+      return;
+    }
+  // -----
+  int row, col;
+  QPoint mouseCoord;
+  // -----
+  mouseCoord = e->pos();
+  row=rowAt(mouseCoord.y());
+  col=columnAt(mouseCoord.x());
+
+  if(row<0 || col<0)
+    { // the user clicked on the frame of the table
+      activeCol = -1;
+      activeRow = -1;
+    } else {
+      activeCol = col;
+      activeRow = row;
+      updateCell( row, col /*, false */ );
+  }
+}
+
+void
+ExtDateInternalMonthPicker::contentsMouseMoveEvent(QMouseEvent *e)
+{
+  if (e->state() & LeftButton)
+    {
+      int row, col;
+      QPoint mouseCoord;
+      // -----
+      mouseCoord = e->pos();
+      row=rowAt(mouseCoord.y());
+      col=columnAt(mouseCoord.x());
+      int tmpRow = -1, tmpCol = -1;
+      if(row<0 || col<0)
+        { // the user clicked on the frame of the table
+          if ( activeCol > -1 )
+            {
+              tmpRow = activeRow;
+              tmpCol = activeCol;
+            }
+          activeCol = -1;
+          activeRow = -1;
+        } else {
+          bool differentCell = (activeRow != row || activeCol != col);
+          if ( activeCol > -1 && differentCell)
+            {
+              tmpRow = activeRow;
+              tmpCol = activeCol;
+            }
+          if ( differentCell)
+            {
+              activeRow = row;
+              activeCol = col;
+              updateCell( row, col /*, false */ ); // mark the new active cell
+            }
+        }
+      if ( tmpRow > -1 ) // repaint the former active cell
+          updateCell( tmpRow, tmpCol /*, true */ );
+    }
+}
+
+void
+ExtDateInternalMonthPicker::contentsMouseReleaseEvent(QMouseEvent *e)
+{
+  if(!isEnabled())
+    {
+      return;
+    }
+  // -----
+  int row, col, pos;
+  QPoint mouseCoord;
+  // -----
+  mouseCoord = e->pos();
+  row=rowAt(mouseCoord.y());
+  col=columnAt(mouseCoord.x());
+  if(row<0 || col<0)
+    { // the user clicked on the frame of the table
+      emit(closeMe(0));
+    }
+
+  pos=3*row+col+1;
+  result=pos;
+  emit(closeMe(1));
+}
+
+
+
+ExtDateInternalYearSelector::ExtDateInternalYearSelector
+(QWidget* parent, const char* name)
+  : QLineEdit(parent, name),
+    val(new QIntValidator(this)),
+    result(0),
+    d(new ExtDateInternalYearPrivate())
+{
+  QFont font;
+  // -----
+  font=KGlobalSettings::generalFont();
+  setFont(font);
+  setFrameStyle(QFrame::NoFrame);
+  // set year limits (perhaps we should get rid of limits altogether)
+  //there si also a year limit in ExtCalendarSystemGregorian...
+  val->setRange(-50000, 50000);
+  setValidator(val);
+  connect(this, SIGNAL(returnPressed()), SLOT(yearEnteredSlot()));
+}
+
+ExtDateInternalYearSelector::~ExtDateInternalYearSelector() {
+       delete val;
+       delete d;
+}
+
+void
+ExtDateInternalYearSelector::yearEnteredSlot()
+{
+  bool ok;
+  int year;
+  ExtDate date;
+  // ----- check if this is a valid year:
+  year=text().toInt(&ok);
+  if(!ok)
+    {
+      KNotifyClient::beep();
+      return;
+    }
+  //date.setYMD(year, 1, 1);
+  d->calendar->setYMD(date, year, 1, 1);
+  if(!date.isValid())
+    {
+      KNotifyClient::beep();
+      return;
+    }
+  result=year;
+  emit(closeMe(1));
+}
+
+int
+ExtDateInternalYearSelector::getYear()
+{
+  return result;
+}
+
+void
+ExtDateInternalYearSelector::setYear(int year)
+{
+  QString temp;
+  // -----
+  temp.setNum(year);
+  setText(temp);
+}
+
+KPopupFrame::KPopupFrame(QWidget* parent, const char*  name)
+  : QFrame(parent, name, WType_Popup),
+    result(0), // rejected
+    main(0)
+{
+  setFrameStyle(QFrame::Box|QFrame::Raised);
+  setMidLineWidth(2);
+}
+
+void
+KPopupFrame::keyPressEvent(QKeyEvent* e)
+{
+  if(e->key()==Key_Escape)
+    {
+      result=0; // rejected
+      qApp->exit_loop();
+    }
+}
+
+void
+KPopupFrame::close(int r)
+{
+  result=r;
+  qApp->exit_loop();
+}
+
+void
+KPopupFrame::setMainWidget(QWidget* m)
+{
+  main=m;
+  if(main!=0)
+    {
+      resize(main->width()+2*frameWidth(), main->height()+2*frameWidth());
+    }
+}
+
+void
+KPopupFrame::resizeEvent(QResizeEvent*)
+{
+  if(main!=0)
+    {
+      main->setGeometry(frameWidth(), frameWidth(),
+          width()-2*frameWidth(), height()-2*frameWidth());
+    }
+}
+
+void
+KPopupFrame::popup(const QPoint &pos)
+{
+  // Make sure the whole popup is visible.
+  QRect d = KGlobalSettings::desktopGeometry(pos);
+
+  int x = pos.x();
+  int y = pos.y();
+  int w = width();
+  int h = height();
+  if (x+w > d.x()+d.width())
+    x = d.width() - w;
+  if (y+h > d.y()+d.height())
+    y = d.height() - h;
+  if (x < d.x())
+    x = 0;
+  if (y < d.y())
+    y = 0;
+
+  // Pop the thingy up.
+  move(x, y);
+  show();
+}
+
+int
+KPopupFrame::exec(QPoint pos)
+{
+  popup(pos);
+  repaint();
+  qApp->enter_loop();
+  hide();
+  return result;
+}
+
+int
+KPopupFrame::exec(int x, int y)
+{
+  return exec(QPoint(x, y));
+}
+
+void KPopupFrame::virtual_hook( int, void* )
+{ /*BASE::virtual_hook( id, data );*/ }
+
+void ExtDateTable::virtual_hook( int, void* )
+{ /*BASE::virtual_hook( id, data );*/ }
+
+#include "extdatetbl.moc"
diff --git a/extdate/extdatetbl.h b/extdate/extdatetbl.h
new file mode 100644 (file)
index 0000000..7da14b9
--- /dev/null
@@ -0,0 +1,429 @@
+/*  -*- C++ -*-
+    This file is part of the KDE libraries
+    Copyright (C) 1997 Tim D. Gilman (tdgilman@best.org)
+              (C) 1998-2001 Mirko Boehm (mirko@kde.org)
+              (C) 2004 Jason Harris (jharris@30doradus.org)
+
+    These classes has been derived from those in kdatetbl.[h|cpp].
+    The only differences are adaptations to use ExtDate instead of QDate,
+    to allow for more remote dates.  These changes by Jason Harris.
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Library General Public
+    License as published by the Free Software Foundation; either
+    version 2 of the License, or (at your option) any later version.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Library General Public License for more details.
+
+    You should have received a copy of the GNU Library General Public License
+    along with this library; see the file COPYING.LIB.  If not, write to
+    the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+    Boston, MA 02111-1307, USA.
+*/
+#ifndef EXTDATETBL_H
+#define EXTDATETBL_H
+
+#include <qvalidator.h>
+#include <qgridview.h>
+#include <klineedit.h>
+#include <qcolor.h>
+#include "extdatetime.h"
+#include "extcalendarsystemgregorian.h"
+
+class KPopupMenu;
+
+/** Week selection widget.
+* @internal
+* @version $Id$
+* @author Stephan Binner
+*/
+class ExtDateInternalWeekSelector : public KLineEdit
+{
+  Q_OBJECT
+protected:
+  QIntValidator *val;
+  int result;
+public slots:
+  void weekEnteredSlot();
+  void setMaxWeek(int max);
+signals:
+  void closeMe(int);
+public:
+  ExtDateInternalWeekSelector( QWidget* parent=0, const char* name=0);
+  int getWeek();
+  void setWeek(int week);
+
+private:
+  class ExtDateInternalWeekPrivate;
+  ExtDateInternalWeekPrivate *d;
+};
+
+/**
+* A table containing month names. It is used to pick a month directly.
+* @internal
+* @version $Id$
+* @author Tim Gilman, Mirko Boehm
+*/
+class ExtDateInternalMonthPicker : public QGridView
+{
+  Q_OBJECT
+protected:
+  /**
+   * Store the month that has been clicked [1..12].
+   */
+  int result;
+  /**
+   * the cell under mouse cursor when LBM is pressed
+   */
+  short int activeCol;
+  short int activeRow;
+  /**
+   * Contains the largest rectangle needed by the month names.
+   */
+  QRect max;
+signals:
+  /**
+   * This is send from the mouse click event handler.
+   */
+  void closeMe(int);
+public:
+  /**
+   * The constructor.
+   */
+  ExtDateInternalMonthPicker(const ExtDate& date, QWidget* parent, const char* name=0);
+  /**
+   * The destructor.
+   */
+  ~ExtDateInternalMonthPicker();
+  /**
+   * The size hint.
+   */
+  QSize sizeHint() const;
+  /**
+   * Return the result. 0 means no selection (reject()), 1..12 are the
+   * months.
+   */
+  int getResult() const;
+protected:
+  /**
+   * Set up the painter.
+   */
+  void setupPainter(QPainter *p);
+  /**
+   * The resize event.
+   */
+  virtual void viewportResizeEvent(QResizeEvent*);
+  /**
+   * Paint a cell. This simply draws the month names in it.
+   */
+  virtual void paintCell(QPainter* painter, int row, int col);
+  /**
+   * Catch mouse click and move events to paint a rectangle around the item.
+   */
+  virtual void contentsMousePressEvent(QMouseEvent *e);
+  virtual void contentsMouseMoveEvent(QMouseEvent *e);
+  /**
+   * Emit monthSelected(int) when a cell has been released.
+   */
+  virtual void contentsMouseReleaseEvent(QMouseEvent *e);
+
+private:
+  class ExtDateInternalMonthPrivate;
+  ExtDateInternalMonthPrivate *d;
+};
+
+/** Year selection widget.
+* @internal
+* @version $Id$
+* @author Tim Gilman, Mirko Boehm
+*/
+class ExtDateInternalYearSelector : public QLineEdit
+{
+  Q_OBJECT
+protected:
+  QIntValidator *val;
+  int result;
+public slots:
+  void yearEnteredSlot();
+signals:
+  void closeMe(int);
+public:
+  ExtDateInternalYearSelector( QWidget* parent=0, const char* name=0);
+  ~ExtDateInternalYearSelector();
+       int getYear();
+  void setYear(int year);
+
+private:
+  class ExtDateInternalYearPrivate {
+    public:
+    ExtDateInternalYearPrivate() {
+      calendar = new ExtCalendarSystemGregorian();
+    }
+               ~ExtDateInternalYearPrivate() {
+                       delete calendar;
+               }
+               ExtCalendarSystem *calendar;
+  };
+  ExtDateInternalYearPrivate *d;
+
+};
+
+/**
+ * Frame with popup menu behavior.
+ * @author Tim Gilman, Mirko Boehm
+ * @version $Id$
+ */
+class KPopupFrame : public QFrame
+{
+  Q_OBJECT
+protected:
+  /**
+   * The result. It is returned from exec() when the popup window closes.
+   */
+  int result;
+  /**
+   * Catch key press events.
+   */
+  virtual void keyPressEvent(QKeyEvent* e);
+  /**
+   * The only subwidget that uses the whole dialog window.
+   */
+  QWidget *main;
+public slots:
+  /**
+   * Close the popup window. This is called from the main widget, usually.
+   * @p r is the result returned from exec().
+   */
+  void close(int r);
+public:
+  /**
+   * The contructor. Creates a dialog without buttons.
+   */
+  KPopupFrame(QWidget* parent=0, const char*  name=0);
+  /**
+   * Set the main widget. You cannot set the main widget from the constructor,
+   * since it must be a child of the frame itselfes.
+   * Be careful: the size is set to the main widgets size. It is up to you to
+   * set the main widgets correct size before setting it as the main
+   * widget.
+   */
+  void setMainWidget(QWidget* m);
+  /**
+   * The resize event. Simply resizes the main widget to the whole
+   * widgets client size.
+   */
+  virtual void resizeEvent(QResizeEvent*);
+  /**
+   * Open the popup window at position pos.
+   */
+  void popup(const QPoint &pos);
+  /**
+   * Execute the popup window.
+   */
+  int exec(QPoint p);
+  /**
+   * Dito.
+   */
+  int exec(int x, int y);
+
+private:
+
+  virtual bool close(bool alsoDelete) { return QFrame::close(alsoDelete); }
+protected:
+  virtual void virtual_hook( int id, void* data );
+private:
+  class KPopupFramePrivate;
+  KPopupFramePrivate *d;
+};
+
+/**
+* Validates user-entered dates.
+*/
+class ExtDateValidator : public QValidator
+{
+public:
+    ExtDateValidator(QWidget* parent=0, const char* name=0);
+    virtual State validate(QString&, int&) const;
+    virtual void fixup ( QString & input ) const;
+    State date(const QString&, ExtDate&) const;
+};
+
+/**
+ * Date selection table.
+ * This is a support class for the ExtDatePicker class.  It just
+ * draws the calender table without titles, but could theoretically
+ * be used as a standalone.
+ *
+ * When a date is selected by the user, it emits a signal:
+ * dateSelected(ExtDate)
+ *
+ * @internal
+ * @version $Id$
+ * @author Tim Gilman, Mirko Boehm
+ */
+class ExtDateTable : public QGridView
+{
+    Q_OBJECT
+    //Q_PROPERTY( ExtDate date READ getDate WRITE setDate )
+    Q_PROPERTY( bool popupMenu READ popupMenuEnabled WRITE setPopupMenuEnabled )
+
+public:
+    /**
+     * The constructor.
+     */
+    ExtDateTable(QWidget *parent=0,
+              ExtDate date=ExtDate::currentDate(),
+              const char* name=0, WFlags f=0);
+
+    /**
+     * The destructor.
+     */
+    ~ExtDateTable();
+
+    /**
+     * Returns a recommended size for the widget.
+     * To save some time, the size of the largest used cell content is
+     * calculated in each paintCell() call, since all calculations have
+     * to be done there anyway. The size is stored in maxCell. The
+     * sizeHint() simply returns a multiple of maxCell.
+     */
+    virtual QSize sizeHint() const;
+    /**
+     * Set the font size of the date table.
+     */
+    void setFontSize(int size);
+    /**
+     * Select and display this date.
+     */
+    bool setDate(const ExtDate&);
+    // ### 4.0 rename to date()
+    const ExtDate& getDate() const;
+
+    /**
+     * Enables a popup menu when right clicking on a date.
+     *
+     * When it's enabled, this object emits a aboutToShowContextMenu signal
+     * where you can fill in the menu items.
+     *
+     * @since 3.2
+     */
+    void setPopupMenuEnabled( bool enable );
+
+    /**
+     * Returns if the popup menu is enabled or not
+     */
+    bool popupMenuEnabled() const;
+
+    enum BackgroundMode { NoBgMode=0, RectangleMode, CircleMode };
+
+    /**
+     * Makes a given date be painted with a given foregroundColor, and background
+     * (a rectangle, or a circle/ellipse) in a given color.
+     *
+     * @since 3.2
+     */
+    void setCustomDatePainting( const ExtDate &date, const QColor &fgColor, BackgroundMode bgMode=NoBgMode, const QColor &bgColor=QColor());
+
+    /**
+     * Unsets the custom painting of a date so that the date is painted as usual.
+     *
+     * @since 3.2
+     */
+    void unsetCustomDatePainting( const ExtDate &date );
+
+protected:
+    /**
+     * calculate the position of the cell in the matrix for the given date. The result is the 0-based index.
+     */
+    int posFromDate( const ExtDate &date ); // KDE4: make this virtual, so subclasses can reimplement this and use a different default for the start of the matrix
+    /**
+     * calculate the date that is displayed at a given cell in the matrix. pos is the
+     * 0-based index in the matrix. Inverse function to posForDate().
+     */
+    ExtDate dateFromPos( int pos ); // KDE4: make this virtual
+
+    /**
+     * Paint a cell.
+     */
+    virtual void paintCell(QPainter*, int, int);
+    /**
+     * Handle the resize events.
+     */
+    virtual void viewportResizeEvent(QResizeEvent *);
+    /**
+     * React on mouse clicks that select a date.
+     */
+    virtual void contentsMousePressEvent(QMouseEvent *);
+    virtual void wheelEvent( QWheelEvent * e );
+    virtual void keyPressEvent( QKeyEvent *e );
+    virtual void focusInEvent( QFocusEvent *e );
+    virtual void focusOutEvent( QFocusEvent *e );
+
+    // ### KDE 4.0 make the following private and mark as members
+
+    /**
+     * The font size of the displayed text.
+     */
+    int fontsize;
+    /**
+     * The currently selected date.
+     */
+    ExtDate date;
+    /**
+     * The day of the first day in the month [1..7].
+     */
+    int firstday;
+    /**
+     * The number of days in the current month.
+     */
+    int numdays;
+    /**
+     * The number of days in the previous month.
+     */
+    int numDaysPrevMonth;
+    /**
+     * unused
+     * ### remove in KDE 4.0
+     */
+    bool unused_hasSelection;
+    /**
+     * Save the size of the largest used cell content.
+     */
+    QRect maxCell;
+signals:
+    /**
+     * The selected date changed.
+     */
+    void dateChanged(const ExtDate&);
+    /**
+     * This function behaves essentially like the one above.
+     * The selected date changed.
+     * @param cur The current date
+     * @param old The date before the date was changed
+     */
+    void dateChanged(const ExtDate& cur, const ExtDate& old);
+    /**
+     * A date has been selected by clicking on the table.
+     */
+    void tableClicked();
+
+    /**
+     * A popup menu for a given date is about to be shown (as when the user
+     * right clicks on that date and the popup menu is enabled). Connect
+     * the slot where you fill the menu to this signal.
+     *
+     * @since 3.2
+     */
+    void aboutToShowContextMenu( KPopupMenu * menu, const ExtDate &date);
+
+protected:
+  virtual void virtual_hook( int id, void* data );
+private:
+    class ExtDateTablePrivate;
+    ExtDateTablePrivate *d;
+};
+
+#endif // EXTDATETBL_H
diff --git a/extdate/extdatetime.cpp b/extdate/extdatetime.cpp
new file mode 100644 (file)
index 0000000..473dc61
--- /dev/null
@@ -0,0 +1,1308 @@
+/*************************************************************************
+** Definition of extended range date classe
+**
+** Created : 031103
+**
+** 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.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+**********************************************************************/
+
+#include "extdatetime.h"
+#include "qregexp.h"
+
+#include <klocale.h>
+#include <kdebug.h>
+#include <assert.h>
+#include <time.h>
+
+static const uint SECS_PER_DAY = 86400;
+static const uint MSECS_PER_DAY = 86400000;
+static const uint SECS_PER_HOUR = 3600;
+static const uint MSECS_PER_HOUR= 3600000;
+static const uint SECS_PER_MIN = 60;
+static const uint MSECS_PER_MIN = 60000;
+
+/*****************************************************************************
+  ExtDate class
+ *****************************************************************************/
+
+/*****************************************************************************
+ *
+ * Concepts :
+ * a day is given by its rank after (or before if negative) the origin-day.
+ * The origin-day is 01/01/0000. Its rank is 1.
+ *
+ * ***************************************************************************/
+
+int    ExtDate::month_length[] = {31, 28, 31, 30,  31,  30,  31,  31,  30,  31,  30,  31};
+int    ExtDate::month_origin[] = { 0, 30, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};
+
+QString ExtDate::my_shortMonthNames[12] = {
+       i18n("Jan"), i18n("Feb"), i18n("Mar"), i18n("Apr"), i18n("May"), i18n("Jun"),
+       i18n("Jul"), i18n("Aug"), i18n("Sep"), i18n("Oct"), i18n("Nov"), i18n("Dec")
+};
+QString ExtDate::my_shortDayNames[7] = {
+       i18n("Mon"), i18n("Tue"), i18n("Wed"), i18n("Thu"), i18n("Fri"), i18n("Sat"), i18n("Sun")
+};
+QString ExtDate::my_longMonthNames[12] = {
+       i18n("January"), i18n("February"), i18n("March"), i18n("April"), i18n("May"),
+       i18n("June"), i18n("July"), i18n("August"), i18n("September"), i18n("October"),
+       i18n("November"), i18n("December")
+};
+QString ExtDate::my_longDayNames[7] = {
+       i18n("Monday"), i18n("Tuesday"), i18n("Wednesday"), i18n("Thursday"),
+       i18n("Friday"), i18n("Saturday"), i18n("Sunday")
+};
+
+int    ExtDate::my_invalid_day = 0;    // RAF : mettre une valeur vraiment invalide
+
+
+#ifndef QT_NO_DATESTRING
+/*****************************************************************************
+  Some static function used by ExtDate and ExtDateTime
+ *****************************************************************************/
+
+// Replaces tokens by their value. See ExtDateTime::toString() for a list of valid tokens
+static QString getFmtString( const QString& f, const QTime* dt = 0, const ExtDate* dd = 0, bool am_pm = FALSE )
+{
+    if ( f.isEmpty() )
+       return QString::null;
+
+    QString buf = f;
+
+    if ( dt ) {
+       if ( f == "h" ) {
+           if ( ( am_pm ) && ( dt->hour() > 12 ) )
+               buf = QString::number( dt->hour() - 12 );
+           else if ( ( am_pm ) && ( dt->hour() == 0 ) )
+               buf = "12";
+           else
+               buf = QString::number( dt->hour() );
+       } else if ( f == "hh" ) {
+           if ( ( am_pm ) && ( dt->hour() > 12 ) )
+               buf = QString::number( dt->hour() - 12 ).rightJustify( 2, '0', TRUE );
+           else if ( ( am_pm ) && ( dt->hour() == 0 ) )
+               buf = "12";
+           else
+               buf = QString::number( dt->hour() ).rightJustify( 2, '0', TRUE );
+       } else if ( f == "m" ) {
+           buf = QString::number( dt->minute() );
+       } else if ( f == "mm" ) {
+           buf = QString::number( dt->minute() ).rightJustify( 2, '0', TRUE );
+       } else if ( f == "s" ) {
+           buf = QString::number( dt->second() );
+       } else if ( f == "ss" ) {
+           buf = QString::number( dt->second() ).rightJustify( 2, '0', TRUE );
+       } else if ( f == "z" ) {
+           buf = QString::number( dt->msec() );
+       } else if ( f == "zzz" ) {
+           buf = QString::number( dt->msec() ).rightJustify( 3, '0', TRUE );
+       } else if ( f == "ap" ) {
+           buf = dt->hour() < 12 ? "am" : "pm";
+       } else if ( f == "AP" ) {
+           buf = dt->hour() < 12 ? "AM" : "PM";
+       }
+    }
+
+    if ( dd ) {
+       if ( f == "d" ) {
+           buf = QString::number( dd->day() );
+       } else if ( f == "dd" ) {
+           buf = QString::number( dd->day() ).rightJustify( 2, '0', TRUE );
+       } else if ( f == "M" ) {
+           buf = QString::number( dd->month() );
+       } else if ( f == "MM" ) {
+           buf = QString::number( dd->month() ).rightJustify( 2, '0', TRUE );
+#ifndef QT_NO_TEXTDATE
+       } else if ( f == "ddd" ) {
+           buf = dd->shortDayName( dd->dayOfWeek() );
+       } else if ( f == "dddd" ) {
+           buf = dd->longDayName( dd->dayOfWeek() );
+       } else if ( f == "MMM" ) {
+           buf = dd->shortMonthName( dd->month() );
+       } else if ( f == "MMMM" ) {
+           buf = dd->longMonthName( dd->month() );
+#endif
+       } else if ( f == "yy" ) {
+           buf = QString::number( dd->year() ).right( 2 );
+       } else if ( f == "yyyy" ) {
+           buf = QString::number( dd->year() );
+       }
+    }
+
+    return buf;
+}
+
+// Parses the format string and uses getFmtString to get the values for the tokens. Ret
+static QString fmtDateTime( const QString& f, const QTime* dt = 0, const ExtDate* dd = 0 )
+{
+    if ( f.isEmpty() ) {
+       return QString::null;
+    }
+
+    if ( dt && !dt->isValid() )
+       return QString::null;
+    if ( dd && !dd->isValid() )
+       return QString::null;
+
+    bool ap = ( f.contains( "AP" ) || f.contains( "ap" ) );
+
+    QString buf;
+    QString frm;
+    QChar status = '0';
+
+    for ( int i = 0; i < (int)f.length(); ++i ) {
+
+       if ( f[ i ] == status ) {
+           if ( ( ap ) && ( ( f[ i ] == 'P' ) || ( f[ i ] == 'p' ) ) )
+               status = '0';
+           frm += f[ i ];
+       } else {
+           buf += getFmtString( frm, dt, dd, ap );
+           frm = QString::null;
+           if ( ( f[ i ] == 'h' ) || ( f[ i ] == 'm' ) || ( f[ i ] == 's' ) || ( f[ i ] == 'z' ) ) {
+               status = f[ i ];
+               frm += f[ i ];
+           } else if ( ( f[ i ] == 'd' ) || ( f[ i ] == 'M' ) || ( f[ i ] == 'y' ) ) {
+               status = f[ i ];
+               frm += f[ i ];
+           } else if ( ( ap ) && ( f[ i ] == 'A' ) ) {
+               status = 'P';
+               frm += f[ i ];
+           } else  if( ( ap ) && ( f[ i ] == 'a' ) ) {
+               status = 'p';
+               frm += f[ i ];
+           } else {
+               buf += f[ i ];
+               status = '0';
+           }
+       }
+    }
+
+    buf += getFmtString( frm, dt, dd, ap );
+
+    return buf;
+}
+#endif // QT_NO_DATESTRING
+
+
+/*
+ * y = year
+ * m = month (Jan : 1, Feb : 2 ...
+ * d = day in [1...31]
+ */
+int ExtDate::dayRank(int y, int m, int d)
+{
+       int     a_day_number;
+       a_day_number = y*365 + (y+3)/4 - (y-1)/100 + (y-1)/400;
+       a_day_number += dayOfYear(y, m, d);
+       return a_day_number;
+}
+
+ExtDate::ExtDate( int y, int m, int d)
+{
+       if ( !isValid(y,m,d) ) {
+#if defined(QT_CHECK_RANGE)
+               qWarning( "ExtDate: Invalid date %04d-%02d-%02d", y, m, d );
+#endif
+               jd = my_invalid_day;
+       } else {
+               jd = dayRank(y, m, d);
+       }
+}
+
+bool ExtDate::isValid() const
+{
+       return (jd != my_invalid_day);
+}
+
+int ExtDate::year() const
+{
+       int     a_year = (int)(jd/365.25);      // first approximation
+       if (dayRank(a_year, 1, 1) > jd)
+       {
+               for (a_year-- ; dayRank(a_year, 1, 1) > jd ; a_year--);
+       }
+
+       if (dayRank(a_year+1, 1, 1) <= jd)
+       {
+               for ( ; dayRank(a_year+1, 1, 1) <= jd ; a_year++);
+       }
+       return a_year;
+}
+
+int ExtDate::month() const
+{
+       int     a_year = year();
+       int     a_res = jd - dayRank(a_year, 1, 0);
+       int     a_month;
+       int     a_leap_year = leapYear(a_year) ? 1 : 0;
+       if (month_origin[1] >= a_res) return 1;
+//     if (month_origin[2] > a_res) return 2;
+       for (a_month = 12 ; (month_origin[a_month-1]+a_leap_year) >= a_res ; a_month--);
+       return a_month;
+}
+
+int ExtDate::day() const
+{
+       return jd - dayRank(year(), month(), 0);
+}
+
+int ExtDate::dayOfWeek() const
+{
+       int a_day = ((jd + 5) % 7);
+       return (a_day == 0) ? 7 : a_day;
+}
+
+int ExtDate::dayOfYear() const
+{
+       return jd - dayRank(year(), 1, 0);
+}
+
+int ExtDate::daysInMonth() const
+{
+       int     a_month = month();
+       return (a_month == 2) ? (leapYear(year()) ? 29 : 28) : month_length[a_month-1] ;
+}
+
+int ExtDate::daysInYear() const
+{
+       return (leapYear(year()) ? 366 : 365);
+}
+
+int ExtDate::weekNumber( int *yearNum) const
+{
+       // the year and week number are those of the next Sunday.
+       ExtDate a_date;
+       a_date.set_jd(jd - dayOfWeek() + 7);
+       int     a_year = a_date.year();
+       *yearNum = a_year;
+       return 1 + a_date.dayOfYear()/7;
+}
+
+#ifndef QT_NO_TEXTDATE
+QString ExtDate::shortMonthName( int month ) {return my_shortMonthNames[month-1];};
+QString ExtDate::shortDayName( int weekday ) {return my_shortDayNames[weekday-1];};
+QString ExtDate::longMonthName( int month ) {return my_longMonthNames[month-1];};
+QString ExtDate::longDayName( int weekday ) {return my_longDayNames[weekday-1];};
+#endif //QT_NO_TEXTDATE
+#ifndef QT_NO_TEXTSTRING
+#if !defined(QT_NO_SPRINTF)
+QString ExtDate::toStringSimpleArg( char code, int nb ) const
+{
+       QString result;
+       switch (code)
+       {
+               case 'd' :
+                       {
+                               switch (nb)
+                               {
+                                       case 1 :
+                                               result = result.sprintf("%d", day());
+                                               break;
+                                       case 2 :
+                                               result = result.sprintf("%02d", day());
+                                               break;
+                                       case 3 :
+                                               result = shortDayName(dayOfWeek());
+                                               break;
+                                       case 4 :
+                                               result = longDayName(dayOfWeek());
+                                               break;
+                                       default :
+                                               result = "?d?";
+                                               break;
+                               }
+                       }
+                       break;
+
+               case 'M' :
+                       {
+                               int     m = month();
+                               switch (nb)
+                               {
+                                       case 1 :
+                                               result = result.sprintf("%d", m);
+                                               break;
+                                       case 2 :
+                                               result = result.sprintf("%02d", m);
+                                               break;
+                                       case 3 :
+                                               result = shortMonthName(m);
+                                               break;
+                                       case 4 :
+                                               result = longMonthName(m);
+                                               break;
+                                       default :
+                                               result = "?M?";
+                                               break;
+                               }
+                       }
+                       break;
+
+               case 'y' :
+                       {
+                               int     y = year();
+                               switch (nb)
+                               {
+                                       case 2 :
+                                               result = result.sprintf("%02d", y%100);
+                                               break;
+                                       case 4 :
+                                               result = result.sprintf("%04d", y);
+                                               break;
+                                       default :
+                                               result = "?y?";
+                                               break;
+                               }
+                       }
+                       break;
+
+               default :
+                       break;
+       }
+       return result;
+}
+
+QString ExtDate::toString( Qt::DateFormat f) const
+{
+       QString a_format;
+
+       if ( ! isValid() ) return QString::null;
+
+       switch (f)
+       {
+               case Qt::TextDate :     // Sat May 20 1995
+                       a_format = "ddd MMM d yyyy";
+                       break;
+
+               case Qt::ISODate :      // YYYY-MM-DD
+                       a_format = "yyyy-MM-dd";
+                       break;
+
+               case Qt::LocalDate :    // local settings
+                       a_format = "toString : Qt::LocalDate not implemented yet";
+                       break;
+
+               default :
+                       a_format = "toString : unknown format";
+                       break;
+
+       }
+       return toString(a_format);
+}
+#endif
+QString ExtDate::toString( const QString& format ) const
+{
+       // d{1-4}, M{1-4}, yy|yyyy
+       uint    i, a_nb = 0;
+       QString result;
+       char    a_code = '\0';
+       char    a_char;
+
+       if ( ! isValid() ) return QString::null;
+
+       for (i = 0 ; i <= format.length() ; i++)
+       {
+               if (i < format.length())
+               {
+                       a_char = format[i];
+               }
+               else
+               {
+                       a_char = '\0';
+               }
+               if (a_code == a_char)
+               {
+                       a_nb++;
+               }
+               else
+               {
+                       if ((a_code == 'd' || a_code == 'M' || a_code == 'y') && a_nb != 0)
+                       {
+                               result += toStringSimpleArg(a_code, a_nb);
+                       }
+                       if (a_char == 'd' || a_char == 'M' || a_char == 'y')
+                       {
+                               a_code = a_char;
+                               a_nb = 1;
+                       }
+                       else
+                       {
+                               a_code = '\0';
+                               a_nb = 0;
+                               if (a_char != '\0')
+                                       result += a_char;
+                       }
+               }
+       }
+       return result;
+}
+#endif
+bool   ExtDate::setYMD( int y, int m, int d )
+{
+       jd = dayRank(y, m, d);
+       return true;
+}
+
+ExtDate  ExtDate::addDays( int days ) const
+{
+       ExtDate a_date;
+       a_date.set_jd(jd + days);
+       return a_date;
+}
+
+ExtDate  ExtDate::addMonths( int months ) const
+{
+       int     a_month = month() + months;
+       int     a_year = year() + (a_month - 1)/12;     // month : [1..12]
+       a_month  = 1 + (a_month -1) % 12;
+       return ExtDate(a_year, a_month, day());
+}
+
+ExtDate  ExtDate::addYears( int years ) const
+{
+       return ExtDate(year() + years, month(), day());
+}
+
+int   ExtDate::daysTo( const ExtDate & a_date) const
+{
+       return a_date.jd - jd;  // RAF
+}
+
+ExtDate ExtDate::currentDate(Qt::TimeSpec ts)
+{
+       time_t          a_current_time;
+       struct  tm      a_current_time_tm;
+
+       time(&a_current_time);
+       switch (ts)
+       {
+               case Qt::LocalTime :
+                       localtime_r(&a_current_time, &a_current_time_tm);
+                       break;
+
+               case Qt::UTC :
+                       gmtime_r(&a_current_time, &a_current_time_tm);
+                       break;
+
+               default :
+                       assert(0);
+                       break;
+       }
+       return ExtDate(a_current_time_tm.tm_year + 1900, a_current_time_tm.tm_mon + 1, a_current_time_tm.tm_mday);
+}
+
+#ifndef QT_NO_DATESTRING
+ExtDate ExtDate::fromString( const QString& s, Qt::DateFormat f )
+{
+       ExtDate dt = ExtDate();  //initialize invalid date
+       if ( s.isEmpty() ) { return dt; }
+       if ( f == Qt::LocalDate ) { //can't use LocalFormat
+#if defined(QT_CHECK_RANGE)
+               qWarning( "QDate::fromString: Parameter out of range" );
+#endif
+               return dt;
+}
+
+       switch( f ) {
+               case Qt::ISODate :
+               {
+                       int year( s.mid( 0, 4 ).toInt() );
+                       int month( s.mid( 5, 2 ).toInt() );
+                       int day( s.mid( 8, 2 ).toInt() );
+                       if ( year && month && day )
+                               return ExtDate( year, month, day );
+               }
+               break;
+
+               default :
+#ifndef QT_NO_TEXTDATE
+               case Qt::TextDate :
+               {
+                       /*
+                               This will fail gracefully if the input string doesn't
+                               contain any space.
+                       */
+                       int monthPos = s.find( ' ' ) + 1;
+                       int dayPos = s.find( ' ', monthPos ) + 1;
+
+                       QString monthName( s.mid(monthPos, dayPos - monthPos - 1) );
+                       int month = -1;
+
+                       // try English names first
+                       for ( int i = 0; i < 12; i++ ) {
+                               if ( monthName == my_shortMonthNames[i] ) {
+                                               month = i + 1;
+                                               break;
+                               }
+                       }
+
+                       // try the localized names
+                       if ( month == -1 ) {
+                               for ( int i = 0; i < 12; i++ ) {
+                                       if ( monthName == shortMonthName( i + 1 ) ) {
+                                               month = i + 1;
+                                               break;
+                                       }
+                               }
+                       }
+
+#if defined(QT_CHECK_RANGE)
+                       if ( month < 1 || month > 12 ) {
+                               qWarning( "QDate::fromString: Parameter out of range" );
+                               return dt;
+                       }
+#endif  //if defined(QT_CHECK_RANGE)
+
+                       int day = s.mid( dayPos, 2 ).stripWhiteSpace().toInt();
+                       int year = s.right( 4 ).toInt();
+                       return ExtDate( year, month, day );
+               }
+#else
+               break;
+#endif  //ifndef QT_NO_TEXTDATE
+       }
+
+       return dt;
+}
+#endif  //ifndef QT_NO_DATESTRING
+
+bool ExtDate::isValid( int y, int m, int d )
+{
+       if (m < 1 || m > 12) return false;
+       if (d < 1) return false;
+       if (m != 2 && d > month_length[m-1]) return false;
+       if (m == 2 && d > (month_length[1] + (leapYear(y) ? 1 : 0))) return false;
+       return true;
+}
+
+QDate ExtDate::qdate() const {
+       QDate q( year(), month(), day() );
+
+       if ( q.isValid() )
+               return q;
+       else
+               return QDate();
+}
+
+bool   ExtDate::leapYear( int year )
+{
+       // year is the year-number where JC birth is 0
+       if ((year % 4) != 0) return false;
+       // multiple of 4 : can be a leap year
+       // centennial years are NOT leap, but quadri-centennial ARE.
+       if ((year % 400) == 0) return true;
+       if ((year % 100) == 0) return false;
+       // year is multiple of 4 but not centennial so leap year !
+       return true;
+}
+
+uint   ExtDate::gregorianToJulian( int y, int m, int d )
+{
+       return 0;       // RAF
+}
+
+void   ExtDate::julianToGregorian( uint jd, int &y, int &m, int &d )
+{
+}
+
+int ExtDate::dayOfYear(int y, int m, int d)
+{
+       return month_origin[m-1] + d + ((m > 1) ? (leapYear(y) ? 1 : 0) : 0);
+}
+
+/*****************************************************************************
+  ExtDateTime member functions
+ *****************************************************************************/
+
+/*!
+    \class ExtDateTime extdatetime.h
+    \reentrant
+    \brief The ExtDateTime class provides date and time functions.
+
+    \ingroup time
+    \mainclass
+
+    A ExtDateTime object contains a calendar date and a clock time (a
+    "datetime"). It is a combination of the ExtDate and QTime classes.
+    It can read the current datetime from the system clock. It
+    provides functions for comparing datetimes and for manipulating a
+    datetime by adding a number of seconds, days, months or years.
+
+    A ExtDateTime object is typically created either by giving a date
+    and time explicitly in the constructor, or by using the static
+    function currentDateTime(), which returns a ExtDateTime object set
+    to the system clock's time. The date and time can be changed with
+    setDate() and setTime(). A datetime can also be set using the
+    setTime_t() function, which takes a POSIX-standard "number of
+    seconds since 00:00:00 on January 1, 1970" value. The fromString()
+    function returns a ExtDateTime given a string and a date format
+    which is used to interpret the date within the string.
+
+    The date() and time() functions provide access to the date and
+    time parts of the datetime. The same information is provided in
+    textual format by the toString() function.
+
+    ExtDateTime provides a full set of operators to compare two
+    ExtDateTime objects where smaller means earlier and larger means
+    later.
+
+    You can increment (or decrement) a datetime by a given number of
+    seconds using addSecs() or days using addDays(). Similarly you can
+    use addMonths() and addYears(). The daysTo() function returns the
+    number of days between two datetimes, and secsTo() returns the
+    number of seconds between two datetimes.
+
+    The range of a datetime object is constrained to the ranges of the
+    ExtDate and QTime objects which it embodies.
+
+    \sa ExtDate QTime ExtDateTimeEdit
+*/
+
+
+/*!
+    \fn ExtDateTime::ExtDateTime()
+
+    Constructs a null datetime (i.e. null date and null time). A null
+    datetime is invalid, since the date is invalid.
+
+    \sa isValid()
+*/
+
+
+/*!
+    Constructs a datetime with date \a date and null (but valid) time
+    (00:00:00.000).
+*/
+
+ExtDateTime::ExtDateTime( const ExtDate &date )
+    : d(date)
+{
+}
+
+/*!
+    Constructs a datetime with date \a date and time \a time.
+*/
+
+ExtDateTime::ExtDateTime( const ExtDate &date, const QTime &time )
+    : d(date), t(time)
+{
+}
+
+
+/*!
+    \fn bool ExtDateTime::isNull() const
+
+    Returns TRUE if both the date and the time are null; otherwise
+    returns FALSE. A null datetime is invalid.
+
+    \sa ExtDate::isNull(), QTime::isNull()
+*/
+
+/*!
+    \fn bool ExtDateTime::isValid() const
+
+    Returns TRUE if both the date and the time are valid; otherwise
+    returns FALSE.
+
+    \sa ExtDate::isValid(), QTime::isValid()
+*/
+
+/*!
+    \fn ExtDate ExtDateTime::date() const
+
+    Returns the date part of the datetime.
+
+    \sa setDate(), time()
+*/
+
+/*!
+    \fn QTime ExtDateTime::time() const
+
+    Returns the time part of the datetime.
+
+    \sa setTime(), date()
+*/
+
+/*!
+    \fn void ExtDateTime::setDate( const ExtDate &date )
+
+    Sets the date part of this datetime to \a date.
+
+    \sa date(), setTime()
+*/
+
+/*!
+    \fn void ExtDateTime::setTime( const QTime &time )
+
+    Sets the time part of this datetime to \a time.
+
+    \sa time(), setDate()
+*/
+
+
+/*!
+    Returns the datetime as the number of seconds that have passed
+    since 1970-01-01T00:00:00, Coordinated Universal Time (UTC).
+
+    On systems that do not support timezones, this function will
+    behave as if local time were UTC.
+
+    \sa setTime_t()
+*/
+
+uint ExtDateTime::toTime_t() const
+{
+    tm brokenDown;
+    brokenDown.tm_sec = t.second();
+    brokenDown.tm_min = t.minute();
+    brokenDown.tm_hour = t.hour();
+    brokenDown.tm_mday = d.day();
+    brokenDown.tm_mon = d.month() - 1;
+    brokenDown.tm_year = d.year() - 1900;
+    brokenDown.tm_isdst = -1;
+    int secsSince1Jan1970UTC = (int) mktime( &brokenDown );
+    if ( secsSince1Jan1970UTC < -1 )
+       secsSince1Jan1970UTC = -1;
+    return (uint) secsSince1Jan1970UTC;
+}
+
+/*!
+    \overload
+
+    Convenience function that sets the date and time to local time
+    based on the given UTC time.
+*/
+
+void ExtDateTime::setTime_t( uint secsSince1Jan1970UTC )
+{
+    setTime_t( secsSince1Jan1970UTC, Qt::LocalTime );
+}
+
+/*!
+    Sets the date and time to \a ts time (\c Qt::LocalTime or \c
+    Qt::UTC) given the number of seconds that have passed since
+    1970-01-01T00:00:00, Coordinated Universal Time (UTC). On systems
+    that do not support timezones this function will behave as if
+    local time were UTC.
+
+    On Windows, only a subset of \a secsSince1Jan1970UTC values are
+    supported, as Windows starts counting from 1980.
+
+    \sa toTime_t()
+*/
+void ExtDateTime::setTime_t( uint secsSince1Jan1970UTC, Qt::TimeSpec ts )
+{
+    time_t tmp = (time_t) secsSince1Jan1970UTC;
+    tm *brokenDown = 0;
+
+#if defined(Q_OS_UNIX) && defined(QT_THREAD_SUPPORT) && defined(_POSIX_THREAD_SAFE_FUNCTIONS)
+    // posix compliant system
+    // use the reentrant versions of localtime() and gmtime() where available
+    tm res;
+    if ( ts == Qt::LocalTime )
+       brokenDown = localtime_r( &tmp, &res );
+    if ( !brokenDown ) {
+       brokenDown = gmtime_r( &tmp, &res );
+       if ( !brokenDown ) {
+           d.jd = ExtDate::gregorianToJulian( 1970, 1, 1 );
+           t.setHMS(0,0,0);
+                       //          t.ds = 0;
+           return;
+       }
+    }
+#else
+    if ( ts == Qt::LocalTime )
+       brokenDown = localtime( &tmp );
+    if ( !brokenDown ) {
+       brokenDown = gmtime( &tmp );
+       if ( !brokenDown ) {
+           d.jd = ExtDate::gregorianToJulian( 1970, 1, 1 );
+//         t.ds = 0;
+           t.setHMS(0,0,0);
+                       return;
+       }
+    }
+#endif
+
+    d.jd = ExtDate::gregorianToJulian( brokenDown->tm_year + 1900,
+                                    brokenDown->tm_mon + 1,
+                                    brokenDown->tm_mday );
+    t.setHMS( brokenDown->tm_hour, brokenDown->tm_min, brokenDown->tm_sec );
+//             t.ds = MSECS_PER_HOUR * brokenDown->tm_hour +
+//        MSECS_PER_MIN * brokenDown->tm_min +
+//        1000 * brokenDown->tm_sec;
+}
+#ifndef QT_NO_DATESTRING
+#ifndef QT_NO_SPRINTF
+/*!
+    \overload
+
+    Returns the datetime as a string. The \a f parameter determines
+    the format of the string.
+
+    If \a f is \c Qt::TextDate, the string format is "Wed May 20
+    03:40:13 1998" (using ExtDate::shortDayName(), ExtDate::shortMonthName(),
+    and QTime::toString() to generate the string, so the day and month
+    names will have localized names).
+
+    If \a f is \c Qt::ISODate, the string format corresponds to the
+    ISO 8601 extended specification for representations of dates and
+    times, which is YYYY-MM-DDTHH:MM:SS.
+
+    If \a f is \c Qt::LocalDate, the string format depends on the
+    locale settings of the system.
+
+    If the format \a f is invalid or the datetime is invalid, toString()
+    returns a null string.
+
+    \sa ExtDate::toString() QTime::toString()
+*/
+
+QString ExtDateTime::toString( Qt::DateFormat f ) const
+{
+    if ( !isValid() )
+       return QString::null;
+
+    if ( f == Qt::ISODate ) {
+       return d.toString( Qt::ISODate ) + "T" + t.toString( Qt::ISODate );
+    }
+#ifndef QT_NO_TEXTDATE
+    else if ( f == Qt::TextDate ) {
+#ifndef Q_WS_WIN
+       QString buf = d.shortDayName( d.dayOfWeek() );
+       buf += ' ';
+       buf += d.shortMonthName( d.month() );
+       buf += ' ';
+       buf += QString().setNum( d.day() );
+       buf += ' ';
+#else
+       QString buf;
+       QString winstr;
+       QT_WA( {
+           TCHAR out[255];
+           GetLocaleInfo( LOCALE_USER_DEFAULT, LOCALE_ILDATE, out, 255 );
+           winstr = QString::fromUcs2( (ushort*)out );
+       } , {
+           char out[255];
+           GetLocaleInfoA( LOCALE_USER_DEFAULT, LOCALE_ILDATE, (char*)&out, 255 );
+           winstr = QString::fromLocal8Bit( out );
+       } );
+       switch ( winstr.toInt() ) {
+       case 1:
+           buf = d.shortDayName( d.dayOfWeek() ) + " " + QString().setNum( d.day() ) + ". " + d.shortMonthName( d.month() ) + " ";
+           break;
+       default:
+           buf = d.shortDayName( d.dayOfWeek() ) + " " + d.shortMonthName( d.month() ) + " " + QString().setNum( d.day() ) + " ";
+           break;
+       }
+#endif
+       buf += t.toString();
+       buf += ' ';
+       buf += QString().setNum( d.year() );
+       return buf;
+    }
+#endif
+    else if ( f == Qt::LocalDate ) {
+       return d.toString( Qt::LocalDate ) + " " + t.toString( Qt::LocalDate );
+    }
+    return QString::null;
+}
+#endif
+
+/*!
+    Returns the datetime as a string. The \a format parameter
+    determines the format of the result string.
+
+    These expressions may be used for the date:
+
+    \table
+    \header \i Expression \i Output
+    \row \i d \i the day as number without a leading zero (1-31)
+    \row \i dd \i the day as number with a leading zero (01-31)
+    \row \i ddd
+           \i the abbreviated localized day name (e.g. 'Mon'..'Sun').
+           Uses ExtDate::shortDayName().
+    \row \i dddd
+           \i the long localized day name (e.g. 'Monday'..'Sunday').
+           Uses ExtDate::longDayName().
+    \row \i M \i the month as number without a leading zero (1-12)
+    \row \i MM \i the month as number with a leading zero (01-12)
+    \row \i MMM
+           \i the abbreviated localized month name (e.g. 'Jan'..'Dec').
+           Uses ExtDate::shortMonthName().
+    \row \i MMMM
+           \i the long localized month name (e.g. 'January'..'December').
+           Uses ExtDate::longMonthName().
+    \row \i yy \i the year as two digit number (00-99)
+    \row \i yyyy \i the year as four digit number (1752-8000)
+    \endtable
+
+    These expressions may be used for the time:
+
+    \table
+    \header \i Expression \i Output
+    \row \i h
+           \i the hour without a leading zero (0..23 or 1..12 if AM/PM display)
+    \row \i hh
+           \i the hour with a leading zero (00..23 or 01..12 if AM/PM display)
+    \row \i m \i the minute without a leading zero (0..59)
+    \row \i mm \i the minute with a leading zero (00..59)
+    \row \i s \i the second whithout a leading zero (0..59)
+    \row \i ss \i the second whith a leading zero (00..59)
+    \row \i z \i the milliseconds without leading zeroes (0..999)
+    \row \i zzz \i the milliseconds with leading zeroes (000..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".
+    \endtable
+
+    All other input characters will be ignored.
+
+    Example format strings (assumed that the ExtDateTime is
+    21<small><sup>st</sup></small> May 2001 14:13:09)
+
+    \table
+    \header \i Format \i Result
+    \row \i dd.MM.yyyy     \i11 21.05.2001
+    \row \i ddd MMMM d yy   \i11 Tue May 21 01
+    \row \i hh:mm:ss.zzz    \i11 14:13:09.042
+    \row \i h:m:s ap       \i11 2:13:9 pm
+    \endtable
+
+    If the datetime is an invalid datetime, then QString::null will be returned.
+
+    \sa ExtDate::toString() QTime::toString()
+*/
+QString ExtDateTime::toString( const QString& format ) const
+{
+    return fmtDateTime( format, &t, &d );
+}
+#endif //QT_NO_DATESTRING
+
+/*!
+    Returns a ExtDateTime object containing a datetime \a ndays days
+    later than the datetime of this object (or earlier if \a ndays is
+    negative).
+
+    \sa daysTo(), addMonths(), addYears(), addSecs()
+*/
+
+ExtDateTime ExtDateTime::addDays( int ndays ) const
+{
+    return ExtDateTime( d.addDays(ndays), t );
+}
+
+/*!
+    Returns a ExtDateTime object containing a datetime \a nmonths months
+    later than the datetime of this object (or earlier if \a nmonths
+    is negative).
+
+    \sa daysTo(), addDays(), addYears(), addSecs()
+*/
+
+ExtDateTime ExtDateTime::addMonths( int nmonths ) const
+{
+    return ExtDateTime( d.addMonths(nmonths), t );
+}
+
+/*!
+    Returns a ExtDateTime object containing a datetime \a nyears years
+    later than the datetime of this object (or earlier if \a nyears is
+    negative).
+
+    \sa daysTo(), addDays(), addMonths(), addSecs()
+*/
+
+ExtDateTime ExtDateTime::addYears( int nyears ) const
+{
+    return ExtDateTime( d.addYears(nyears), t );
+}
+
+/*!
+    Returns a ExtDateTime object containing a datetime \a nsecs seconds
+    later than the datetime of this object (or earlier if \a nsecs is
+    negative).
+
+    \sa secsTo(), addDays(), addMonths(), addYears()
+*/
+
+ExtDateTime ExtDateTime::addSecs( int nsecs ) const
+{
+       uint dd = d.jd;
+       int tt = MSECS_PER_HOUR*t.hour() + MSECS_PER_MIN*t.minute() + 1000*t.second() + t.msec();
+       int  sign = 1;
+
+       if ( nsecs < 0 ) {
+               nsecs = -nsecs;
+               sign = -1;
+       }
+
+       if ( nsecs >= (int)SECS_PER_DAY ) {
+               dd += sign*(nsecs/SECS_PER_DAY);
+               nsecs %= SECS_PER_DAY;
+       }
+       tt += sign*nsecs*1000;
+
+       if ( tt < 0 ) {
+               tt = MSECS_PER_DAY - tt - 1;
+               dd -= tt / MSECS_PER_DAY;
+               tt = tt % MSECS_PER_DAY;
+               tt = MSECS_PER_DAY - tt - 1;
+       } else if ( tt >= (int)MSECS_PER_DAY ) {
+               dd += ( tt / MSECS_PER_DAY );
+               tt = tt % MSECS_PER_DAY;
+       }
+
+       ExtDateTime ret;
+       ret.setTime( ret.t.addMSecs( tt ) );
+       ret.d.jd = dd;
+
+       return ret;
+}
+
+/*!
+    Returns the number of days from this datetime to \a dt (which is
+    negative if \a dt is earlier than this datetime).
+
+    \sa addDays(), secsTo()
+*/
+
+int ExtDateTime::daysTo( const ExtDateTime &dt ) const
+{
+    return d.daysTo( dt.d );
+}
+
+/*!
+    Returns the number of seconds from this datetime to \a dt (which
+    is negative if \a dt is earlier than this datetime).
+
+    Example:
+    \code
+    ExtDateTime dt = ExtDateTime::currentDateTime();
+    ExtDateTime xmas( ExtDate(dt.date().year(),12,24), QTime(17,00) );
+    qDebug( "There are %d seconds to Christmas", dt.secsTo(xmas) );
+    \endcode
+
+    \sa addSecs(), daysTo(), QTime::secsTo()
+*/
+
+int ExtDateTime::secsTo( const ExtDateTime &dt ) const
+{
+    return t.secsTo(dt.t) + d.daysTo(dt.d)*SECS_PER_DAY;
+}
+
+
+/*!
+    Returns TRUE if this datetime is equal to \a dt; otherwise returns FALSE.
+
+    \sa operator!=()
+*/
+
+bool ExtDateTime::operator==( const ExtDateTime &dt ) const
+{
+    return  t == dt.t && d == dt.d;
+}
+
+/*!
+    Returns TRUE if this datetime is different from \a dt; otherwise
+    returns FALSE.
+
+    \sa operator==()
+*/
+
+bool ExtDateTime::operator!=( const ExtDateTime &dt ) const
+{
+    return  t != dt.t || d != dt.d;
+}
+
+/*!
+    Returns TRUE if this datetime is earlier than \a dt; otherwise
+    returns FALSE.
+*/
+
+bool ExtDateTime::operator<( const ExtDateTime &dt ) const
+{
+    if ( d < dt.d )
+       return TRUE;
+    return d == dt.d ? t < dt.t : FALSE;
+}
+
+/*!
+    Returns TRUE if this datetime is earlier than or equal to \a dt;
+    otherwise returns FALSE.
+*/
+
+bool ExtDateTime::operator<=( const ExtDateTime &dt ) const
+{
+    if ( d < dt.d )
+       return TRUE;
+    return d == dt.d ? t <= dt.t : FALSE;
+}
+
+/*!
+    Returns TRUE if this datetime is later than \a dt; otherwise
+    returns FALSE.
+*/
+
+bool ExtDateTime::operator>( const ExtDateTime &dt ) const
+{
+    if ( d > dt.d )
+       return TRUE;
+    return d == dt.d ? t > dt.t : FALSE;
+}
+
+/*!
+    Returns TRUE if this datetime is later than or equal to \a dt;
+    otherwise returns FALSE.
+*/
+
+bool ExtDateTime::operator>=( const ExtDateTime &dt ) const
+{
+    if ( d > dt.d )
+       return TRUE;
+    return d == dt.d ? t >= dt.t : FALSE;
+}
+
+/*!
+    \overload
+
+    Returns the current datetime, as reported by the system clock.
+
+    \sa ExtDate::currentDate(), QTime::currentTime()
+*/
+
+ExtDateTime ExtDateTime::currentDateTime()
+{
+    return currentDateTime( Qt::LocalTime );
+}
+
+/*!
+  Returns the current datetime, as reported by the system clock, for the
+  TimeSpec \a ts. The default TimeSpec is LocalTime.
+
+  \sa ExtDate::currentDate(), QTime::currentTime(), Qt::TimeSpec
+*/
+
+ExtDateTime ExtDateTime::currentDateTime( Qt::TimeSpec ts )
+{
+    ExtDateTime dt;
+    dt.setDate( ExtDate::currentDate(ts) );
+    QTime t = t.currentTime(ts);
+    if ( t.hour()==0 && t.minute()==0 )         // midnight or right after?
+        dt.setDate( ExtDate::currentDate(ts) ); // fetch date again
+    dt.setTime( t );
+    return dt;
+}
+
+#ifndef QT_NO_DATESTRING
+/*!
+    Returns the ExtDateTime represented by the string \a s, using the
+    format \a f, or an invalid datetime if this is not possible.
+
+    Note for \c Qt::TextDate: It is recommended that you use the
+    English short month names (e.g. "Jan"). Although localized month
+    names can also be used, they depend on the user's locale settings.
+
+    \warning Note that \c Qt::LocalDate cannot be used here.
+*/
+ExtDateTime ExtDateTime::fromString( const QString& s, Qt::DateFormat f )
+{
+    if ( ( s.isEmpty() ) || ( f == Qt::LocalDate ) ) {
+#if defined(QT_CHECK_RANGE)
+       qWarning( "ExtDateTime::fromString: Parameter out of range" );
+#endif
+       ExtDateTime dt;
+       dt.d.jd = 0;
+       return dt;
+    }
+    if ( f == Qt::ISODate ) {
+       return ExtDateTime( ExtDate::fromString( s.mid(0,10), Qt::ISODate ),
+                         QTime::fromString( s.mid(11), Qt::ISODate ) );
+    }
+#if !defined(QT_NO_REGEXP) && !defined(QT_NO_TEXTDATE)
+    else if ( f == Qt::TextDate ) {
+       QString monthName( s.mid( 4, 3 ) );
+       int month = -1;
+       // Assume that English monthnames are the default
+       for ( int i = 0; i < 12; ++i ) {
+           if ( monthName == ExtDate::my_shortMonthNames[i] ) {
+               month = i + 1;
+               break;
+           }
+       }
+       // If English names can't be found, search the localized ones
+       if ( month == -1 ) {
+           for ( int i = 1; i <= 12; ++i ) {
+               if ( monthName == ExtDate::shortMonthName( i ) ) {
+                   month = i;
+                   break;
+               }
+           }
+       }
+#if defined(QT_CHECK_RANGE)
+       if ( month < 1 || month > 12 ) {
+           qWarning( "ExtDateTime::fromString: Parameter out of range" );
+           ExtDateTime dt;
+           dt.d.jd = 0;
+           return dt;
+       }
+#endif
+       int day = s.mid( 8, 2 ).simplifyWhiteSpace().toInt();
+       int year = s.right( 4 ).toInt();
+       ExtDate date( year, month, day );
+       QTime time;
+       int hour, minute, second;
+       int pivot = s.find( QRegExp(QString::fromLatin1("[0-9][0-9]:[0-9][0-9]:[0-9][0-9]")) );
+       if ( pivot != -1 ) {
+           hour = s.mid( pivot, 2 ).toInt();
+           minute = s.mid( pivot+3, 2 ).toInt();
+           second = s.mid( pivot+6, 2 ).toInt();
+           time.setHMS( hour, minute, second );
+       }
+       return ExtDateTime( date, time );
+    }
+#endif //QT_NO_REGEXP
+    return ExtDateTime();
+}
+#endif //QT_NO_DATESTRING
+
+
+
+
+
+
+#ifndef QT_NO_DATASTREAM
+Q_EXPORT QDataStream &operator<<( QDataStream & ostream, const ExtDate & date)
+{
+       return ostream << (Q_UINT32)(date.jd);
+}
+
+Q_EXPORT QDataStream &operator>>( QDataStream & ostream, ExtDate & date)
+{
+       Q_UINT32 julday;
+       ostream >> julday;
+       date.jd = julday;
+       return ostream;
+}
+
+Q_EXPORT QDataStream &operator<<( QDataStream & ostream, const ExtDateTime & dt)
+{
+       return ostream << dt.d << dt.t;
+}
+
+Q_EXPORT QDataStream &operator>>( QDataStream & ostream, ExtDateTime & dt)
+{
+       ostream >> dt.d >> dt.t;
+       return ostream;
+}
+
+#endif // QT_NO_DATASTREAM
diff --git a/extdate/extdatetime.h b/extdate/extdatetime.h
new file mode 100644 (file)
index 0000000..488bbb4
--- /dev/null
@@ -0,0 +1,180 @@
+/*************************************************************************
+**
+** Definition of extended range date classe
+**
+** Created : 031102
+**
+** 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.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+**********************************************************************/
+
+#ifndef EXTDATETIME_H
+#define EXTDATETIME_H
+
+#ifndef QT_H
+#include "qstring.h"
+#include "qnamespace.h"
+#include "qdatetime.h"
+#endif // QT_H
+
+
+/*****************************************************************************
+  ExtDate class
+ *****************************************************************************/
+
+extern void test2_unit(int y, int m, int d);
+
+class Q_EXPORT ExtDate
+{
+public:
+    ExtDate() { jd = my_invalid_day; }
+    ExtDate( int y, int m, int d );
+    ExtDate( const QDate &q ) { ExtDate( q.year(), q.month(), q.day() ); }
+    bool isNull() const { return jd == 0; }
+    bool isValid() const;
+
+    QDate qdate() const;
+
+    int year() const;
+    int month() const;
+    int day() const;
+    int dayOfWeek() const;
+    int dayOfYear() const;
+    int daysInMonth() const;
+    int daysInYear() const;
+    int weekNumber( int *yearNum = 0 ) const;
+
+#ifndef QT_NO_TEXTDATE
+#ifndef QT_NO_COMPAT
+    static QString monthName( int month ) { return shortMonthName( month ); }
+    static QString dayName( int weekday ) { return shortDayName( weekday ); }
+#endif
+    static QString shortMonthName( int month );
+    static QString shortDayName( int weekday );
+    static QString longMonthName( int month );
+    static QString longDayName( int weekday );
+#endif //QT_NO_TEXTDATE
+#ifndef QT_NO_TEXTSTRING
+#if !defined(QT_NO_SPRINTF)
+    QString toString( Qt::DateFormat f = Qt::TextDate ) const;
+#endif
+    QString toString( const QString& format ) const;
+#endif
+    bool   setYMD( int y, int m, int d );
+
+    ExtDate  addDays( int days )               const;
+    ExtDate  addMonths( int months )      const;
+    ExtDate  addYears( int years )        const;
+    int           daysTo( const ExtDate & )    const;
+
+    bool   operator==( const ExtDate &d ) const { return jd == d.jd; };
+    bool   operator!=( const ExtDate &d ) const { return jd != d.jd; };
+    bool   operator<( const ExtDate &d )       const { return jd < d.jd; };
+    bool   operator<=( const ExtDate &d ) const { return jd <= d.jd; };
+    bool   operator>( const ExtDate &d )       const { return jd > d.jd; };
+    bool   operator>=( const ExtDate &d ) const { return jd >= d.jd; };
+
+    static ExtDate currentDate( Qt::TimeSpec ts = Qt::LocalTime );
+#ifndef QT_NO_DATESTRING
+    static ExtDate fromString( const QString& s, Qt::DateFormat f = Qt::TextDate );
+#endif
+    static bool         isValid( int y, int m, int d );
+    static bool         leapYear( int year );
+
+    static uint         gregorianToJulian( int y, int m, int d );
+    static void         julianToGregorian( uint jd, int &y, int &m, int &d );
+private:
+    int         jd;
+    void   set_jd(int the_jd) {jd = the_jd;};
+    static int month_length[12];
+    static int month_origin[12];
+    static QString my_shortMonthNames[12];
+    static QString my_shortDayNames[7];
+    static QString my_longMonthNames[12];
+    static QString my_longDayNames[7];
+    QString toStringSimpleArg( char code, int nb ) const;
+
+    static int my_invalid_day;
+    friend class ExtDateTime;
+    static int dayOfYear(int y, int m, int d);
+    static int dayRank(int y, int m, int d);
+#ifndef QT_NO_DATASTREAM
+    friend Q_EXPORT QDataStream &operator<<( QDataStream &, const ExtDate & );
+    friend Q_EXPORT QDataStream &operator>>( QDataStream &, ExtDate & );
+    friend Q_EXPORT QDataStream &operator<<( QDataStream &, const ExtDateTime & );
+    friend Q_EXPORT QDataStream &operator>>( QDataStream &, ExtDateTime & );
+#endif
+};
+
+/*****************************************************************************
+  ExtDateTime class
+ *****************************************************************************/
+
+class Q_EXPORT ExtDateTime
+{
+public:
+    ExtDateTime() {}                           // set null date and null time
+    ExtDateTime( const ExtDate & );
+    ExtDateTime( const ExtDate &, const QTime & );
+
+    bool   isNull()    const           { return d.isNull() && t.isNull(); }
+    bool   isValid()   const           { return d.isValid() && t.isValid(); }
+
+    ExtDate  date()    const           { return d; }
+    QTime  time()      const           { return t; }
+    uint   toTime_t()  const;
+    void   setDate( const ExtDate &date ) { d = date; }
+    void   setTime( const QTime &time ) { t = time; }
+    void   setTime_t( uint secsSince1Jan1970UTC );
+    void   setTime_t( uint secsSince1Jan1970UTC, Qt::TimeSpec );
+#ifndef QT_NO_DATESTRING
+#ifndef QT_NO_SPRINTF
+    QString toString( Qt::DateFormat f = Qt::TextDate )        const;
+#endif
+    QString toString( const QString& format ) const;
+#endif
+    ExtDateTime addDays( int days )    const;
+    ExtDateTime addMonths( int months )   const;
+    ExtDateTime addYears( int years )     const;
+    ExtDateTime addSecs( int secs )    const;
+    int           daysTo( const ExtDateTime & )        const;
+    int           secsTo( const ExtDateTime & )        const;
+
+    bool   operator==( const ExtDateTime &dt ) const;
+    bool   operator!=( const ExtDateTime &dt ) const;
+    bool   operator<( const ExtDateTime &dt )  const;
+    bool   operator<=( const ExtDateTime &dt ) const;
+    bool   operator>( const ExtDateTime &dt )  const;
+    bool   operator>=( const ExtDateTime &dt ) const;
+
+    static ExtDateTime currentDateTime();
+    static ExtDateTime currentDateTime( Qt::TimeSpec );
+#ifndef QT_NO_DATESTRING
+    static ExtDateTime fromString( const QString& s, Qt::DateFormat f = Qt::TextDate );
+#endif
+private:
+    ExtDate  d;
+    QTime  t;
+#ifndef QT_NO_DATASTREAM
+    friend Q_EXPORT QDataStream &operator<<( QDataStream &, const ExtDateTime &);
+    friend Q_EXPORT QDataStream &operator>>( QDataStream &, ExtDateTime & );
+#endif
+};
+
+/*****************************************************************************
+  Date and time stream functions
+ *****************************************************************************/
+
+#ifndef QT_NO_DATASTREAM
+Q_EXPORT QDataStream &operator<<( QDataStream &, const ExtDate & );
+Q_EXPORT QDataStream &operator>>( QDataStream &, ExtDate & );
+#endif // QT_NO_DATASTREAM
+
+#endif // EXTDATE_H
+
diff --git a/extdate/extdatetimeedit.cpp b/extdate/extdatetimeedit.cpp
new file mode 100644 (file)
index 0000000..f003936
--- /dev/null
@@ -0,0 +1,2734 @@
+/****************************************************************************
+**
+**
+** Implementation of date and time edit classes
+**
+** Created : 001103
+**
+** 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 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.
+**
+** 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.
+**
+**********************************************************************/
+
+#include "extdatetimeedit.h"
+
+#ifndef QT_NO_DATETIMEEDIT
+
+//#include "../kernel/qinternal_p.h"
+//#include "../kernel/qrichtext_p.h"
+#include <private/qinternal_p.h>
+#include <private/qrichtext_p.h>
+#include <qrangecontrol.h>
+#include <qapplication.h>
+#include <qpixmap.h>
+#include <qapplication.h>
+#include <qvaluelist.h>
+#include <qstring.h>
+#include <qstyle.h>
+#include <qdatetimeedit.h> //need for QTimeEdit
+
+#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
+    }
+
+#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;
+       }
+    }
+#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;
+}
+
+class ExtDateTimeEditorPrivate
+{
+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();
+    }
+
+    void appendSection( const QNumberSection& sec )
+    {
+       sections.append( sec );
+
+    }
+    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; }
+
+    void setFrame( bool f ) { frm = f; }
+    bool frame() const { return frm; }
+
+    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;
+    }
+
+    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;
+    }
+
+    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();
+    }
+
+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;
+    QValueList< QNumberSection > sections;
+    QString sep;
+    int offset;
+};
+
+class ExtDateTimeSpinWidget : public QSpinWidget
+{
+public:
+    ExtDateTimeSpinWidget( QWidget *parent, const char *name )
+       : QSpinWidget( parent, name )
+    {
+    }
+
+protected:
+#ifndef QT_NO_WHEELEVENT
+    void wheelEvent( QWheelEvent *e )
+    {
+       ExtDateTimeEditor *editor = (ExtDateTimeEditor*)editWidget()->qt_cast( "ExtDateTimeEditor" );
+       Q_ASSERT( editor );
+       if ( !editor )
+           return;
+
+       int section = editor->sectionAt( e->pos() );
+       editor->setFocusSection( section );
+
+       if ( section == -1 )
+           return;
+       QSpinWidget::wheelEvent( e );
+    }
+#endif
+};
+
+/*!
+    Constructs an empty datetime editor with parent \a parent and
+    called \a name.
+*/
+ExtDateTimeEditor::ExtDateTimeEditor( ExtDateTimeEditBase * parent,
+                                 const char * name )
+    : QWidget( parent, name, WNoAutoErase )
+{
+    d = new ExtDateTimeEditorPrivate();
+    cw = parent;
+    init();
+}
+
+/*!
+    Destroys the object and frees any allocated resources.
+*/
+
+ExtDateTimeEditor::~ExtDateTimeEditor()
+{
+    delete d;
+}
+
+/*! \internal
+
+*/
+
+void ExtDateTimeEditor::init()
+{
+    setBackgroundMode( PaletteBase );
+    setFocusSection( -1 );
+    installEventFilter( this );
+    setFocusPolicy( WheelFocus );
+}
+
+
+/*! \reimp
+
+*/
+
+bool ExtDateTimeEditor::event( QEvent *e )
+{
+    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;
+       }
+    }
+    return QWidget::event( e );
+}
+
+/*! \reimp
+
+*/
+
+void ExtDateTimeEditor::resizeEvent( QResizeEvent *e )
+{
+    d->resize( e->size() );
+    QWidget::resizeEvent( e );
+}
+
+
+/*! \reimp
+
+*/
+
+void ExtDateTimeEditor::paintEvent( QPaintEvent * )
+{
+    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 += " ";
+       }
+    }
+
+    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();
+}
+
+
+/*!
+    Returns the section index at point \a p.
+*/
+int ExtDateTimeEditor::sectionAt( const QPoint &p )
+{
+    return d->section( p );
+}
+
+int ExtDateTimeEditor::mapSection( int sec )
+{
+    return d->mapSection( sec );
+}
+
+
+/*! \reimp
+
+*/
+
+void ExtDateTimeEditor::mousePressEvent( QMouseEvent *e )
+{
+    QPoint p( e->pos().x(), 0 );
+    int sec = sectionAt( p );
+    if ( sec != -1 ) {
+       cw->setFocusSection( sec );
+       repaint( rect(), FALSE );
+    }
+}
+
+/*! \reimp
+
+*/
+bool ExtDateTimeEditor::eventFilter( QObject *o, QEvent *e )
+{
+    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<QTimeEdit*>(cw) )
+                   ((QTimeEdit*)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;
+
+               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();
+               }
+
+               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();
+                       }
+                   }
+
+                   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<QTimeEdit*>(cw) && focusSection() == (int) d->sectionCount()-1 ) {
+                   // the first character of the AM/PM indicator toggles if the section has focus
+                   QTimeEdit *te = (QTimeEdit*)cw;
+                   QTime time = te->time();
+                   if ( lAMPM && lAM && lPM && (te->display()&QTimeEdit::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 );
+                       }
+                   }
+               }
+
+               int num = txt[0].digitValue();
+               if ( num != -1 ) {
+                   cw->addNumber( d->focusSection(), num );
+                   return TRUE;
+               }
+           }
+       }
+    }
+    return FALSE;
+}
+
+
+/*!
+    Appends the number section \a sec to the editor.
+*/
+
+void ExtDateTimeEditor::appendSection( const QNumberSection& sec )
+{
+    d->appendSection( sec );
+}
+
+/*!
+    Removes all sections from the editor.
+*/
+
+void ExtDateTimeEditor::clearSections()
+{
+    d->clearSections();
+}
+
+/*!
+    Sets the selection of \a sec to start at \a selstart and end at \a
+    selend.
+*/
+
+void ExtDateTimeEditor::setSectionSelection( int sec, int selstart, int selend )
+{
+    d->setSectionSelection( sec, selstart, selend );
+}
+
+/*!
+    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 )
+{
+    d->setSeparator( s );
+    update();
+}
+
+
+/*!
+    Returns the editor's separator.
+*/
+
+QString ExtDateTimeEditor::separator() const
+{
+    return d->separator();
+}
+
+/*!
+    Returns the number of the section that has focus.
+*/
+
+int ExtDateTimeEditor::focusSection() const
+{
+    return d->focusSection();
+}
+
+
+/*!
+    Sets the focus to section \a sec. If \a sec does not exist,
+    nothing happens.
+*/
+
+bool ExtDateTimeEditor::setFocusSection( int sec )
+{
+    return d->setFocusSection( sec );
+}
+
+/*! \class ExtDateTimeEditBase ExtDatetimeedit.h
+    \brief The ExtDateTimeEditBase class provides an abstraction for date and edit editors.
+    \internal
+
+    Small abstract class that provides some functions that are common
+    for both ExtDateEdit and QTimeEdit. Its used internally by
+    ExtDateTimeEditor.
+*/
+
+/*! \fn QString ExtDateTimeEditBase::sectionFormattedText( int sec )
+    \internal
+
+  Pure virtual function which returns the formatted text of section \a
+  sec.
+
+*/
+
+/*! \fn void ExtDateTimeEditBase::stepUp()
+    \internal
+
+  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.
+*/
+
+/*! \fn void ExtDateTimeEditBase::stepDown()
+    \internal
+
+  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.
+
+*/
+
+/*! \fn void ExtDateTimeEditBase::addNumber( int sec, int num )
+    \internal
+
+  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.
+*/
+
+/*! \fn void ExtDateTimeEditBase::removeLastNumber( int sec )
+    \internal
+
+  Pure virtual function which is called whenever the user tries to
+  remove the last number from \a sec by pressing the delete key.
+*/
+
+////////////////
+
+class ExtDateEditPrivate
+{
+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;
+    QSpinWidget *controls;
+};
+
+
+/*!
+    \class ExtDateEdit ExtDatetimeedit.h
+    \brief The ExtDateEdit class provides a date editor.
+
+    \ingroup advanced
+    \ingroup time
+    \mainclass
+
+    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.
+
+    \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
+
+    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.
+
+    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().
+
+    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 "-".
+
+    \img datetimewidgets.png Date Time Widgets
+
+    \sa ExtDate QTimeEdit ExtDateTimeEdit
+*/
+
+/*!
+    \enum ExtDateEdit::Order
+
+    This enum defines the order in which the sections that comprise a
+    date appear.
+    \value MDY month-day-year
+    \value DMY day-month-year
+    \value YMD year-month-day (the default)
+    \value YDM year-day-month (included for completeness; but should
+    not be used)
+*/
+
+/*!
+    \enum QTimeEdit::Display
+
+    This enum defines the sections that comprise a time
+
+    \value Hours The hours section
+    \value Minutes The minutes section
+    \value Seconds The seconds section
+    \value AMPM The AM/PM section
+
+    The values can be or'ed together to show any combination.
+*/
+
+/*!
+    Constructs an empty date editor which is a child of \a parent and
+    called name \a name.
+*/
+
+ExtDateEdit::ExtDateEdit( QWidget * parent, const char * name )
+    : ExtDateTimeEditBase( parent, name )
+{
+    init();
+    updateButtons();
+}
+
+/*!
+    \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.
+*/
+
+ExtDateEdit::ExtDateEdit( const ExtDate& date, QWidget * parent, const char * name )
+    : ExtDateTimeEditBase( parent, name )
+{
+    init();
+    setDate( date );
+}
+
+/*! \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 ) );
+
+    d->yearSection = -1;
+    d->monthSection = -1;
+    d->daySection = -1;
+
+    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( 1752, 9, 14 );
+    d->max = ExtDate( 8000, 12, 31 );
+    d->changed = FALSE;
+
+    setSizePolicy( QSizePolicy::Minimum, QSizePolicy::Fixed );
+
+    refcount++;
+}
+
+/*!
+    Destroys the object and frees any allocated resources.
+*/
+
+ExtDateEdit::~ExtDateEdit()
+{
+    delete d;
+    if ( !--refcount )
+       cleanup();
+}
+
+/*!
+    \property ExtDateEdit::minValue
+
+    \brief the editor's minimum value
+
+    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.
+
+    \sa maxValue setRange()
+*/
+
+ExtDate ExtDateEdit::minValue() const
+{
+    return d->min;
+}
+
+/*!
+    \property ExtDateEdit::maxValue
+
+    \brief the editor's maximum value
+
+    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()
+*/
+
+ExtDate ExtDateEdit::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 date will be set.
+    Similarly, if \a max is invalid no maximum date will be set.
+*/
+
+void ExtDateEdit::setRange( const ExtDate& min, const ExtDate& max )
+{
+    if ( min.isValid() )
+       d->min = min;
+    if ( max.isValid() )
+       d->max = max;
+}
+
+/*!
+    Sets the separator to \a s. Note that currently only the first
+    character of \a s is used.
+*/
+
+void ExtDateEdit::setSeparator( const QString& s )
+{
+    d->ed->setSeparator( s );
+}
+
+/*!
+    Returns the editor's separator.
+*/
+
+QString ExtDateEdit::separator() const
+{
+    return d->ed->separator();
+}
+
+
+/*!
+    Enables/disables the push buttons according to the min/max date
+    for this widget.
+*/
+
+void ExtDateEdit::updateButtons()
+{
+    if ( !isEnabled() )
+       return;
+
+    bool upEnabled = date() < maxValue();
+    bool downEnabled = date() > minValue();
+
+    d->controls->setUpEnabled( upEnabled );
+    d->controls->setDownEnabled( downEnabled );
+}
+
+/*! \reimp
+ */
+void ExtDateEdit::resizeEvent( QResizeEvent * )
+{
+    d->controls->resize( width(), height() );
+}
+
+/*! \reimp
+
+*/
+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() );
+}
+
+/*! \reimp
+
+*/
+QSize ExtDateEdit::minimumSizeHint() const
+{
+    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()
+*/
+
+QString ExtDateEdit::sectionFormattedText( int sec )
+{
+    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.
+
+    \sa setOrder()
+*/
+
+int ExtDateEdit::sectionLength( int sec ) const
+{
+    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;
+}
+
+/*!
+    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()
+*/
+
+QString ExtDateEdit::sectionText( int sec ) const
+{
+    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 );
+}
+
+/*! \internal
+
+  Returns the end of the section offset \a sec.
+
+*/
+
+int ExtDateEdit::sectionOffsetEnd( int sec ) const
+{
+    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 );
+       }
+    } 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 );
+       }
+    } 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 );
+       }
+    }
+    return 0;
+}
+
+
+/*!
+    \property ExtDateEdit::order
+    \brief the order in which the year, month and day appear
+
+    The default order is locale dependent.
+
+    \sa Order
+*/
+
+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 );
+}
+
+
+ExtDateEdit::Order ExtDateEdit::order() const
+{
+    return d->ord;
+}
+
+
+/*! \reimp
+
+*/
+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 );
+       }
+    } 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 ( accepted ) {
+       d->changed = TRUE;
+       emit valueChanged( date() );
+    }
+    d->ed->repaint( d->ed->rect(), FALSE );
+}
+
+
+
+/*! \reimp
+
+*/
+
+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 );
+       }
+    } 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 ( accepted ) {
+       d->changed = TRUE;
+       emit valueChanged( date() );
+    }
+    d->ed->repaint( d->ed->rect(), FALSE );
+}
+
+/*!
+    Sets the year to \a year, which must be a valid year. The range
+    currently supported is from 1752 to 8000.
+
+    \sa ExtDate
+*/
+
+void ExtDateEdit::setYear( int year )
+{
+    if ( year < 1752 )
+       year = 1752;
+    if ( year > 8000 )
+       year = 8000;
+    if ( !outOfRange( year, d->m, d->d ) ) {
+       d->y = year;
+       setMonth( d->m );
+       int tmp = d->dayCache;
+       setDay( d->dayCache );
+       d->dayCache = tmp;
+    }
+}
+
+
+/*!
+    Sets the month to \a month, which must be a valid month, i.e.
+    between 1 and 12.
+*/
+
+void ExtDateEdit::setMonth( int month )
+{
+    if ( month < 1 )
+       month = 1;
+    if ( month > 12 )
+       month = 12;
+    if ( !outOfRange( d->y, month, d->d ) ) {
+       d->m = month;
+       int tmp = d->dayCache;
+       setDay( d->dayCache );
+       d->dayCache = tmp;
+    }
+}
+
+
+/*!
+    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.
+*/
+
+void ExtDateEdit::setDay( int day )
+{
+    if ( day < 1 )
+       day = 1;
+    if ( day > 31 )
+       day = 31;
+    if ( d->m > 0 && d->y > 1752 ) {
+       while ( !ExtDate::isValid( d->y, d->m, day ) )
+           --day;
+       if ( !outOfRange( d->y, d->m, day ) )
+           d->d = day;
+    } else if ( d->m > 0 ) {
+       if ( day > 0 && day < 32 ) {
+           if ( !outOfRange( d->y, d->m, day ) )
+               d->d = day;
+       }
+    }
+    d->dayCache = d->d;
+}
+
+
+/*!
+    \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.
+
+    When changing the date property, if the date is less than
+    minValue(), or is greater than maxValue(), nothing happens.
+*/
+
+void ExtDateEdit::setDate( const ExtDate& date )
+{
+    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:
+
+    \list
+    \i If the year has four digits it is left unchanged.
+    \i If the year has two digits, the year will be changed to four
+    digits in the range current year - 70 to current year + 29.
+    \i 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.
+    \endlist
+
+*/
+
+void ExtDateEdit::fix()
+{
+    bool changed = FALSE;
+    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;
+    }
+}
+
+
+/*! \reimp
+
+*/
+
+bool ExtDateEdit::event( QEvent *e )
+{
+    if( e->type() == QEvent::FocusOut ) {
+       d->typing = FALSE;
+       fix();
+       // 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;
+       }
+       if ( d->changed ) {
+           emit valueChanged( date() );
+           d->changed = FALSE;
+       }
+    } else if ( e->type() == QEvent::LocaleChange ) {
+       readLocaleSettings();
+       d->ed->setSeparator( localDateSep() );
+       setOrder( localOrder() );
+    }
+    return ExtDateTimeEditBase::event( e );
+}
+
+/*!
+  \internal
+
+  Function which is called whenever the user tries to
+  remove the first number from \a sec by pressing the backspace key.
+*/
+
+void ExtDateEdit::removeFirstNumber( int sec )
+{
+    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;
+    }
+    d->ed->repaint( d->ed->rect(), FALSE );
+}
+
+/*! \reimp
+
+*/
+
+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;
+    }
+    d->ed->repaint( d->ed->rect(), FALSE );
+}
+
+/*!
+    \property ExtDateEdit::autoAdvance
+    \brief whether the editor automatically advances to the next
+    section
+
+    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.
+*/
+
+void ExtDateEdit::setAutoAdvance( bool advance )
+{
+    d->adv = advance;
+}
+
+
+bool ExtDateEdit::autoAdvance() const
+{
+    return d->adv;
+}
+
+/*! \reimp
+*/
+
+void ExtDateEdit::timerEvent( QTimerEvent * )
+{
+    d->overwrite = TRUE;
+}
+
+/*!
+    \fn void ExtDateEdit::valueChanged( const ExtDate& date )
+
+    This signal is emitted whenever the editor's value changes. The \a
+    date parameter is the new value.
+*/
+
+///////////
+
+class QTimeEditPrivate
+{
+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;
+    QSpinWidget *controls;
+};
+
+/*!
+    \class QTimeEdit ExtDatetimeedit.h
+    \brief The QTimeEdit class provides a time editor.
+
+    \ingroup advanced
+    \ingroup time
+    \mainclass
+
+    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
+{
+public:
+    bool adv;
+};
+
+/*!
+    \class ExtDateTimeEdit ExtDatetimeedit.h
+    \brief The ExtDateTimeEdit class combines a ExtDateEdit and QTimeEdit
+    widget into a single widget for editing datetimes.
+
+    \ingroup advanced
+    \ingroup time
+    \mainclass
+
+    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().
+
+    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.
+
+    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.
+
+    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.
+
+    \img datetimewidgets.png Date Time Widgets
+
+    \sa ExtDateEdit QTimeEdit
+*/
+
+/*!
+    Constructs an empty datetime edit with parent \a parent and called
+    \a name.
+*/
+ExtDateTimeEdit::ExtDateTimeEdit( QWidget * parent, const char * name )
+    : QWidget( parent, name )
+{
+    init();
+}
+
+
+/*!
+    \overload
+
+    Constructs a datetime edit with the initial value \a datetime,
+    parent \a parent and called \a name.
+*/
+ExtDateTimeEdit::ExtDateTimeEdit( const ExtDateTime& datetime,
+                             QWidget * parent, const char * name )
+    : QWidget( parent, name )
+{
+    init();
+    setDateTime( datetime );
+}
+
+
+
+/*!
+    Destroys the object and frees any allocated resources.
+*/
+
+ExtDateTimeEdit::~ExtDateTimeEdit()
+{
+    delete d;
+}
+
+
+/*!
+    \reimp
+
+    Intercepts and handles resize events which have special meaning
+    for the ExtDateTimeEdit.
+*/
+
+void ExtDateTimeEdit::resizeEvent( QResizeEvent * )
+{
+    int dw = de->sizeHint().width();
+    int tw = te->sizeHint().width();
+    int w = width();
+    int h = height();
+    int extra = w - ( dw + tw );
+
+    if ( tw + extra < 0 ) {
+       dw = w;
+    } else {
+       dw += 9 * extra / 16;
+    }
+    tw = w - dw;
+
+    de->setGeometry( 0, 0, dw, h );
+    te->setGeometry( dw, 0, tw, h );
+}
+
+/*! \reimp
+*/
+
+QSize ExtDateTimeEdit::minimumSizeHint() const
+{
+    QSize dsh = de->minimumSizeHint();
+    QSize tsh = te->minimumSizeHint();
+    return QSize( dsh.width() + tsh.width(),
+                 QMAX( dsh.height(), tsh.height() ) );
+}
+
+/*!  \internal
+ */
+
+void ExtDateTimeEdit::init()
+{
+    d = new ExtDateTimeEditPrivate();
+    de = new ExtDateEdit( this, "qt_datetime_dateedit" );
+    te = new QTimeEdit( 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 );
+}
+
+/*! \reimp
+ */
+
+QSize ExtDateTimeEdit::sizeHint() const
+{
+    constPolish();
+    QSize dsh = de->sizeHint();
+    QSize tsh = te->sizeHint();
+    return QSize( dsh.width() + tsh.width(),
+                 QMAX( dsh.height(), tsh.height() ) );
+}
+
+/*!
+    \property ExtDateTimeEdit::dateTime
+    \brief the editor's datetime value
+
+    The datetime edit's datetime which may be an invalid datetime.
+*/
+
+void ExtDateTimeEdit::setDateTime( const ExtDateTime & dt )
+{
+    if ( dt.isValid() ) {
+       de->setDate( dt.date() );
+       te->setTime( dt.time() );
+       emit valueChanged( dt );
+    }
+}
+
+ExtDateTime ExtDateTimeEdit::dateTime() const
+{
+    return ExtDateTime( de->date(), te->time() );
+}
+
+/*!
+    \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
+
+  Re-emits the value \a d.
+ */
+
+void ExtDateTimeEdit::newValue( const ExtDate& )
+{
+    ExtDateTime dt = dateTime();
+    emit valueChanged( dt );
+}
+
+/*! \internal
+  \overload
+  Re-emits the value \a t.
+ */
+
+void ExtDateTimeEdit::newValue( const QTime& )
+{
+    ExtDateTime dt = dateTime();
+    emit valueChanged( dt );
+}
+
+
+/*!
+    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.
+*/
+
+void ExtDateTimeEdit::setAutoAdvance( bool advance )
+{
+    de->setAutoAdvance( advance );
+    te->setAutoAdvance( advance );
+}
+
+/*!
+    Returns TRUE if auto-advance is enabled, otherwise returns FALSE.
+
+    \sa setAutoAdvance()
+*/
+
+bool ExtDateTimeEdit::autoAdvance() const
+{
+    return de->autoAdvance();
+}
+
+/*!
+    \fn ExtDateEdit* ExtDateTimeEdit::dateEdit()
+
+    Returns the internal widget used for editing the date part of the
+    datetime.
+*/
+
+/*!
+    \fn QTimeEdit* ExtDateTimeEdit::timeEdit()
+
+    Returns the internal widget used for editing the time part of the
+    datetime.
+*/
+
+#include "extdatetimeedit.moc"
+
+#endif
diff --git a/extdate/extdatetimeedit.h b/extdate/extdatetimeedit.h
new file mode 100644 (file)
index 0000000..838810b
--- /dev/null
@@ -0,0 +1,339 @@
+/****************************************************************************
+**
+**
+** Definition of date and time edit classes
+**
+** Created : 001103
+**
+** Original QDateTimeEdit Copyright (C) 2000 Trolltech AS.  All rights reserved.
+**
+** >> 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 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.
+**
+** 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"
+#include "extdatetimeeditor.h"
+
+#ifndef QT_NO_DATETIMEEDIT
+
+class QTimeEdit;
+
+class ExtDateTimeEditBase : public QWidget
+{
+    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 Q_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 )
+
+public:
+    ExtDateEdit( QWidget* parent=0,  const char* name=0 );
+    ExtDateEdit( const ExtDate& date, QWidget* parent=0,  const char* name=0 );
+    ~ExtDateEdit();
+
+    enum Order { DMY, MDY, YMD, YDM };
+
+    QSize sizeHint() const;
+    QSize minimumSizeHint() const;
+
+public slots:
+    virtual void setDate( const ExtDate& date );
+
+public:
+    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 );
+
+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();
+
+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
+};
+
+// 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
+// };
+//
+
+class ExtDateTimeEditPrivate;
+
+class Q_EXPORT ExtDateTimeEdit : public QWidget
+{
+    Q_OBJECT
+//    Q_PROPERTY( ExtDateTime dateTime READ dateTime WRITE setDateTime )
+
+public:
+    ExtDateTimeEdit( QWidget* parent=0, const char* name=0 );
+    ExtDateTimeEdit( const ExtDateTime& datetime, QWidget* parent=0,
+                  const char* name=0 );
+    ~ExtDateTimeEdit();
+
+    QSize sizeHint() const;
+    QSize minimumSizeHint() const;
+
+public slots:
+    virtual void setDateTime( const ExtDateTime & dt );
+
+public:
+    ExtDateTime dateTime() const;
+
+    ExtDateEdit* dateEdit() { return de; }
+    QTimeEdit* timeEdit() { return te; }
+
+    virtual void setAutoAdvance( bool advance );
+    bool autoAdvance() const;
+
+signals:
+    void valueChanged( const ExtDateTime& datetime );
+
+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 );
+
+private:
+    ExtDateEdit* de;
+    QTimeEdit* te;
+    ExtDateTimeEditPrivate* d;
+
+#if defined(Q_DISABLE_COPY)
+    ExtDateTimeEdit( const ExtDateTimeEdit & );
+    ExtDateTimeEdit &operator=( const ExtDateTimeEdit & );
+#endif
+};
+
+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;
+};
+
+class ExtDateTimeEditorPrivate;
+
+class ExtDateTimeEditor : public QWidget
+{
+    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;
+
+    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 );
+
+protected:
+    void init();
+    bool event( QEvent *e );
+    void resizeEvent( QResizeEvent * );
+    void paintEvent( QPaintEvent * );
+    void mousePressEvent( QMouseEvent *e );
+
+private:
+    ExtDateTimeEditBase* cw;
+    ExtDateTimeEditorPrivate* d;
+};
+
+#endif
+#endif
diff --git a/extdate/extdatewidget.cpp b/extdate/extdatewidget.cpp
new file mode 100644 (file)
index 0000000..511a7b2
--- /dev/null
@@ -0,0 +1,180 @@
+/*  This file is part of the KDE libraries
+    Copyright (C) 2001 Waldo Bastian (bastian@kde.org)
+
+    Modified to use ExtDate instead of QDate.  Modifications
+    Copyright (C) 2004 Jason Harris (jharris@30doradus.org)
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Library General Public
+    License version 2 as published by the Free Software Foundation.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Library General Public License for more details.
+
+    You should have received a copy of the GNU Library General Public License
+    along with this library; see the file COPYING.LIB.  If not, write to
+    the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+    Boston, MA 02111-1307, USA.
+*/
+
+
+#include <qpopupmenu.h>
+#include <qcombobox.h>
+#include <qlayout.h>
+#include <qlineedit.h>
+
+#include <knuminput.h>
+#include <kglobal.h>
+#include <klocale.h>
+#include <kdialog.h>
+
+#include "extdatewidget.h"
+#include "extcalendarsystem.h"
+#include "extcalendarsystemgregorian.h"
+
+class ExtDateWidgetSpinBox : public QSpinBox
+{
+public:
+  ExtDateWidgetSpinBox(int min, int max, QWidget *parent)
+    : QSpinBox(min, max, 1, parent)
+  {
+     editor()->setAlignment(AlignRight);
+  }
+};
+
+class ExtDateWidget::ExtDateWidgetPrivate
+{
+public:
+   ExtDateWidgetPrivate() { calendar = new ExtCalendarSystemGregorian(); }
+   ~ExtDateWidgetPrivate() { delete calendar; }
+   ExtDateWidgetSpinBox *m_day;
+   QComboBox *m_month;
+   ExtDateWidgetSpinBox *m_year;
+   ExtDate m_dat;
+   ExtCalendarSystemGregorian *calendar;
+};
+
+
+ExtDateWidget::ExtDateWidget( QWidget *parent, const char *name )
+  : QWidget( parent, name )
+{
+  init(ExtDate());
+  setDate(ExtDate());
+}
+
+ExtDateWidget::ExtDateWidget( const ExtDate &date, QWidget *parent,
+                           const char *name )
+  : QWidget( parent, name )
+{
+  init(date);
+  setDate(date);
+}
+
+// // ### CFM Repaced by init(const ExtDate&). Can be safely removed
+// //     when no risk of BIC
+// void ExtDateWidget::init()
+// {
+//   d = new ExtDateWidgetPrivate;
+//   KLocale *locale = KGlobal::locale();
+//   QHBoxLayout *layout = new QHBoxLayout(this, 0, KDialog::spacingHint());
+//   layout->setAutoAdd(true);
+//   d->m_day = new ExtDateWidgetSpinBox(1, 1, this);
+//   d->m_month = new QComboBox(false, this);
+//   for (int i = 1; ; ++i)
+//   {
+//     QString str = d->calendar->monthName(i,
+//        d->calendar->year(ExtDate()));
+//     if (str.isNull()) break;
+//     d->m_month->insertItem(str);
+//   }
+//
+//   d->m_year = new ExtDateWidgetSpinBox(d->calendar->minValidYear(),
+//                                  d->calendar->maxValidYear(), this);
+//
+//   connect(d->m_day, SIGNAL(valueChanged(int)), this, SLOT(slotDateChanged()));
+//   connect(d->m_month, SIGNAL(activated(int)), this, SLOT(slotDateChanged()));
+//   connect(d->m_year, SIGNAL(valueChanged(int)), this, SLOT(slotDateChanged()));
+// }
+
+void ExtDateWidget::init(const ExtDate& date)
+{
+  d = new ExtDateWidgetPrivate;
+  KLocale *locale = KGlobal::locale();
+  QHBoxLayout *layout = new QHBoxLayout(this, 0, KDialog::spacingHint());
+  layout->setAutoAdd(true);
+  d->m_day = new ExtDateWidgetSpinBox(1, 1, this);
+  d->m_month = new QComboBox(false, this);
+  for (int i = 1; ; ++i)
+  {
+    QString str = d->calendar->monthName(i,
+       d->calendar->year(date));
+    if (str.isNull()) break;
+    d->m_month->insertItem(str);
+  }
+
+  d->m_year = new ExtDateWidgetSpinBox(d->calendar->minValidYear(),
+                                    d->calendar->maxValidYear(), this);
+
+  connect(d->m_day, SIGNAL(valueChanged(int)), this, SLOT(slotDateChanged()));
+  connect(d->m_month, SIGNAL(activated(int)), this, SLOT(slotDateChanged()));
+  connect(d->m_year, SIGNAL(valueChanged(int)), this, SLOT(slotDateChanged()));
+}
+
+ExtDateWidget::~ExtDateWidget()
+{
+}
+
+void ExtDateWidget::setDate( const ExtDate &date )
+{
+//  const KCalendarSystem * calendar = KGlobal::locale()->calendar();
+
+  d->m_day->blockSignals(true);
+  d->m_month->blockSignals(true);
+  d->m_year->blockSignals(true);
+
+  d->m_day->setMaxValue(d->calendar->daysInMonth(date));
+  d->m_day->setValue(d->calendar->day(date));
+  d->m_month->setCurrentItem(d->calendar->month(date)-1);
+  d->m_year->setValue(d->calendar->year(date));
+
+  d->m_day->blockSignals(false);
+  d->m_month->blockSignals(false);
+  d->m_year->blockSignals(false);
+
+  d->m_dat = date;
+  emit changed(d->m_dat);
+}
+
+ExtDate ExtDateWidget::date() const
+{
+  return d->m_dat;
+}
+
+void ExtDateWidget::slotDateChanged( )
+{
+//  const KCalendarSystem * calendar = KGlobal::locale()->calendar();
+
+  ExtDate date;
+  int y,m,day;
+
+  y = d->m_year->value();
+  y = QMIN(QMAX(y, d->calendar->minValidYear()), d->calendar->maxValidYear());
+
+  d->calendar->setYMD(date, y, 1, 1);
+  m = d->m_month->currentItem()+1;
+  m = QMIN(QMAX(m,1), d->calendar->monthsInYear(date));
+
+  d->calendar->setYMD(date, y, m, 1);
+  day = d->m_day->value();
+  day = QMIN(QMAX(day,1), d->calendar->daysInMonth(date));
+
+  d->calendar->setYMD(date, y, m, day);
+  setDate(date);
+}
+
+void ExtDateWidget::virtual_hook( int, void* )
+{ /*BASE::virtual_hook( id, data );*/ }
+
+#include "extdatewidget.moc"
diff --git a/extdate/extdatewidget.h b/extdate/extdatewidget.h
new file mode 100644 (file)
index 0000000..bbd285e
--- /dev/null
@@ -0,0 +1,90 @@
+/* This file is part of the KDE libraries
+    Copyright (C) 2001 Waldo Bastian (bastian@kde.org)
+
+    Modified to use ExtDate instead of QDate.  Modifications
+    Copyright (C) 2004 Jason Harris (jharris@30doradus.org)
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Library General Public
+    License version 2 as published by the Free Software Foundation.
+
+    This library is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+    Library General Public License for more details.
+
+    You should have received a copy of the GNU Library General Public License
+    along with this library; see the file COPYING.LIB.  If not, write to
+    the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+    Boston, MA 02111-1307, USA.
+*/
+
+#ifndef __EXTDATEWIDGET_H__
+#define __EXTDATEWIDGET_H__
+
+#include <qwidget.h>
+#include "extdatetime.h"
+
+/**
+* This widget can be used to display or allow user selection of a date.
+*
+* @see ExtDatePicker
+*
+* @short A pushbutton to display or allow user selection of a date.
+* @version $Id$
+*/
+class ExtDateWidget : public QWidget
+{
+  Q_OBJECT
+//  Q_PROPERTY( ExtDate date READ date WRITE setDate )
+
+public:
+  /**
+   * Constructs a date selection widget.
+   */
+  ExtDateWidget( QWidget *parent=0, const char *name=0 );
+
+  /**
+   * Constructs a date selection widget with the initial date set to @p date.
+   */
+  ExtDateWidget( const ExtDate &date, QWidget *parent=0, const char *name=0 );
+
+  /**
+   * Destructs the date selection widget.
+   */
+  virtual ~ExtDateWidget();
+
+  /**
+   * Returns the currently selected date.
+   */
+  ExtDate date() const;
+
+  /**
+   * Changes the selected date to @p date.
+   */
+  void setDate(const ExtDate &date);
+
+
+signals:
+  /**
+   * Emitted whenever the date of the widget
+   * is changed, either with setDate() or via user selection.
+   */
+   void changed(ExtDate);
+
+protected:
+   void init();
+   void init(const ExtDate&);
+
+protected slots:
+  void slotDateChanged();
+
+protected:
+  virtual void virtual_hook( int id, void* data );
+private:
+   class ExtDateWidgetPrivate;
+   ExtDateWidgetPrivate *d;
+};
+
+#endif
+
diff --git a/extdate/main.cpp b/extdate/main.cpp
new file mode 100644 (file)
index 0000000..a7e51d3
--- /dev/null
@@ -0,0 +1,31 @@
+#include "testwidget.h"
+#include <kapplication.h>
+#include <kcmdlineargs.h>
+#include <kaboutdata.h>
+#include <klocale.h>
+
+static const char description[] = I18N_NOOP("ExtDatePicker test program");
+static const char notice[] = I18N_NOOP("Compares KDatePicker and ExtDatePicker");
+
+static KCmdLineOptions options[] =
+{
+       KCmdLineLastOption
+};
+
+int main( int argc, char *argv[] )
+{
+       KAboutData aboutData( "test_extdatepicker", I18N_NOOP("Test ExtDatePicker"),
+                               "0.1", description, KAboutData::License_GPL,
+                               I18N_NOOP("(c) 2004, Jason Harris"), notice,
+                               "http://30doradus.org");
+       aboutData.addAuthor("Jason Harris", 0,
+                               "jharris@30doradus.org", "http://www.30doradus.org");
+
+       KCmdLineArgs::init( argc, argv, &aboutData );
+
+       KApplication a;
+       TestWidget *t = new TestWidget(0,0);
+       t->show();
+       QObject::connect(kapp, SIGNAL(lastWindowClosed()), kapp, SLOT(quit()));
+       return a.exec();
+}
diff --git a/extdate/test_extdate.cc b/extdate/test_extdate.cc
new file mode 100644 (file)
index 0000000..8821770
--- /dev/null
@@ -0,0 +1,328 @@
+#include <iostream>
+#include <qstring.h>
+#include <qnamespace.h>
+#include <qdatetime.h>
+#include "extdatetime.h"
+
+
+void test1_unit(int a_year)
+{
+       std::cout << a_year << "  (QDate|ExtDate): " << ((QDate::leapYear(a_year)) ? "yes" : "no")
+                       <<"|"<< ((ExtDate::leapYear(a_year)) ? "yes" : "no") << std::endl;
+}
+
+void test1()
+{
+       int a_set_of_years[] =
+       {
+               1996,
+               1997,
+               1998,
+               2000,
+               1999,
+               2001,
+               1900,
+               1800,
+               1700,
+               1600,
+               2100,
+               2200,
+               2300,
+               0,
+               -1,
+               -4,
+               -100,
+               -200,
+               -300,
+               -400,
+               -500
+       };
+       uint i;
+       std::cout << "Checking Leap Years:\n" << std::endl;
+       for (i = 0 ; i < sizeof(a_set_of_years)/sizeof(a_set_of_years[0]) ; i++)
+       {
+               test1_unit(a_set_of_years[i]);
+       }
+       std::cout << "--------------------" << std::endl;
+}
+
+void test2_unit(int y, int m, int d)
+{
+       QDate   q(y, m, d);
+       ExtDate e(y, m, d);
+       int q_week_number = q.dayOfWeek();
+       int e_week_number = e.dayOfWeek();
+       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() << "  :  "
+               << e.toString("dd.MMM.yyyy").local8Bit() << "  :: "
+               << q.dayOfWeek() << " : " << e.dayOfWeek() << " :: "
+               << q_week_number << " : " << e_week_number << " :: "
+               << q_day_of_year << " : " << e_day_of_year << std::endl;
+}
+
+void test2()
+{
+       int a_set_of_dates[][3] =
+       {
+               {0, 1, 1},
+               {1, 1, 1},
+               {2, 1, 1},
+               {3, 1, 1},
+               {4, 1, 1},
+               {5, 1, 1},
+               {99, 1, 1},
+               {100, 1, 1},
+               {100, 12, 31},
+               {101, 1, 1},
+               {102, 1, 1},
+               {103, 1, 1},
+               {104, 1, 1},
+               {399, 1, 1},
+               {400, 1, 1},
+               {401, 1, 1},
+               {402, 1, 1},
+               {403, 1, 1},
+               {404, 1, 1},
+               {2003, 1, 1},
+               {2003, 1, 2},
+               {2003, 1, 3},
+               {2003, 1, 4},
+               {2003, 1, 5},
+               {2003, 1, 6},
+               {2003, 1, 7},
+               {2003, 1, 8},
+               {2003, 1, 9},
+               {2003, 1, 10},
+               {2003, 1, 11},
+               {2003, 1, 12},
+               {2003, 1, 13},
+               {2003, 1, 14},
+               {2003, 1, 15},
+               {2003, 1, 16},
+               {2003, 1, 17},
+               {2003, 1, 18},
+               {2003, 12, 19},
+               {2003, 12, 20},
+               {2003, 12, 21},
+               {2003, 12, 22},
+               {2003, 12, 23},
+               {2003, 12, 24},
+               {2003, 12, 25},
+               {2003, 12, 26},
+               {2003, 12, 27},
+               {2003, 12, 28},
+               {2003, 12, 29},
+               {2003, 12, 30},
+               {2003, 12, 31},
+               {2004, 1, 1},
+               {2003, 11, 2}
+       };
+       uint i;
+       std::cout << "(y, m, d) : QDate : ExtDate :: Q.dayOfWeek() : E.dayOfWeek() :: Q.dayOfYear() : E.dayOfYear()\n" << std::endl;
+
+       for (i = 0 ; i < sizeof(a_set_of_dates)/sizeof(a_set_of_dates[0]) ; i++)
+       {
+               test2_unit(a_set_of_dates[i][0], a_set_of_dates[i][1], a_set_of_dates[i][2]);
+       }
+       std::cout << "--------------------" << std::endl;
+}
+
+void test3_unit(int y, int m, int d, int dm)
+{
+       QDate   q(y, m, d);
+       ExtDate e(y, m, d);
+       QDate q2 = q.addMonths(dm);
+       ExtDate e2 = e.addMonths(dm);
+       std::cout << e.toString("dd.MMM.yyyy").local8Bit() << " + " << dm
+               << " months :: ExtDate : " << e2.toString("dd.MMM.yyyy").local8Bit()
+               << "   QDate : " << q2.toString("dd.MMM.yyyy").local8Bit() << std::endl;
+}
+
+void test3()
+{
+       int a_set_of_dates_delta[][4] =
+       {
+               {2003, 11, 5, 0},
+               {2003, 11, 5, 1},
+               {2003, 11, 5, -1},
+               {2003, 11, 5, 2},
+               {2003, 11, 5, 3}
+       };
+       uint i;
+       std::cout << "Adding Months:\n" << std::endl;
+       for (i = 0 ; i < sizeof(a_set_of_dates_delta)/sizeof(a_set_of_dates_delta[0]) ; i++)
+       {
+               test3_unit(a_set_of_dates_delta[i][0], a_set_of_dates_delta[i][1], a_set_of_dates_delta[i][2], a_set_of_dates_delta[i][3]);
+       }
+       std::cout << "--------------------" << std::endl;
+}
+void test4_unit(int y, int m, int d, int dy)
+{
+       QDate   q(y, m, d);
+       ExtDate e(y, m, d);
+       QDate   q2 = q.addYears(dy);
+       ExtDate e2 = e.addYears(dy);
+       std::cout << e.toString("dd.MMM.yyyy").local8Bit() << " + " << dy << " years :: ExtDate : "
+               << e2.toString().local8Bit() << "   QDate : "
+               << q2.toString().local8Bit() << std::endl;
+}
+
+void test4()
+{
+       int a_set_of_dates_delta[][4] =
+       {
+               {-1, 11, 5, 0},
+               {-1, 11, 5, 1},
+               {-1, 11, 5, 2},
+               {2003, 11, 5, 1},
+               {2003, 11, 5, -1},
+               {2003, 11, 5, 2},
+               {2003, 11, 5, 3}
+       };
+       uint i;
+       std::cout << "Adding years:\n" << std::endl;
+       for (i = 0 ; i < sizeof(a_set_of_dates_delta)/sizeof(a_set_of_dates_delta[0]) ; i++)
+       {
+               test4_unit(a_set_of_dates_delta[i][0], a_set_of_dates_delta[i][1], a_set_of_dates_delta[i][2], a_set_of_dates_delta[i][3]);
+       }
+       std::cout << "--------------------" << std::endl;
+}
+
+void test5_unit(int y, int m, int d, const char *format)
+{
+       QDate q(y, m, d);
+       ExtDate e(y, m, d);
+
+       if ( QString(format) == "<default>" )
+               std::cout <<  format << " :: "
+                       << e.toString().local8Bit() << " : "
+                       << q.toString().local8Bit() << std::endl;
+       else
+               std::cout << format << " :: "
+                       << e.toString(format).local8Bit() << " : "
+                       << q.toString(format).local8Bit() << std::endl;
+}
+
+void test5()
+{
+       const char *a_set_of_formats[] =
+       {
+               "d.M.yy",
+               "dd.MM.yy",
+               "ddd.MMM.yy",
+               "ddd dd.MMM.yy",
+               "dddd.MMMM.yy",
+               ">dd.M.yyyy<",
+               "<default>"
+       };
+       uint i;
+       std::cout << "Date.toString(\"...\")" << std::endl;
+       std::cout << "Format :: ExtDate : QDate\n" << std::endl;
+
+       for (i = 0 ; i < sizeof(a_set_of_formats)/sizeof(a_set_of_formats[0]) ; i++)
+       {
+               test5_unit(2003, 11, 5, a_set_of_formats[i]);
+       }
+       std::cout << "--------------------" << std::endl;
+}
+
+void test6_unit(int y, int m, int d)
+{
+       std::cout << d << "/" << m << "/" << y << " :: "
+               << ( ExtDate::isValid(y, m, d) ? "TRUE" : "FALSE" ) << " : "
+               << ( QDate::isValid(y, m, d) ? "TRUE" : "FALSE" ) << std::endl;
+}
+
+void test6()
+{
+       int a_set_of_dates[][3] =
+       {
+               {-1, 11, 5},
+               {-1, 11, 5},
+               {-1, 11, 5},
+               {2003, 11, 5},
+               {2003, -1, 5},
+               {2003, 0, 5},
+               {2003, 12, 5},
+               {2003, 13, 5},
+               {2003, 11, -2},
+               {2003, 11, 0},
+               {2003, 11, 40},
+               {2004, 2, 28},
+               {2004, 2, 29},
+               {2004, 2, 30},
+               {2003, 2, 28},
+               {2003, 2, 29},
+               {2003, 2, 30}
+       };
+       uint i;
+       std::cout << "Date.isValid()" << std::endl;
+       std::cout << "d/m/y :: ExtDate.isValid() : QDate.isValid()\n" << std::endl;
+
+       for (i = 0 ; i < sizeof(a_set_of_dates)/sizeof(a_set_of_dates[0]) ; i++)
+       {
+               test6_unit(a_set_of_dates[i][0], a_set_of_dates[i][1], a_set_of_dates[i][2]);
+       }
+       std::cout << "--------------------" << std::endl;
+}
+
+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;
+       q = QDate::currentDate(Qt::UTC);
+       e = ExtDate::currentDate(Qt::UTC);
+       std::cout << "Qt::UTC       :: ExtDate : " << e.toString().local8Bit() << "   QDate : "
+               << q.toString().local8Bit() << std::endl;
+       q = QDate::currentDate();
+       e = ExtDate::currentDate();
+       std::cout << "<default>     :: ExtDate : " << e.toString().local8Bit() << "   QDate : "
+               << q.toString().local8Bit() << std::endl;
+       std::cout << "--------------------" << std::endl;
+}
+
+void test8() {
+       std::cout << "Set dates using days 1-32 for Jan and Feb (some will be invalid): \n" << std::endl;
+       std::cout << "    QDate      :     ExtDate" << std::endl;
+
+       for ( uint m=1; m<=2; ++m ) {
+               for ( uint d=1; d<=32; ++d ) {
+
+                       QDate   test1( 2004, m, d );
+                       ExtDate test2( 2004, m, d );
+                       std::cout << test1.toString( "ddd dd.MMM.yy" ).local8Bit() << "  :  "
+               << test2.toString( "ddd dd.MMM.yy" ).local8Bit() << std::endl;
+               }
+       }
+
+       std::cout << "--------------------" << std::endl;
+}
+
+void test9() {
+       std::cout << "QDateTime : ExtDateTime: \n" << std::endl;
+       QDateTime q = QDateTime::currentDateTime();
+       ExtDateTime e = ExtDateTime::currentDateTime();
+
+       std::cout << q.toString().local8Bit() << " : " << e.toString().local8Bit() << std::endl;
+       std::cout << "--------------------" << std::endl;
+}
+
+int main(int argc, char *argv[])
+{
+       test1();
+       test2();
+       test3();
+       test4();
+       test5();
+       test6();
+       test7();
+       test8();
+       test9();
+       exit(0);
+}
+
diff --git a/extdate/testwidget.cpp b/extdate/testwidget.cpp
new file mode 100644 (file)
index 0000000..0dba28d
--- /dev/null
@@ -0,0 +1,46 @@
+#include <kdatepicker.h>
+#include <klineedit.h>
+#include <qdatetime.h>
+#include <qlayout.h>
+#include <qlabel.h>
+
+#include "extdatepicker.h"
+#include "extdatetime.h"
+#include "testwidget.h"
+
+TestWidget::TestWidget( QWidget *p=0, const char *name=0 ) : KMainWindow( p, name ) {
+       QWidget *w = new QWidget(this);
+
+       glay = new QGridLayout(w, 3, 2);
+
+       QLabel *kdpLabel = new QLabel( QString("KDatePicker"), w );
+       QLabel *edpLabel = new QLabel( QString("ExtDatePicker"), w );
+       kdp = new KDatePicker(w);
+       edp = new ExtDatePicker(w);
+       kdpEdit = new KLineEdit(w);
+       kdpEdit->setReadOnly( TRUE );
+       edpEdit = new KLineEdit(w);
+       edpEdit->setReadOnly( TRUE );
+
+       glay->addWidget( kdpLabel, 0, 0 );
+       glay->addWidget( edpLabel, 0, 1 );
+       glay->addWidget( kdp, 1, 0 );
+       glay->addWidget( edp, 1, 1 );
+       glay->addWidget( kdpEdit, 2, 0 );
+       glay->addWidget( edpEdit, 2, 1 );
+
+       setCentralWidget(w);
+
+       connect( kdp, SIGNAL( dateChanged(QDate) ), this, SLOT( slotKDateChanged(QDate) ) );
+       connect( edp, SIGNAL( dateChanged(const ExtDate&) ), this, SLOT( slotExtDateChanged(const ExtDate&) ) );
+}
+
+void TestWidget::slotKDateChanged(QDate d) {
+       kdpEdit->setText( d.toString() );
+}
+
+void TestWidget::slotExtDateChanged(const ExtDate &d) {
+       edpEdit->setText( d.toString() );
+}
+
+#include "testwidget.moc"
diff --git a/extdate/testwidget.h b/extdate/testwidget.h
new file mode 100644 (file)
index 0000000..0b97f5a
--- /dev/null
@@ -0,0 +1,30 @@
+#ifndef TESTWIDGET_H
+#define TESTWIDGET_H
+
+#include <kmainwindow.h>
+
+class KDatePicker;
+class KLineEdit;
+class ExtDatePicker;
+class QGridLayout;
+class QDate;
+class ExtDate;
+
+class TestWidget : public KMainWindow {
+       Q_OBJECT
+       public:
+               TestWidget( QWidget *parent, const char *name );
+               ~TestWidget() {}
+
+       public slots:
+               void slotKDateChanged(QDate);
+               void slotExtDateChanged(const ExtDate&);
+
+       private:
+               QGridLayout *glay;
+               KDatePicker *kdp;
+               ExtDatePicker *edp;
+               KLineEdit *kdpEdit, *edpEdit;
+};
+
+#endif //ifndef TESTWIDGET_H