You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
550 lines
16 KiB
550 lines
16 KiB
/* -*- 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)
|
|
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 <tqlayout.h>
|
|
#include <tqframe.h>
|
|
#include <tqpainter.h>
|
|
#include <tqdialog.h>
|
|
#include <tqstyle.h>
|
|
#include <tqtoolbutton.h>
|
|
#include <tqcombobox.h>
|
|
#include <tqtooltip.h>
|
|
#include <tqfont.h>
|
|
#include <tqvalidator.h>
|
|
#include <tqpopupmenu.h>
|
|
#include <tqtimer.h>
|
|
|
|
#include "kdatepicker.h"
|
|
#include <kglobal.h>
|
|
#include <kapplication.h>
|
|
#include <kdialog.h>
|
|
#include <klocale.h>
|
|
#include <kiconloader.h>
|
|
#include <ktoolbar.h>
|
|
#include <klineedit.h>
|
|
#include <kdebug.h>
|
|
#include <knotifyclient.h>
|
|
#include <kcalendarsystem.h>
|
|
|
|
#include "kdatetbl.h"
|
|
#include "kdatepicker.moc"
|
|
|
|
// Week numbers are defined by ISO 8601
|
|
// See http://www.merlyn.demon.co.uk/weekinfo.htm for details
|
|
|
|
class KDatePicker::KDatePickerPrivate
|
|
{
|
|
public:
|
|
KDatePickerPrivate() : closeButton(0L), selectWeek(0L), todayButton(0), navigationLayout(0) {}
|
|
|
|
void fillWeeksCombo(const TQDate &date);
|
|
|
|
TQToolButton *closeButton;
|
|
TQComboBox *selectWeek;
|
|
TQToolButton *todayButton;
|
|
TQBoxLayout *navigationLayout;
|
|
};
|
|
|
|
void KDatePicker::fillWeeksCombo(const TQDate &date)
|
|
{
|
|
// every year can have a different number of weeks
|
|
const KCalendarSystem * 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
|
|
|
|
TQDate day;
|
|
int year = calendar->year(date);
|
|
calendar->setYMD(day, year, 1, 1);
|
|
int lastMonth = calendar->monthsInYear(day);
|
|
TQDate lastDay, firstDayOfLastMonth;
|
|
calendar->setYMD(firstDayOfLastMonth, year, lastMonth, 1);
|
|
calendar->setYMD(lastDay, year, lastMonth, calendar->daysInMonth(firstDayOfLastMonth));
|
|
|
|
for (; day <= lastDay ; day = calendar->addDays(day, 7 /*calendar->daysOfWeek()*/) )
|
|
{
|
|
TQString week = i18n("Week %1").arg(calendar->weekNumber(day, &year));
|
|
if ( year != calendar->year(day) ) week += "*"; // show that this is a week from a different year
|
|
d->selectWeek->insertItem(week);
|
|
|
|
// make sure that the week of the lastDay is always inserted: in Chinese calendar
|
|
// system, this is not always the case
|
|
if(day < lastDay && day.daysTo(lastDay) < 7 && calendar->weekNumber(day) != calendar->weekNumber(lastDay))
|
|
day = TQT_TQDATE_OBJECT(lastDay.addDays(-7));
|
|
}
|
|
}
|
|
|
|
KDatePicker::KDatePicker(TQWidget *parent, TQDate dt, const char *name)
|
|
: TQFrame(parent,name)
|
|
{
|
|
init( dt );
|
|
}
|
|
|
|
KDatePicker::KDatePicker(TQWidget *parent, TQDate dt, const char *name, WFlags f)
|
|
: TQFrame(parent,name, f)
|
|
{
|
|
init( dt );
|
|
}
|
|
|
|
KDatePicker::KDatePicker( TQWidget *parent, const char *name )
|
|
: TQFrame(parent,name)
|
|
{
|
|
init( TQDate::currentDate() );
|
|
}
|
|
|
|
void KDatePicker::init( const TQDate &dt )
|
|
{
|
|
d = new KDatePickerPrivate();
|
|
|
|
TQBoxLayout * topLayout = new TQVBoxLayout(this);
|
|
|
|
d->navigationLayout = new TQHBoxLayout(topLayout);
|
|
d->navigationLayout->addStretch();
|
|
yearBackward = new TQToolButton(this);
|
|
yearBackward->setAutoRaise(true);
|
|
d->navigationLayout->addWidget(yearBackward);
|
|
monthBackward = new TQToolButton(this);
|
|
monthBackward ->setAutoRaise(true);
|
|
d->navigationLayout->addWidget(monthBackward);
|
|
d->navigationLayout->addSpacing(KDialog::spacingHint());
|
|
|
|
selectMonth = new TQToolButton(this);
|
|
selectMonth ->setAutoRaise(true);
|
|
d->navigationLayout->addWidget(selectMonth);
|
|
selectYear = new TQToolButton(this);
|
|
selectYear->setToggleButton(true);
|
|
selectYear->setAutoRaise(true);
|
|
d->navigationLayout->addWidget(selectYear);
|
|
d->navigationLayout->addSpacing(KDialog::spacingHint());
|
|
|
|
monthForward = new TQToolButton(this);
|
|
monthForward ->setAutoRaise(true);
|
|
d->navigationLayout->addWidget(monthForward);
|
|
yearForward = new TQToolButton(this);
|
|
yearForward ->setAutoRaise(true);
|
|
d->navigationLayout->addWidget(yearForward);
|
|
d->navigationLayout->addStretch();
|
|
|
|
line = new KLineEdit(this);
|
|
val = new KDateValidator(this);
|
|
table = new KDateTable(this);
|
|
fontsize = KGlobalSettings::generalFont().pointSize();
|
|
if (fontsize == -1)
|
|
fontsize = TQFontInfo(KGlobalSettings::generalFont()).pointSize();
|
|
|
|
fontsize++; // Make a little bigger
|
|
|
|
d->selectWeek = new TQComboBox(false, this); // read only week selection
|
|
d->todayButton = new TQToolButton(this);
|
|
d->todayButton->setIconSet(SmallIconSet("today"));
|
|
|
|
TQToolTip::add(yearForward, i18n("Next year"));
|
|
TQToolTip::add(yearBackward, i18n("Previous year"));
|
|
TQToolTip::add(monthForward, i18n("Next month"));
|
|
TQToolTip::add(monthBackward, i18n("Previous month"));
|
|
TQToolTip::add(d->selectWeek, i18n("Select a week"));
|
|
TQToolTip::add(selectMonth, i18n("Select a month"));
|
|
TQToolTip::add(selectYear, i18n("Select a year"));
|
|
TQToolTip::add(d->todayButton, i18n("Select the current day"));
|
|
|
|
// -----
|
|
setFontSize(fontsize);
|
|
line->setValidator(val);
|
|
line->installEventFilter( this );
|
|
if ( TQApplication::reverseLayout() )
|
|
{
|
|
yearForward->setIconSet(BarIconSet(TQString::fromLatin1("2leftarrow")));
|
|
yearBackward->setIconSet(BarIconSet(TQString::fromLatin1("2rightarrow")));
|
|
monthForward->setIconSet(BarIconSet(TQString::fromLatin1("1leftarrow")));
|
|
monthBackward->setIconSet(BarIconSet(TQString::fromLatin1("1rightarrow")));
|
|
}
|
|
else
|
|
{
|
|
yearForward->setIconSet(BarIconSet(TQString::fromLatin1("2rightarrow")));
|
|
yearBackward->setIconSet(BarIconSet(TQString::fromLatin1("2leftarrow")));
|
|
monthForward->setIconSet(BarIconSet(TQString::fromLatin1("1rightarrow")));
|
|
monthBackward->setIconSet(BarIconSet(TQString::fromLatin1("1leftarrow")));
|
|
}
|
|
connect(table, TQT_SIGNAL(dateChanged(TQDate)), TQT_SLOT(dateChangedSlot(TQDate)));
|
|
connect(table, TQT_SIGNAL(tableClicked()), TQT_SLOT(tableClickedSlot()));
|
|
connect(monthForward, TQT_SIGNAL(clicked()), TQT_SLOT(monthForwardClicked()));
|
|
connect(monthBackward, TQT_SIGNAL(clicked()), TQT_SLOT(monthBackwardClicked()));
|
|
connect(yearForward, TQT_SIGNAL(clicked()), TQT_SLOT(yearForwardClicked()));
|
|
connect(yearBackward, TQT_SIGNAL(clicked()), TQT_SLOT(yearBackwardClicked()));
|
|
connect(d->selectWeek, TQT_SIGNAL(activated(int)), TQT_SLOT(weekSelected(int)));
|
|
connect(d->todayButton, TQT_SIGNAL(clicked()), TQT_SLOT(todayButtonClicked()));
|
|
connect(selectMonth, TQT_SIGNAL(clicked()), TQT_SLOT(selectMonthClicked()));
|
|
connect(selectYear, TQT_SIGNAL(toggled(bool)), TQT_SLOT(selectYearClicked()));
|
|
connect(line, TQT_SIGNAL(returnPressed()), TQT_SLOT(lineEnterPressed()));
|
|
table->setFocus();
|
|
|
|
|
|
topLayout->addWidget(table);
|
|
|
|
TQBoxLayout * bottomLayout = new TQHBoxLayout(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
|
|
}
|
|
|
|
KDatePicker::~KDatePicker()
|
|
{
|
|
delete d;
|
|
}
|
|
|
|
bool
|
|
KDatePicker::eventFilter(TQObject *o, TQEvent *e )
|
|
{
|
|
if ( e->type() == TQEvent::KeyPress ) {
|
|
TQKeyEvent *k = (TQKeyEvent *)e;
|
|
|
|
if ( (k->key() == TQt::Key_Prior) ||
|
|
(k->key() == TQt::Key_Next) ||
|
|
(k->key() == Qt::Key_Up) ||
|
|
(k->key() == Qt::Key_Down) )
|
|
{
|
|
TQApplication::sendEvent( table, e );
|
|
table->setFocus();
|
|
return true; // eat event
|
|
}
|
|
}
|
|
return TQFrame::eventFilter( o, e );
|
|
}
|
|
|
|
void
|
|
KDatePicker::resizeEvent(TQResizeEvent* e)
|
|
{
|
|
TQWidget::resizeEvent(e);
|
|
}
|
|
|
|
void
|
|
KDatePicker::dateChangedSlot(TQDate date)
|
|
{
|
|
kdDebug(298) << "KDatePicker::dateChangedSlot: date changed (" << date.year() << "/" << date.month() << "/" << date.day() << ")." << endl;
|
|
|
|
const KCalendarSystem * calendar = KGlobal::locale()->calendar();
|
|
|
|
line->setText(KGlobal::locale()->formatDate(date, true));
|
|
selectMonth->setText(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
|
|
TQDate firstDay;
|
|
calendar->setYMD(firstDay, calendar->year(date), 1, 1);
|
|
d->selectWeek->setCurrentItem((calendar->dayOfYear(date) + calendar->dayOfWeek(firstDay) - 2) / 7/*calendar->daysInWeek()*/);
|
|
selectYear->setText(calendar->yearString(date, false));
|
|
|
|
emit(dateChanged(date));
|
|
}
|
|
|
|
void
|
|
KDatePicker::tableClickedSlot()
|
|
{
|
|
kdDebug(298) << "KDatePicker::tableClickedSlot: table clicked." << endl;
|
|
emit(dateSelected(table->getDate()));
|
|
emit(tableClicked());
|
|
}
|
|
|
|
const TQDate&
|
|
KDatePicker::getDate() const
|
|
{
|
|
return table->getDate();
|
|
}
|
|
|
|
const TQDate &
|
|
KDatePicker::date() const
|
|
{
|
|
return table->getDate();
|
|
}
|
|
|
|
bool
|
|
KDatePicker::setDate(const TQDate& date)
|
|
{
|
|
if(date.isValid())
|
|
{
|
|
table->setDate(date); // this also emits dateChanged() which then calls our dateChangedSlot()
|
|
return true;
|
|
}
|
|
else
|
|
{
|
|
kdDebug(298) << "KDatePicker::setDate: refusing to set invalid date." << endl;
|
|
return false;
|
|
}
|
|
}
|
|
|
|
void
|
|
KDatePicker::monthForwardClicked()
|
|
{
|
|
TQDate temp;
|
|
temp = KGlobal::locale()->calendar()->addMonths( table->getDate(), 1 );
|
|
|
|
setDate( temp );
|
|
}
|
|
|
|
void
|
|
KDatePicker::monthBackwardClicked()
|
|
{
|
|
TQDate temp;
|
|
temp = KGlobal::locale()->calendar()->addMonths( table->getDate(), -1 );
|
|
|
|
setDate( temp );
|
|
}
|
|
|
|
void
|
|
KDatePicker::yearForwardClicked()
|
|
{
|
|
TQDate temp;
|
|
temp = KGlobal::locale()->calendar()->addYears( table->getDate(), 1 );
|
|
|
|
setDate( temp );
|
|
}
|
|
|
|
void
|
|
KDatePicker::yearBackwardClicked()
|
|
{
|
|
TQDate temp;
|
|
temp = KGlobal::locale()->calendar()->addYears( table->getDate(), -1 );
|
|
|
|
setDate( temp );
|
|
}
|
|
|
|
void KDatePicker::selectWeekClicked() {} // ### in 3.2 obsolete; kept for binary compatibility
|
|
|
|
void
|
|
KDatePicker::weekSelected(int week)
|
|
{
|
|
const KCalendarSystem * calendar = KGlobal::locale()->calendar();
|
|
|
|
TQDate date = table->getDate();
|
|
int year = calendar->year(date);
|
|
|
|
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 = calendar->addDays(date, week * 7/*calendar->daysOfWeek()*/ -calendar->dayOfWeek(date) + 1);
|
|
|
|
setDate(date);
|
|
}
|
|
|
|
void
|
|
KDatePicker::selectMonthClicked()
|
|
{
|
|
// every year can have different month names (in some calendar systems)
|
|
const KCalendarSystem * calendar = KGlobal::locale()->calendar();
|
|
TQDate date = table->getDate();
|
|
int i, month, months = calendar->monthsInYear(date);
|
|
|
|
TQPopupMenu popup(selectMonth);
|
|
|
|
for (i = 1; i <= months; i++)
|
|
popup.insertItem(calendar->monthName(i, calendar->year(date)), i);
|
|
|
|
popup.setActiveItem(calendar->month(date) - 1);
|
|
|
|
if ( (month = popup.exec(selectMonth->mapToGlobal(TQPoint(0, 0)), calendar->month(date) - 1)) == -1 ) return; // canceled
|
|
|
|
int day = calendar->day(date);
|
|
// ----- construct a valid date in this month:
|
|
calendar->setYMD(date, calendar->year(date), month, 1);
|
|
date = TQT_TQDATE_OBJECT(date.addDays(QMIN(day, calendar->daysInMonth(date)) - 1));
|
|
// ----- set this month
|
|
setDate(date);
|
|
}
|
|
|
|
void
|
|
KDatePicker::selectYearClicked()
|
|
{
|
|
const KCalendarSystem * calendar = KGlobal::locale()->calendar();
|
|
|
|
if (selectYear->state() == TQButton::Off)
|
|
{
|
|
return;
|
|
}
|
|
|
|
int year;
|
|
KPopupFrame* popup = new KPopupFrame(this);
|
|
KDateInternalYearSelector* picker = new KDateInternalYearSelector(popup);
|
|
// -----
|
|
picker->resize(picker->sizeHint());
|
|
picker->setYear( table->getDate().year() );
|
|
picker->selectAll();
|
|
popup->setMainWidget(picker);
|
|
connect(picker, TQT_SIGNAL(closeMe(int)), popup, TQT_SLOT(close(int)));
|
|
picker->setFocus();
|
|
if(popup->exec(selectYear->mapToGlobal(TQPoint(0, selectMonth->height()))))
|
|
{
|
|
TQDate date;
|
|
int day;
|
|
// -----
|
|
year=picker->getYear();
|
|
date=table->getDate();
|
|
day=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()));
|
|
calendar->setYMD(date, year, calendar->month(date),
|
|
QMIN(day, calendar->daysInMonth(date)));
|
|
// ----- set this month
|
|
setDate(date);
|
|
} else {
|
|
KNotifyClient::beep();
|
|
}
|
|
|
|
delete popup;
|
|
TQTimer::singleShot(0, this, TQT_SLOT(ensureSelectYearIsUp()));
|
|
}
|
|
|
|
void
|
|
KDatePicker::ensureSelectYearIsUp()
|
|
{
|
|
if (!selectYear->isDown())
|
|
{
|
|
selectYear->setOn( false );
|
|
}
|
|
}
|
|
|
|
void
|
|
KDatePicker::setEnabled(bool enable)
|
|
{
|
|
TQWidget *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
|
|
KDatePicker::lineEnterPressed()
|
|
{
|
|
TQDate temp;
|
|
// -----
|
|
if(val->date(line->text(), temp)==TQValidator::Acceptable)
|
|
{
|
|
kdDebug(298) << "KDatePicker::lineEnterPressed: valid date entered." << endl;
|
|
emit(dateEntered(temp));
|
|
setDate(temp);
|
|
} else {
|
|
KNotifyClient::beep();
|
|
kdDebug(298) << "KDatePicker::lineEnterPressed: invalid date entered." << endl;
|
|
}
|
|
}
|
|
|
|
void
|
|
KDatePicker::todayButtonClicked()
|
|
{
|
|
setDate(TQDate::currentDate());
|
|
}
|
|
|
|
TQSize
|
|
KDatePicker::sizeHint() const
|
|
{
|
|
return TQWidget::sizeHint();
|
|
}
|
|
|
|
void
|
|
KDatePicker::setFontSize(int s)
|
|
{
|
|
TQWidget *buttons[]= {
|
|
// yearBackward,
|
|
// monthBackward,
|
|
selectMonth,
|
|
selectYear,
|
|
// monthForward,
|
|
// yearForward
|
|
};
|
|
const int NoOfButtons=sizeof(buttons)/sizeof(buttons[0]);
|
|
int count;
|
|
TQFont font;
|
|
TQRect r;
|
|
// -----
|
|
fontsize=s;
|
|
for(count=0; count<NoOfButtons; ++count)
|
|
{
|
|
font=buttons[count]->font();
|
|
font.setPointSize(s);
|
|
buttons[count]->setFont(font);
|
|
}
|
|
TQFontMetrics metrics(selectMonth->fontMetrics());
|
|
|
|
for (int i = 1; ; ++i)
|
|
{
|
|
TQString str = KGlobal::locale()->calendar()->monthName(i,
|
|
KGlobal::locale()->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()));
|
|
}
|
|
|
|
TQSize metricBound = style().tqsizeFromContents(TQStyle::CT_ToolButton,
|
|
selectMonth,
|
|
maxMonthRect);
|
|
selectMonth->setMinimumSize(metricBound);
|
|
|
|
table->setFontSize(s);
|
|
}
|
|
|
|
void
|
|
KDatePicker::setCloseButton( bool enable )
|
|
{
|
|
if ( enable == (d->closeButton != 0L) )
|
|
return;
|
|
|
|
if ( enable ) {
|
|
d->closeButton = new TQToolButton( this );
|
|
d->closeButton->setAutoRaise(true);
|
|
d->navigationLayout->addSpacing(KDialog::spacingHint());
|
|
d->navigationLayout->addWidget(d->closeButton);
|
|
TQToolTip::add(d->closeButton, i18n("Close"));
|
|
d->closeButton->setPixmap( SmallIcon("remove") );
|
|
connect( d->closeButton, TQT_SIGNAL( clicked() ),
|
|
topLevelWidget(), TQT_SLOT( close() ) );
|
|
}
|
|
else {
|
|
delete d->closeButton;
|
|
d->closeButton = 0L;
|
|
}
|
|
|
|
updateGeometry();
|
|
}
|
|
|
|
bool KDatePicker::hasCloseButton() const
|
|
{
|
|
return (d->closeButton);
|
|
}
|
|
|
|
void KDatePicker::virtual_hook( int /*id*/, void* /*data*/ )
|
|
{ /*BASE::virtual_hook( id, data );*/ }
|
|
|