summaryrefslogtreecommitdiffstats
path: root/libkdeedu/extdate
diff options
context:
space:
mode:
authortoma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2009-11-25 17:56:58 +0000
committertoma <toma@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2009-11-25 17:56:58 +0000
commitce599e4f9f94b4eb00c1b5edb85bce5431ab3df2 (patch)
treed3bb9f5d25a2dc09ca81adecf39621d871534297 /libkdeedu/extdate
downloadtdeedu-ce599e4f9f94b4eb00c1b5edb85bce5431ab3df2.tar.gz
tdeedu-ce599e4f9f94b4eb00c1b5edb85bce5431ab3df2.zip
Copy the KDE 3.5 branch to branches/trinity for new KDE 3.5 features.
BUG:215923 git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/kdeedu@1054174 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'libkdeedu/extdate')
-rw-r--r--libkdeedu/extdate/Makefile.am21
-rw-r--r--libkdeedu/extdate/README43
-rw-r--r--libkdeedu/extdate/extcalendarsystem.cpp151
-rw-r--r--libkdeedu/extdate/extcalendarsystem.h357
-rw-r--r--libkdeedu/extdate/extcalendarsystemgregorian.cpp328
-rw-r--r--libkdeedu/extdate/extcalendarsystemgregorian.h96
-rw-r--r--libkdeedu/extdate/extdatepicker.cpp532
-rw-r--r--libkdeedu/extdate/extdatepicker.h253
-rw-r--r--libkdeedu/extdate/extdatetbl.cpp968
-rw-r--r--libkdeedu/extdate/extdatetbl.h427
-rw-r--r--libkdeedu/extdate/extdatetime.cpp1148
-rw-r--r--libkdeedu/extdate/extdatetime.h190
-rw-r--r--libkdeedu/extdate/extdatetimeedit.cpp2751
-rw-r--r--libkdeedu/extdate/extdatetimeedit.h341
-rw-r--r--libkdeedu/extdate/extdatewidget.cpp177
-rw-r--r--libkdeedu/extdate/extdatewidget.h89
-rw-r--r--libkdeedu/extdate/main.cpp30
-rw-r--r--libkdeedu/extdate/test_extdate.cc334
-rw-r--r--libkdeedu/extdate/testwidget.cpp68
-rw-r--r--libkdeedu/extdate/testwidget.h51
20 files changed, 8355 insertions, 0 deletions
diff --git a/libkdeedu/extdate/Makefile.am b/libkdeedu/extdate/Makefile.am
new file mode 100644
index 00000000..d7b78860
--- /dev/null
+++ b/libkdeedu/extdate/Makefile.am
@@ -0,0 +1,21 @@
+check_PROGRAMS = test_extdate test_extdatepicker
+
+INCLUDES= $(all_includes)
+
+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_KDEUI)
+
+test_extdate_SOURCES = test_extdate.cc
+test_extdate_LDADD = libextdate.la
+test_extdate_LDFLAGS = $(all_libraries) $(KDE_RPATH)
+
+test_extdatepicker_SOURCES = testwidget.cpp main.cpp
+test_extdatepicker_LDADD = libextdate.la
+test_extdatepicker_LDFLAGS = $(all_libraries) $(KDE_RPATH)
+
+METASOURCES = AUTO
+
diff --git a/libkdeedu/extdate/README b/libkdeedu/extdate/README
new file mode 100644
index 00000000..fc9b21b1
--- /dev/null
+++ b/libkdeedu/extdate/README
@@ -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/libkdeedu/extdate/extcalendarsystem.cpp b/libkdeedu/extdate/extcalendarsystem.cpp
new file mode 100644
index 00000000..f5cd0a36
--- /dev/null
+++ b/libkdeedu/extdate/extcalendarsystem.cpp
@@ -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., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, 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/libkdeedu/extdate/extcalendarsystem.h b/libkdeedu/extdate/extcalendarsystem.h
new file mode 100644
index 00000000..5007ba90
--- /dev/null
+++ b/libkdeedu/extdate/extcalendarsystem.h
@@ -0,0 +1,357 @@
+/*
+ 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., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef EXTCALENDARSYSTEM_H
+#define EXTCALENDARSYSTEM_H
+
+#include "extdatetime.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/libkdeedu/extdate/extcalendarsystemgregorian.cpp b/libkdeedu/extdate/extcalendarsystemgregorian.cpp
new file mode 100644
index 00000000..d358f595
--- /dev/null
+++ b/libkdeedu/extdate/extcalendarsystemgregorian.cpp
@@ -0,0 +1,328 @@
+/*
+ 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., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+// Derived gregorian kde calendar class
+// Just a schema.
+
+
+#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), year(date), shortName);
+}
+
+QString ExtCalendarSystemGregorian::monthNamePossessive(const ExtDate& date, bool shortName) const
+{
+ return monthNamePossessive(month(date), year(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/libkdeedu/extdate/extcalendarsystemgregorian.h b/libkdeedu/extdate/extcalendarsystemgregorian.h
new file mode 100644
index 00000000..c426f997
--- /dev/null
+++ b/libkdeedu/extdate/extcalendarsystemgregorian.h
@@ -0,0 +1,96 @@
+/*
+ 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., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef EXTCALENDARSYSTEMGREGORIAN_H
+#define EXTCALENDARSYSTEMGREGORIAN_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/libkdeedu/extdate/extdatepicker.cpp b/libkdeedu/extdate/extdatepicker.cpp
new file mode 100644
index 00000000..22b4ba80
--- /dev/null
+++ b/libkdeedu/extdate/extdatepicker.cpp
@@ -0,0 +1,532 @@
+/* -*- 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., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#include <qlayout.h>
+#include <qstyle.h>
+#include <qtoolbutton.h>
+#include <qtooltip.h>
+#include <qpopupmenu.h>
+
+#include <kdialog.h>
+#include <klocale.h>
+#include <kiconloader.h>
+#include <ktoolbar.h>
+#include <kdebug.h>
+#include <knotifyclient.h>
+
+#include "extdatepicker.h"
+#include "extdatetbl.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 );
+ line->setReadOnly( true );
+
+ 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( KGlobal::locale()->dateFormatShort() ) );
+ 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/libkdeedu/extdate/extdatepicker.h b/libkdeedu/extdate/extdatepicker.h
new file mode 100644
index 00000000..58fae58a
--- /dev/null
+++ b/libkdeedu/extdate/extdatepicker.h
@@ -0,0 +1,253 @@
+/* -*- 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., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+#ifndef EXTDATEPICKER_H
+#define EXTDATEPICKER_H
+
+
+#include "extdatetime.h"
+
+class KLineEdit;
+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 KDE_EXPORT 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
+ KLineEdit *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/libkdeedu/extdate/extdatetbl.cpp b/libkdeedu/extdate/extdatetbl.cpp
new file mode 100644
index 00000000..43a33a76
--- /dev/null
+++ b/libkdeedu/extdate/extdatetbl.cpp
@@ -0,0 +1,968 @@
+/* -*- 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., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, 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)
+//
+// Modified to use ExtDate by Jason Harris, 2004
+//
+// 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 "extdatepicker.h"
+#include "extdatetbl.h"
+
+#include <kapplication.h>
+#include <kdebug.h>
+#include <knotifyclient.h>
+#include "kpopupmenu.h"
+#include <qpainter.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/libkdeedu/extdate/extdatetbl.h b/libkdeedu/extdate/extdatetbl.h
new file mode 100644
index 00000000..ac9b7156
--- /dev/null
+++ b/libkdeedu/extdate/extdatetbl.h
@@ -0,0 +1,427 @@
+/* -*- 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., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+#ifndef EXTDATETBL_H
+#define EXTDATETBL_H
+
+#include <qvalidator.h>
+#include <qgridview.h>
+#include <klineedit.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/libkdeedu/extdate/extdatetime.cpp b/libkdeedu/extdate/extdatetime.cpp
new file mode 100644
index 00000000..36e3860d
--- /dev/null
+++ b/libkdeedu/extdate/extdatetime.cpp
@@ -0,0 +1,1148 @@
+/*************************************************************************
+** Definition of extended range date classe
+** (c) 2004 by Michel Guitel <michel.guitel@sap.ap-hop-paris.fr>
+** modifications by Jason Harris <kstars@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.
+**
+**********************************************************************/
+
+#include "extdatetime.h"
+#include <qregexp.h>
+
+#include <kglobal.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 date is represented internally by its Julian Day number, a simple count
+ * of the number of days since a remote, arbitrary date (01 January, 4713 BC).
+ * This date has Julian Day number zero.
+ *
+ * ***************************************************************************/
+
+uint ExtDate::m_monthLength[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
+uint ExtDate::m_monthOrigin[] = { 0, 30, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334};
+
+QString ExtDate::m_shortMonthNames[12] = {
+ i18n("Short month name", "Jan"), i18n("Short month name", "Feb"),
+ i18n("Short month name", "Mar"), i18n("Short month name", "Apr"),
+ i18n("Short month name", "May"), i18n("Short month name", "Jun"),
+ i18n("Short month name", "Jul"), i18n("Short month name", "Aug"),
+ i18n("Short month name", "Sep"), i18n("Short month name", "Oct"),
+ i18n("Short month name", "Nov"), i18n("Short month name", "Dec")
+};
+QString ExtDate::m_shortDayNames[7] = {
+ i18n("Short day name", "Mon"), i18n("Short day name", "Tue"),
+ i18n("Short day name", "Wed"), i18n("Short day name", "Thu"),
+ i18n("Short day name", "Fri"), i18n("Short day name", "Sat"),
+ i18n("Short day name", "Sun")
+};
+QString ExtDate::m_longMonthNames[12] = {
+ i18n("Long month name", "January"), i18n("Long month name", "February"),
+ i18n("Long month name", "March"), i18n("Long month name", "April"),
+ i18n("Long month name", "May"), i18n("Long month name", "June"),
+ i18n("Long month name", "July"), i18n("Long month name", "August"),
+ i18n("Long month name", "September"), i18n("Long month name", "October"),
+ i18n("Long month name", "November"), i18n("Long month name", "December")
+};
+QString ExtDate::m_longDayNames[7] = {
+ i18n("Long day name", "Monday"), i18n("Long day name", "Tuesday"),
+ i18n("Long day name", "Wednesday"), i18n("Long day name", "Thursday"),
+ i18n("Long day name", "Friday"), i18n("Long day name", "Saturday"),
+ i18n("Long day name", "Sunday")
+};
+
+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
+ m_year = 0;
+ m_month = 0;
+ m_day = 0;
+ m_jd = INVALID_DAY;
+ } else {
+ m_year = y;
+ m_month = m;
+ m_day = d;
+ m_jd = GregorianToJD(y, m, d);
+ }
+}
+
+ExtDate::ExtDate( long int jd ) {
+ m_jd = jd;
+ JDToGregorian( jd, m_year, m_month, m_day );
+}
+
+long int ExtDate::GregorianToJD( int year, int month, int day )
+{
+ int m, y, A, B, C, D;
+
+ if (month > 2) {
+ m = month;
+ y = year;
+ } else {
+ y = year - 1;
+ m = month + 12;
+ }
+
+/* If the date is after 10/15/1582, then take Pope Gregory's modification
+ to the Julian calendar into account */
+
+ if ( ( year >1582 ) ||
+ ( year ==1582 && month >9 ) ||
+ ( year ==1582 && month ==9 && day >15 ))
+ {
+ A = int(y/100);
+ B = 2 - A + int(A/4);
+ } else {
+ B = 0;
+ }
+
+ if (y < 0) {
+ C = int((365.25*y) - 0.75);
+ } else {
+ C = int(365.25*y);
+ }
+
+ D = int(30.6001*(m+1));
+
+ long int jd = B + C + D + day + 1720995;
+
+ return jd;
+}
+
+void ExtDate::JDToGregorian( long int jd, int &year, int &month, int &day )
+{
+ int a, b, c, d, e, alpha;
+
+ if (jd<2299161) {
+ a = jd;
+ } else {
+ alpha = int ((jd-1867216.25)/ 36524.25);
+ a = jd + 1 + alpha - int(alpha / 4.0);
+ }
+ b = a + 1524;
+ c = int ((b-122.1)/ 365.25);
+ d = int (365.25*c);
+ e = int ((b-d)/ 30.6001);
+
+ day = b-d-int(30.6001*e);
+ month = (e<14) ? e-1 : e-13;
+ year = (month>2) ? c-4716 : c-4715;
+}
+
+bool ExtDate::isValid() const
+{
+ return ( jd() != INVALID_DAY && isValid( year(), month(), day() ) );
+}
+
+int ExtDate::dayOfWeek() const
+{
+ //JD 2451545 (01 Jan 2000) was a Saturday, which is dayOfWeek=6.
+ int a_day = (( jd() - 2451545 + 6 ) % 7);
+ if ( a_day < 0 ) a_day += 7;
+ return (a_day == 0) ? 7 : a_day;
+}
+
+int ExtDate::dayOfYear() const
+{
+ return jd() - GregorianToJD( year(), 1, 1) + 1;
+}
+
+int ExtDate::daysInMonth() const
+{
+ if ( isValid() ) {
+ int m = month();
+ int d = m_monthLength[m-1];
+ if (m==2 && leapYear(year())) d++;
+ return d;
+ } else {
+ return 31;
+ }
+}
+
+int ExtDate::daysInYear() const
+{
+ if ( ! isValid() ) return 365;
+ return (leapYear(year()) ? 366 : 365);
+}
+
+int ExtDate::weekNumber( int *yearNum ) const
+{
+ //ISO 8601:
+ //Week 1 is the week containing the first Thursday of the year.
+ ExtDate day1( year(), 1, 1 ); //First day of the year
+
+ if ( day1.dayOfWeek() > 4 ) {
+ //Jan 1 is after Thursday, so it's in the previous year's last week.
+ //Set day1 to be the following Monday, which is the start of week 1
+ day1 = day1.addDays( 7 - day1.dayOfWeek() + 1 );
+ } else {
+ //Jan 1 is before Friday, so it is in Week 1.
+ //Set day1 to be the preceding Monday
+ day1 = day1.addDays( 1 - day1.dayOfWeek() );
+ }
+
+ //Is the target date prior to day1? If so, the target is in the
+ //last week of the previous year.
+ if ( day1.daysTo( *this ) < 0 ) {
+ if ( yearNum ) *yearNum = year() - 1;
+
+ //The last week of the year always contains Dec 28th (ISO 8601)
+ ExtDate lastDec28( year()-1, 12, 28 );
+ return lastDec28.weekNumber();
+ }
+
+ //If the target date is after Dec 28th, it's possible that it is in
+ //Week 1 of the following year.
+ ExtDate dec28( year(), 12, 28 );
+ if ( dayOfYear() > dec28.dayOfYear() && dayOfWeek() < 4 ) {
+ if ( yearNum ) *yearNum = year() + 1;
+ return 1;
+ }
+
+ //If we reach here, the week number will be in this year.
+ int week = 1 + int( day1.daysTo( *this )/7 );
+
+ if ( yearNum ) *yearNum = year();
+ return week;
+}
+
+#ifndef QT_NO_TEXTDATE
+QString ExtDate::shortMonthName( int month ) {return m_shortMonthNames[month-1];}
+QString ExtDate::shortDayName( int weekday ) {return m_shortDayNames[weekday-1];}
+QString ExtDate::longMonthName( int month ) {return m_longMonthNames[month-1];}
+QString ExtDate::longDayName( int weekday ) {return m_longDayNames[weekday-1];}
+#endif //QT_NO_TEXTDATE
+
+#ifndef QT_NO_TEXTSTRING
+#if !defined(QT_NO_SPRINTF)
+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 = "%a %b %e %Y";
+ break;
+
+ case Qt::ISODate : // YYYY-MM-DD
+ a_format = "%Y-%m-%d";
+ break;
+
+ case Qt::LocalDate : // local settings
+ a_format = KGlobal::locale()->dateFormat();
+ break;
+
+ default :
+ a_format = "toString : unknown format";
+ break;
+
+ }
+ return toString(a_format);
+}
+#endif
+
+QString ExtDate::toString( const QString& format ) const
+{
+ if ( ! isValid() ) return QString::null;
+
+ //We use the KDE Date format specs.
+ //Replace occurences of the following tokens with their
+ //corresponding values:
+ //
+ // %Y The year, including centuries prefix (e.g., "1984")
+ // %y The year, excluding centuries prefix (e.g., "84")
+ // %n Numerical month value (e.g., "3" for March)
+ // %m Numerical month value, two digits (e.g., "03" for March)
+ // %e Numerical day value (e.g., "3" on March 3rd)
+ // %d Numerical day value, two digits (e.g., "03" on March 3rd)
+ // %b Month name, short form (e.g., "Mar" for March)
+ // %B Month name, long form (e.g., "March")
+ // %a Weekday name, short form (e.g., "Wed" for Wednesday)
+ // %A Weekday name, long form (e.g., "Wednesday")
+
+ //All other characters are left as-is.
+
+ QString result( format );
+
+ result.replace( "%Y", QString().sprintf( "%d", year() ) );
+ result.replace( "%y", QString().sprintf( "%02d", (year() % 100) ) );
+ result.replace( "%n", QString().sprintf( "%d", month() ) );
+ result.replace( "%m", QString().sprintf( "%02d", month() ) );
+ result.replace( "%e", QString().sprintf( "%d", day() ) );
+ result.replace( "%d", QString().sprintf( "%02d", day() ) );
+ result.replace( "%b", shortMonthName( month() ) );
+ result.replace( "%B", longMonthName( month() ) );
+ result.replace( "%a", shortDayName( dayOfWeek() ) );
+ result.replace( "%A", longDayName( dayOfWeek() ) );
+
+ return result;
+}
+#endif
+
+bool ExtDate::setYMD( 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
+ m_year = 0;
+ m_month = 0;
+ m_day = 0;
+ m_jd = INVALID_DAY;
+ return false;
+ } else {
+ m_year = y;
+ m_month = m;
+ m_day = d;
+ m_jd = GregorianToJD( y, m, d );
+ return true;
+ }
+}
+
+bool ExtDate::setJD( long int _jd ) {
+ if ( _jd == INVALID_DAY ) {
+ m_jd = _jd;
+ m_year = 0;
+ m_month = 0;
+ m_day = 0;
+ return false;
+ } else {
+ m_jd = _jd;
+ JDToGregorian( _jd, m_year, m_month, m_day );
+ return true;
+ }
+}
+
+ExtDate ExtDate::addDays( int days ) const
+{
+ ExtDate a_date;
+ a_date.setJD( jd() + days );
+ return a_date;
+}
+
+ExtDate ExtDate::addMonths( int months ) const
+{
+ int a_month = month() + months%12;
+ int a_year = year() + int(months/12);
+
+ while ( a_month < 1 ) {
+ a_month += 12;
+ a_year--;
+ }
+
+ while ( a_month > 12 ) {
+ a_month -= 12;
+ a_year++;
+ }
+
+ 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();
+}
+
+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
+//Try both DateFormat values
+ExtDate ExtDate::fromString( const QString& s )
+{
+ ExtDate dResult = ExtDate::fromString( s, Qt::TextDate );
+ if ( dResult.isValid() ) return dResult;
+
+ dResult = ExtDate::fromString( s, Qt::ISODate );
+ if ( dResult.isValid() ) return dResult;
+ else return ExtDate(); //invalid
+}
+
+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 :
+ {
+ //Three possible date formats:
+ //dd mth yyyy; mth dd yyyy; wkd mth dd yyyy
+ //"mth" is the word for the month (long or short form)
+ QStringList ss = QStringList::split( " ", s );
+ bool ok = false;
+ int month = -1;
+ uint imonth = 0;
+ uint iyear = 0;
+
+ //If neither of the first two words is a number, then we'll assume
+ //the first word is a superfluous "weekday" string
+ int day = ss[0].toInt( &ok );
+ if ( ! ok ) {
+ day = ss[1].toInt( &ok );
+ if ( ! ok ) {
+ day = ss[2].toInt( &ok );
+ if ( !ok ) return dt; //could not find a valid day number in first three words
+ imonth = 1; //the month must be the second word
+ iyear = 3; //the year must be the fourth word
+ } else {
+ //the month is either the first word, or the third.
+ imonth = 0;
+ iyear = 2;
+ }
+ } else {
+ //month is the second word
+ imonth = 1;
+ iyear = 2;
+ }
+
+ for ( uint i = 0; i < 12; i++ ) {
+ if ( ss[imonth] == shortMonthName( i+1 ) || ss[imonth] == longMonthName( i+1 ) ) {
+ month = i + 1;
+ break;
+ }
+ }
+
+ if ( month == -1 && imonth == 0 ) { //try the third word
+ imonth = 2;
+ iyear = 3;
+ for ( uint i = 0; i < 12; i++ ) {
+ if ( ss[imonth] == shortMonthName( i+1 ) || ss[imonth] == longMonthName( i+1 ) ) {
+ month = i + 1;
+ break;
+ }
+ }
+ }
+
+ if ( month > -1 ) ok = true;
+ if ( ! ok ) return dt; //could not parse month; return invalid
+
+ int year = ss[iyear].toInt( &ok );
+ if ( ! ok ) return dt; //could not parse year; return invalid
+
+ return ExtDate( year, month, day );
+
+ break;
+ }
+#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 > (int) m_monthLength[m-1]) return false;
+ if (m == 2 && d > ( (int) m_monthLength[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;
+}
+
+int ExtDate::dayOfYear(int y, int m, int d)
+{
+ return m_monthOrigin[m-1] + d + ((m > 1) ? (leapYear(y) ? 1 : 0) : 0);
+}
+
+/*****************************************************************************
+ ExtDateTime member functions
+ *****************************************************************************/
+
+/*!
+ \class ExtDateTime extdatetime.h
+ \brief The ExtDateTime class provides date and time functions.
+
+ \ingroup time
+
+ 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.
+
+ Methods in this class are reentrant.
+
+ \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.setJD( ExtDate::GregorianToJD( 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.setJD( ExtDate::GregorianToJD( 1970, 1, 1 ) );
+// t.ds = 0;
+ t.setHMS(0,0,0);
+ return;
+ }
+ }
+#endif
+
+ d.setJD( ExtDate::GregorianToJD( 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 ) {
+ return toString( "%a %b %e %Y %H:%M:%S" );
+ }
+#endif
+ else if ( f == Qt::LocalDate ) {
+ return toString( KGlobal::locale()->dateFormat()
+ + " " + KGlobal::locale()->timeFormat() );
+ }
+
+ return QString::null;
+}
+#endif
+
+QString ExtDateTime::toString( const QString& format ) const
+{
+ if ( !isValid() )
+ return QString::null;
+
+ //Parse the date portion of the format string
+ QString result = date().toString( format );
+
+ //For the time format, use the following KDE format specs:
+ //Replace occurences of the following tokens with their
+ //corresponding values:
+ //
+ // %H Hour in 24h format, 2 digits
+ // %k Hour in 24h format, 1-2 digits
+ // %I Hour in 12h format, 2 digits
+ // %l Hour in 12h format, 1-2 digits
+ // %M Minute, 2 digits
+ // %S Seconds, 2 digits
+ // %p pm/am
+
+ int h = time().hour();
+
+ result.replace( "%H", QString().sprintf( "%02d", h ) );
+ result.replace( "%k", QString().sprintf( "%d", h ) );
+ result.replace( "%I", QString().sprintf( "%02d", ( h > 12 ) ? h-12 : h ) );
+ result.replace( "%l", QString().sprintf( "%d", ( h > 12 ) ? h-12 : h ) );
+ result.replace( "%M", QString().sprintf( "%02d", time().minute() ) );
+ result.replace( "%S", QString().sprintf( "%02d", time().second() ) );
+ result.replace( "%p", QString().sprintf( "%s", ( h > 12 ) ? "pm" : "am" ) );
+
+ return result;
+}
+#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
+{
+ long int dd = d.jd();
+ int tt = MSECS_PER_HOUR*t.hour() + MSECS_PER_MIN*t.minute() + 1000*t.second() + t.msec();
+ tt += nsecs*1000;
+
+ while ( tt < 0 ) {
+ tt += MSECS_PER_DAY;
+ --dd;
+ }
+
+ while ( tt > int(MSECS_PER_DAY) ) {
+ tt -= MSECS_PER_DAY;
+ ++dd;
+ }
+
+ ExtDateTime ret;
+ ret.setTime( QTime().addMSecs( tt ) );
+ ret.setDate( ExtDate( 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) );
+ kdDebug( ) << "There are " << dt.secsTo(xmas) << " seconds to Christmas" << endl;
+ \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 )
+{
+ ExtDateTime dtResult = ExtDateTime::fromString( s, Qt::TextDate );
+ if ( dtResult.isValid() ) return dtResult;
+
+ dtResult = ExtDateTime::fromString( s, Qt::ISODate );
+
+ if ( dtResult.isValid() ) return dtResult;
+ else return ExtDateTime(); //invalid
+}
+
+ExtDateTime ExtDateTime::fromString( const QString& s, Qt::DateFormat f )
+{
+ ExtDateTime dt;
+
+ if ( ( s.isEmpty() ) || ( f == Qt::LocalDate ) ) {
+#if defined(QT_CHECK_RANGE)
+ qWarning( "ExtDateTime::fromString: Parameter out of range" );
+#endif
+ dt.d.setJD( INVALID_DAY );
+ return dt;
+ }
+
+ if ( f == Qt::ISODate ) {
+ if ( s.length() <= 10 || ! s.contains( ':' ) ) { //no time specified
+ QTime t = QTime(0,0,0);
+ return ExtDateTime( ExtDate::fromString( s.mid(0,10), Qt::ISODate ) );
+ } else {
+ 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 ) {
+
+ //parse the time, if it exists.
+ QTime time;
+ QString sd = s;
+ 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 );
+
+ sd = s.left( pivot - 1 );
+ }
+
+ //sd is now just the date string.
+ ExtDate date = ExtDate::fromString( s, Qt::TextDate );
+ return ExtDateTime( date, time );
+ }
+
+#endif //QT_NO_REGEXP
+ return ExtDateTime();
+}
+#endif //QT_NO_DATESTRING
+
+
+#ifndef QT_NO_DATASTREAM
+KDE_EXPORT QDataStream &operator<<( QDataStream & ostream, const ExtDate & date)
+{
+ return ostream << (Q_UINT32)(date.jd());
+}
+
+KDE_EXPORT QDataStream &operator>>( QDataStream & ostream, ExtDate & date)
+{
+ Q_UINT32 julday;
+ ostream >> julday;
+ date.setJD( julday );
+ return ostream;
+}
+
+KDE_EXPORT QDataStream &operator<<( QDataStream & ostream, const ExtDateTime & dt)
+{
+ return ostream << dt.d << dt.t;
+}
+
+KDE_EXPORT QDataStream &operator>>( QDataStream & ostream, ExtDateTime & dt)
+{
+ ostream >> dt.d >> dt.t;
+ return ostream;
+}
+
+#endif // QT_NO_DATASTREAM
diff --git a/libkdeedu/extdate/extdatetime.h b/libkdeedu/extdate/extdatetime.h
new file mode 100644
index 00000000..e1bc2a79
--- /dev/null
+++ b/libkdeedu/extdate/extdatetime.h
@@ -0,0 +1,190 @@
+/*************************************************************************
+** Definition of extended range date class
+** (c) 2004 by Michel Guitel <michel.guitel@sap.ap-hop-paris.fr>
+** modifications by Jason Harris <kstars@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.
+**
+**********************************************************************/
+
+#ifndef EXTDATETIME_H
+#define EXTDATETIME_H
+
+#include <limits.h>
+#include "qstring.h"
+#include "qnamespace.h"
+#include "qdatetime.h"
+#include <kdemacros.h>
+
+#define INVALID_DAY LONG_MIN
+
+class ExtDateTime;
+
+/*****************************************************************************
+ ExtDate class
+ *****************************************************************************/
+
+extern void test2_unit(int y, int m, int d);
+
+class ExtDateTime;
+
+class KDE_EXPORT ExtDate
+{
+public:
+ ExtDate() : m_jd(INVALID_DAY), m_year(0), m_month(0), m_day(0) {}
+ ExtDate( int y, int m, int d );
+ ExtDate( const QDate &q ) { ExtDate( q.year(), q.month(), q.day() ); }
+ ExtDate( long int jd );
+
+ bool isNull() const { return m_jd == INVALID_DAY; }
+ bool isValid() const;
+
+ QDate qdate() const;
+
+ int year() const { return m_year; }
+ int month() const { return m_month; }
+ int day() const { return m_day; }
+ int dayOfWeek() const;
+ int dayOfYear() const;
+ int daysInMonth() const;
+ int daysInYear() const;
+ int weekNumber( int *yearNum = 0 ) const;
+ long int jd() const { return m_jd; }
+
+#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 );
+ bool setJD( long int _jd );
+
+ 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 m_jd == d.jd(); }
+ bool operator!=( const ExtDate &d ) const { return m_jd != d.jd(); }
+ bool operator<( const ExtDate &d ) const { return m_jd < d.jd(); }
+ bool operator<=( const ExtDate &d ) const { return m_jd <= d.jd(); }
+ bool operator>( const ExtDate &d ) const { return m_jd > d.jd(); }
+ bool operator>=( const ExtDate &d ) const { return m_jd >= d.jd(); }
+
+ static ExtDate currentDate( Qt::TimeSpec ts = Qt::LocalTime );
+#ifndef QT_NO_DATESTRING
+ static ExtDate fromString( const QString &s );
+ static ExtDate fromString( const QString &s, Qt::DateFormat f );
+#endif
+ static bool isValid( int y, int m, int d );
+ static bool leapYear( int year );
+
+ static long int GregorianToJD( int y, int m, int d );
+ static void JDToGregorian( long int jd, int &y, int &m, int &d );
+
+private:
+ static int dayOfYear(int y, int m, int d);
+
+ long int m_jd;
+ int m_year, m_month, m_day;
+ static uint m_monthLength[12];
+ static uint m_monthOrigin[12];
+ static QString m_shortMonthNames[12];
+ static QString m_shortDayNames[7];
+ static QString m_longMonthNames[12];
+ static QString m_longDayNames[7];
+
+ friend class ExtDateTime;
+
+#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 KDE_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 );
+ static ExtDateTime fromString( const QString &s, Qt::DateFormat f );
+#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/libkdeedu/extdate/extdatetimeedit.cpp b/libkdeedu/extdate/extdatetimeedit.cpp
new file mode 100644
index 00000000..2a9a467b
--- /dev/null
+++ b/libkdeedu/extdate/extdatetimeedit.cpp
@@ -0,0 +1,2751 @@
+/****************************************************************************
+**
+**
+** 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.
+**
+**********************************************************************/
+
+//DEBUG
+#include <kdebug.h>
+
+#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
+
+ 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 "-".
+
+ \image html 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.
+
+*/
+
+
+/*!
+ \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( -50000, 1, 1 );
+ d->max = ExtDate( 50000, 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;
+
+ fix();
+
+ 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 ( !outOfRange( year, d->m, d->d ) ) {
+ d->y = year;
+ setMonth( d->m );
+ }
+}
+
+
+/*!
+ 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;
+ setDay( d->d );
+ }
+}
+
+
+/*!
+ 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 )
+{
+ ExtDate test = ExtDate( d->y, d->m, 1 );
+
+ if ( day < 1 )
+ day = 1;
+ if ( day > test.daysInMonth() )
+ day = test.daysInMonth();
+
+ d->dayCache = d->d;
+ d->d = day;
+}
+
+
+/*!
+ \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 ) {
+ if ( d->overwrite ) {
+ d->y = num;
+ d->overwrite = FALSE;
+ accepted = TRUE;
+ } else {
+ txt = QString::number( 10*d->y + num );
+ if ( txt.length() > 5 ) txt = txt.mid(1);
+ d->y = txt.toInt();
+ accepted = TRUE;
+ }
+/*
+ txt = QString::number( d->y );
+ if ( d->overwrite || txt.length() == 4 ) {
+ accepted = TRUE;
+ d->y = num;
+ } else {
+ txt += QString::number( num );
+ if ( txt.length() == 4 ) {
+ int val = txt.toInt();
+ if ( val < 1792 )
+ d->y = 1792;
+ else if ( val > 8000 )
+ d->y = 8000;
+ else if ( outOfRange( val, d->m, d->d ) )
+ txt = QString::number( d->y );
+ else {
+ accepted = TRUE;
+ d->y = val;
+ }
+ } else {
+ accepted = TRUE;
+ d->y = txt.toInt();
+ }
+ if ( d->adv && txt.length() == 4 ) {
+ d->ed->setFocusSection( d->ed->focusSection()+1 );
+ overwrite = TRUE;
+ }
+ }
+*/
+ } else if ( sec == d->monthSection ) {
+ txt = QString::number( d->m );
+ if ( d->overwrite || txt.length() == 2 ) {
+ accepted = TRUE;
+ d->m = num;
+ } else {
+ txt += QString::number( num );
+ int temp = txt.toInt();
+ if ( temp > 12 )
+ temp = num;
+ if ( outOfRange( d->y, temp, d->d ) )
+ txt = QString::number( d->m );
+ else {
+ accepted = TRUE;
+ d->m = temp;
+ }
+ if ( d->adv && txt.length() == 2 ) {
+ d->ed->setFocusSection( d->ed->focusSection()+1 );
+ overwrite = TRUE;
+ }
+ }
+ } else if ( sec == d->daySection ) {
+ txt = QString::number( d->d );
+ if ( d->overwrite || txt.length() == 2 ) {
+ accepted = TRUE;
+ d->d = num;
+ d->dayCache = d->d;
+ } else {
+ txt += QString::number( num );
+ int temp = txt.toInt();
+ if ( temp > 31 )
+ temp = num;
+ if ( outOfRange( d->y, d->m, temp ) )
+ txt = QString::number( d->d );
+ else {
+ accepted = TRUE;
+ d->d = temp;
+ d->dayCache = d->d;
+ }
+ if ( d->adv && txt.length() == 2 ) {
+ d->ed->setFocusSection( d->ed->focusSection()+1 );
+ overwrite = TRUE;
+ }
+ }
+ }
+ if ( accepted ) {
+ d->changed = TRUE;
+ emit valueChanged( date() );
+ }
+ d->overwrite = overwrite;
+ d->timerId = startTimer( qApp->doubleClickInterval()*4 );
+ d->ed->repaint( d->ed->rect(), FALSE );
+}
+
+
+/*! \reimp
+
+*/
+
+bool ExtDateEdit::setFocusSection( int s )
+{
+ if ( s != d->ed->focusSection() ) {
+ killTimer( d->timerId );
+ d->overwrite = TRUE;
+ d->typing = FALSE;
+ fix(); // will emit valueChanged if necessary
+ }
+ return d->ed->setFocusSection( s );
+}
+
+
+/*!
+ Attempts to fix any invalid date entries.
+
+ The rules applied are as follows:
+
+ - if the day is larger than the number of days in the month,
+ - it is reset to that number
+ - If the year has four digits it is left unchanged.
+ - If the year has two digits, the year will be changed to four
+ digits in the range current year - 70 to current year + 29.
+ - If the year has three digits in the range 100..999, the
+ current millennium, i.e. 2000, will be added giving a year
+ in the range 2100..2999.
+
+*/
+
+void ExtDateEdit::fix()
+{
+ bool changed = FALSE;
+
+ ExtDate test = ExtDate( d->y, d->m, 1 );
+ if ( d->d > test.daysInMonth() ) {
+
+ d->d = test.daysInMonth();
+ changed = TRUE;
+ }
+
+ int currentYear = ExtDate::currentDate().year();
+ int year = d->y;
+/* No longer valid for extended dates
+ 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;
+ d->overwrite = TRUE;
+ // 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 ) {
+ fix();
+ emit valueChanged( date() );
+ d->changed = FALSE;
+ }
+ } else if ( e->type() == QEvent::LocaleChange ) {
+ readLocaleSettings();
+ d->ed->setSeparator( localDateSep() );
+ setOrder( localOrder() );
+ }
+
+ bool result = ExtDateTimeEditBase::event( e );
+
+ return result;
+}
+
+/*!
+ \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
+
+ 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.
+
+ \image html 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/libkdeedu/extdate/extdatetimeedit.h b/libkdeedu/extdate/extdatetimeedit.h
new file mode 100644
index 00000000..048f7aa3
--- /dev/null
+++ b/libkdeedu/extdate/extdatetimeedit.h
@@ -0,0 +1,341 @@
+/****************************************************************************
+**
+**
+** 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"
+
+#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 KDE_EXPORT ExtDateEdit : public ExtDateTimeEditBase
+{
+ Q_OBJECT
+ Q_ENUMS( Order )
+ Q_PROPERTY( Order order READ order WRITE setOrder )
+// Q_PROPERTY( ExtDate date READ date WRITE setDate )
+ Q_PROPERTY( bool autoAdvance READ autoAdvance WRITE setAutoAdvance )
+// Q_PROPERTY( ExtDate maxValue READ maxValue WRITE setMaxValue )
+// Q_PROPERTY( ExtDate minValue READ minValue WRITE setMinValue )
+
+public:
+ ExtDateEdit( QWidget* parent=0, const char* name=0 );
+ ExtDateEdit( const ExtDate& date, QWidget* parent=0, const char* name=0 );
+ ~ExtDateEdit();
+
+ enum Order { DMY /**< Day-Month-Year */,
+ MDY /**< Month-Day-Year */,
+ YMD /**< Year-Month-Day, also the default */,
+ YDM /**< Year-Day-Month @deprecated Included for completeness. */ };
+
+ 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 KDE_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/libkdeedu/extdate/extdatewidget.cpp b/libkdeedu/extdate/extdatewidget.cpp
new file mode 100644
index 00000000..6a3fcbf5
--- /dev/null
+++ b/libkdeedu/extdate/extdatewidget.cpp
@@ -0,0 +1,177 @@
+/* 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., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+
+#include <qcombobox.h>
+#include <qlayout.h>
+#include <qlineedit.h>
+
+#include <knuminput.h>
+#include <kdialog.h>
+
+#include "extdatewidget.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::currentDate());
+ 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()
+{
+ delete d;
+}
+
+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/libkdeedu/extdate/extdatewidget.h b/libkdeedu/extdate/extdatewidget.h
new file mode 100644
index 00000000..66bec871
--- /dev/null
+++ b/libkdeedu/extdate/extdatewidget.h
@@ -0,0 +1,89 @@
+/* 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., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef __EXTDATEWIDGET_H__
+#define __EXTDATEWIDGET_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 KDE_EXPORT ExtDateWidget : public QWidget
+{
+ Q_OBJECT
+// Q_PROPERTY( ExtDate date READ date WRITE setDate )
+
+public:
+ /**
+ * Constructs a date selection widget, initialized to the current CPU date.
+ */
+ 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/libkdeedu/extdate/main.cpp b/libkdeedu/extdate/main.cpp
new file mode 100644
index 00000000..f71a6acd
--- /dev/null
+++ b/libkdeedu/extdate/main.cpp
@@ -0,0 +1,30 @@
+#include "testwidget.h"
+#include <kapplication.h>
+#include <kcmdlineargs.h>
+#include <kaboutdata.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/libkdeedu/extdate/test_extdate.cc b/libkdeedu/extdate/test_extdate.cc
new file mode 100644
index 00000000..b21e228b
--- /dev/null
+++ b/libkdeedu/extdate/test_extdate.cc
@@ -0,0 +1,334 @@
+#include <stdlib.h>
+#include <iostream>
+#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() << " : "
+ << q.dayOfWeek() << " : " << q_week_number << " : " << q_day_of_year << " :: "
+ << e.toString("%d.%b.%Y").local8Bit() << " : "
+ << e.dayOfWeek() << " : " << e_week_number << " : " << 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 : Q.dayOfWeek() : Q.weekNumber() : Q.dayOfYear() :: ExtDate : E.dayOfWeek() : E.weekNumber() : 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("%d.%b.%Y").local8Bit() << " + " << dm
+ << " months :: ExtDate : " << e2.toString("%d.%b.%Y").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("%d.%m.%Y").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 *qformat, const char *eformat)
+{
+ QDate q(y, m, d);
+ ExtDate e(y, m, d);
+
+ if ( QString(qformat) == "<default>" )
+ std::cout << eformat << " : " << e.toString().local8Bit() << " :: "
+ << qformat << " : " << q.toString().local8Bit() << std::endl;
+ else
+ std::cout << eformat << " : " << e.toString(eformat).local8Bit() << " :: "
+ << qformat << " : " << q.toString(qformat).local8Bit() << std::endl;
+}
+
+void test5()
+{
+ const char *q_set_of_formats[7] =
+ {
+ "d.M.yy",
+ "dd.MM.yy",
+ "ddd.MMM.yy",
+ "ddd dd.MMM.yy",
+ "dddd.MMMM.yy",
+ ">dd.M.yyyy<",
+ "<default>"
+ };
+ const char *e_set_of_formats[7] =
+ {
+ "%e.%n.%y",
+ "%d.%m.%y",
+ "%d.%b.%y",
+ "%a %d.%b.%y",
+ "%A.%B.%y",
+ ">%d.%n.%Y<",
+ "<default>"
+ };
+
+ uint i;
+ std::cout << "Date.toString(\"...\")" << std::endl;
+ std::cout << "Ext Format : ExtDate :: Q Format : QDate\n" << std::endl;
+
+ for (i = 0 ; i < sizeof(q_set_of_formats)/sizeof(q_set_of_formats[0]) ; i++)
+ {
+ test5_unit(2003, 11, 5, q_set_of_formats[i], e_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( "%a %d.%b.%y" ).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/libkdeedu/extdate/testwidget.cpp b/libkdeedu/extdate/testwidget.cpp
new file mode 100644
index 00000000..4dcd91c8
--- /dev/null
+++ b/libkdeedu/extdate/testwidget.cpp
@@ -0,0 +1,68 @@
+/***************************************************************************
+ testwidget.h - description
+ -------------------
+ begin : Sun Apr 11 2004
+ copyright : (C) 2004 by Jason Harris
+ email : kstars@30doradus.org
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#include <kdatepicker.h>
+#include <kdatewidget.h>
+#include <klineedit.h>
+#include <qlayout.h>
+#include <qlabel.h>
+
+#include "extdatepicker.h"
+#include "extdatewidget.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 );
+
+ kdw = new KDateWidget( QDate::currentDate(), w );
+ edw = new ExtDateWidget( ExtDate::currentDate(), w );
+
+ 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 );
+ glay->addWidget( kdw, 3, 0 );
+ glay->addWidget( edw, 3, 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/libkdeedu/extdate/testwidget.h b/libkdeedu/extdate/testwidget.h
new file mode 100644
index 00000000..ef69f8b6
--- /dev/null
+++ b/libkdeedu/extdate/testwidget.h
@@ -0,0 +1,51 @@
+/***************************************************************************
+ testwidget.cpp - description
+ -------------------
+ begin : Sun Apr 11 2004
+ copyright : (C) 2004 by Jason Harris
+ email : kstars@30doradus.org
+ ***************************************************************************/
+
+/***************************************************************************
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ ***************************************************************************/
+
+#ifndef TESTWIDGET_H
+#define TESTWIDGET_H
+
+#include <kmainwindow.h>
+
+class KDatePicker;
+class KLineEdit;
+class KDateWidget;
+class ExtDatePicker;
+class ExtDateWidget;
+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;
+ ExtDateWidget *edw;
+ KDateWidget *kdw;
+ KLineEdit *kdpEdit, *edpEdit;
+};
+
+#endif //ifndef TESTWIDGET_H