00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <qlayout.h>
00022 #include <qframe.h>
00023 #include <qpainter.h>
00024 #include <qdialog.h>
00025 #include <qstyle.h>
00026 #include <qtoolbutton.h>
00027 #include <qcombobox.h>
00028 #include <qtooltip.h>
00029 #include <qfont.h>
00030 #include <qvalidator.h>
00031 #include <qpopupmenu.h>
00032
00033 #include "kdatepicker.h"
00034 #include <kglobal.h>
00035 #include <kapplication.h>
00036 #include <kdialog.h>
00037 #include <klocale.h>
00038 #include <kiconloader.h>
00039 #include <ktoolbar.h>
00040 #include <klineedit.h>
00041 #include <kdebug.h>
00042 #include <knotifyclient.h>
00043 #include <kcalendarsystem.h>
00044
00045 #include "kdatetbl.h"
00046 #include "kdatepicker.moc"
00047
00048
00049
00050
00051 class KDatePicker::KDatePickerPrivate
00052 {
00053 public:
00054 KDatePickerPrivate() : closeButton(0L), selectWeek(0L), todayButton(0), navigationLayout(0) {}
00055
00056 void fillWeeksCombo(const QDate &date);
00057
00058 QToolButton *closeButton;
00059 QComboBox *selectWeek;
00060 QToolButton *todayButton;
00061 QBoxLayout *navigationLayout;
00062 };
00063
00064 void KDatePicker::fillWeeksCombo(const QDate &date)
00065 {
00066
00067 const KCalendarSystem * calendar = KGlobal::locale()->calendar();
00068
00069
00070
00071
00072 d->selectWeek->clear();
00073
00074
00075
00076
00077 QDate day(date.year(), 1, 1);
00078 int lastMonth = calendar->monthsInYear(day);
00079 QDate lastDay(date.year(), lastMonth, calendar->daysInMonth(QDate(date.year(), lastMonth, 1)));
00080
00081 for (; day <= lastDay; day = calendar->addDays(day, 7 ) )
00082 {
00083 int year = 0;
00084 QString week = i18n("Week %1").arg(calendar->weekNumber(day, &year));
00085 if ( year != date.year() ) week += "*";
00086 d->selectWeek->insertItem(week);
00087 }
00088 }
00089
00090 KDatePicker::KDatePicker(QWidget *parent, QDate dt, const char *name)
00091 : QFrame(parent,name)
00092 {
00093 init( dt );
00094 }
00095
00096 KDatePicker::KDatePicker(QWidget *parent, QDate dt, const char *name, WFlags f)
00097 : QFrame(parent,name, f)
00098 {
00099 init( dt );
00100 }
00101
00102 KDatePicker::KDatePicker( QWidget *parent, const char *name )
00103 : QFrame(parent,name)
00104 {
00105 init( QDate::currentDate() );
00106 }
00107
00108 void KDatePicker::init( const QDate &dt )
00109 {
00110 d = new KDatePickerPrivate();
00111
00112 QBoxLayout * topLayout = new QVBoxLayout(this);
00113
00114 d->navigationLayout = new QHBoxLayout(topLayout);
00115 d->navigationLayout->addStretch();
00116 yearBackward = new QToolButton(this);
00117 yearBackward->setAutoRaise(true);
00118 d->navigationLayout->addWidget(yearBackward);
00119 monthBackward = new QToolButton(this);
00120 monthBackward ->setAutoRaise(true);
00121 d->navigationLayout->addWidget(monthBackward);
00122 d->navigationLayout->addSpacing(KDialog::spacingHint());
00123
00124 selectMonth = new QToolButton(this);
00125 selectMonth ->setAutoRaise(true);
00126 d->navigationLayout->addWidget(selectMonth);
00127 selectYear = new QToolButton(this);
00128 selectYear->setToggleButton(true);
00129 selectYear->setAutoRaise(true);
00130 d->navigationLayout->addWidget(selectYear);
00131 d->navigationLayout->addSpacing(KDialog::spacingHint());
00132
00133 monthForward = new QToolButton(this);
00134 monthForward ->setAutoRaise(true);
00135 d->navigationLayout->addWidget(monthForward);
00136 yearForward = new QToolButton(this);
00137 yearForward ->setAutoRaise(true);
00138 d->navigationLayout->addWidget(yearForward);
00139 d->navigationLayout->addStretch();
00140
00141 line = new KLineEdit(this);
00142 val = new KDateValidator(this);
00143 table = new KDateTable(this);
00144 fontsize = KGlobalSettings::generalFont().pointSize();
00145 if (fontsize == -1)
00146 fontsize = QFontInfo(KGlobalSettings::generalFont()).pointSize();
00147
00148 fontsize++;
00149
00150 d->selectWeek = new QComboBox(false, this);
00151 d->todayButton = new QToolButton(this);
00152 d->todayButton->setIconSet(SmallIconSet("today"));
00153
00154 QToolTip::add(yearForward, i18n("Next year"));
00155 QToolTip::add(yearBackward, i18n("Previous year"));
00156 QToolTip::add(monthForward, i18n("Next month"));
00157 QToolTip::add(monthBackward, i18n("Previous month"));
00158 QToolTip::add(d->selectWeek, i18n("Select a week"));
00159 QToolTip::add(selectMonth, i18n("Select a month"));
00160 QToolTip::add(selectYear, i18n("Select a year"));
00161 QToolTip::add(d->todayButton, i18n("Select the current day"));
00162
00163
00164 setFontSize(fontsize);
00165 line->setValidator(val);
00166 line->installEventFilter( this );
00167 if ( QApplication::reverseLayout() )
00168 {
00169 yearForward->setIconSet(BarIconSet(QString::fromLatin1("2leftarrow")));
00170 yearBackward->setIconSet(BarIconSet(QString::fromLatin1("2rightarrow")));
00171 monthForward->setIconSet(BarIconSet(QString::fromLatin1("1leftarrow")));
00172 monthBackward->setIconSet(BarIconSet(QString::fromLatin1("1rightarrow")));
00173 }
00174 else
00175 {
00176 yearForward->setIconSet(BarIconSet(QString::fromLatin1("2rightarrow")));
00177 yearBackward->setIconSet(BarIconSet(QString::fromLatin1("2leftarrow")));
00178 monthForward->setIconSet(BarIconSet(QString::fromLatin1("1rightarrow")));
00179 monthBackward->setIconSet(BarIconSet(QString::fromLatin1("1leftarrow")));
00180 }
00181 connect(table, SIGNAL(dateChanged(QDate)), SLOT(dateChangedSlot(QDate)));
00182 connect(table, SIGNAL(tableClicked()), SLOT(tableClickedSlot()));
00183 connect(monthForward, SIGNAL(clicked()), SLOT(monthForwardClicked()));
00184 connect(monthBackward, SIGNAL(clicked()), SLOT(monthBackwardClicked()));
00185 connect(yearForward, SIGNAL(clicked()), SLOT(yearForwardClicked()));
00186 connect(yearBackward, SIGNAL(clicked()), SLOT(yearBackwardClicked()));
00187 connect(d->selectWeek, SIGNAL(activated(int)), SLOT(weekSelected(int)));
00188 connect(d->todayButton, SIGNAL(clicked()), SLOT(todayButtonClicked()));
00189 connect(selectMonth, SIGNAL(clicked()), SLOT(selectMonthClicked()));
00190 connect(selectYear, SIGNAL(toggled(bool)), SLOT(selectYearClicked()));
00191 connect(line, SIGNAL(returnPressed()), SLOT(lineEnterPressed()));
00192 table->setFocus();
00193
00194
00195 topLayout->addWidget(table);
00196
00197 QBoxLayout * bottomLayout = new QHBoxLayout(topLayout);
00198 bottomLayout->addWidget(d->todayButton);
00199 bottomLayout->addWidget(line);
00200 bottomLayout->addWidget(d->selectWeek);
00201
00202 table->setDate(dt);
00203 dateChangedSlot(dt);
00204 }
00205
00206 KDatePicker::~KDatePicker()
00207 {
00208 delete d;
00209 }
00210
00211 bool
00212 KDatePicker::eventFilter(QObject *o, QEvent *e )
00213 {
00214 if ( e->type() == QEvent::KeyPress ) {
00215 QKeyEvent *k = (QKeyEvent *)e;
00216
00217 if ( (k->key() == Qt::Key_Prior) ||
00218 (k->key() == Qt::Key_Next) ||
00219 (k->key() == Qt::Key_Up) ||
00220 (k->key() == Qt::Key_Down) )
00221 {
00222 QApplication::sendEvent( table, e );
00223 table->setFocus();
00224 return true;
00225 }
00226 }
00227 return QFrame::eventFilter( o, e );
00228 }
00229
00230 void
00231 KDatePicker::resizeEvent(QResizeEvent* e)
00232 {
00233 QWidget::resizeEvent(e);
00234 }
00235
00236 void
00237 KDatePicker::dateChangedSlot(QDate date)
00238 {
00239 kdDebug(298) << "KDatePicker::dateChangedSlot: date changed (" << date.year() << "/" << date.month() << "/" << date.day() << ")." << endl;
00240
00241 const KCalendarSystem * calendar = KGlobal::locale()->calendar();
00242
00243 line->setText(KGlobal::locale()->formatDate(date, true));
00244 selectMonth->setText(calendar->monthName(date, false));
00245 fillWeeksCombo(date);
00246
00247
00248 QDate firstDay(date.year(), 1, 1);
00249 d->selectWeek->setCurrentItem((calendar->dayOfYear(date) + calendar->dayOfWeek(firstDay) - 2) / 7);
00250
00251 selectYear->setText(calendar->yearString(date, false));
00252
00253 emit(dateChanged(date));
00254 }
00255
00256 void
00257 KDatePicker::tableClickedSlot()
00258 {
00259 kdDebug(298) << "KDatePicker::tableClickedSlot: table clicked." << endl;
00260 emit(dateSelected(table->getDate()));
00261 emit(tableClicked());
00262 }
00263
00264 const QDate&
00265 KDatePicker::getDate() const
00266 {
00267 return table->getDate();
00268 }
00269
00270 const QDate &
00271 KDatePicker::date() const
00272 {
00273 return table->getDate();
00274 }
00275
00276 bool
00277 KDatePicker::setDate(const QDate& date)
00278 {
00279 if(date.isValid())
00280 {
00281 table->setDate(date);
00282 return true;
00283 }
00284 else
00285 {
00286 kdDebug(298) << "KDatePicker::setDate: refusing to set invalid date." << endl;
00287 return false;
00288 }
00289 }
00290
00291 void
00292 KDatePicker::monthForwardClicked()
00293 {
00294 QDate temp;
00295 temp = KGlobal::locale()->calendar()->addMonths( table->getDate(), 1 );
00296
00297 setDate( temp );
00298 }
00299
00300 void
00301 KDatePicker::monthBackwardClicked()
00302 {
00303 QDate temp;
00304 temp = KGlobal::locale()->calendar()->addMonths( table->getDate(), -1 );
00305
00306 setDate( temp );
00307 }
00308
00309 void
00310 KDatePicker::yearForwardClicked()
00311 {
00312 QDate temp;
00313 temp = KGlobal::locale()->calendar()->addYears( table->getDate(), 1 );
00314
00315 setDate( temp );
00316 }
00317
00318 void
00319 KDatePicker::yearBackwardClicked()
00320 {
00321 QDate temp;
00322 temp = KGlobal::locale()->calendar()->addYears( table->getDate(), -1 );
00323
00324 setDate( temp );
00325 }
00326
00327 void KDatePicker::selectWeekClicked() {}
00328
00329 void
00330 KDatePicker::weekSelected(int week)
00331 {
00332 const KCalendarSystem * calendar = KGlobal::locale()->calendar();
00333
00334 QDate date = table->getDate();
00335 int year = calendar->year(date);
00336
00337 calendar->setYMD(date, year, 1, 1);
00338
00339
00340 date = calendar->addDays(date, week * 7 -calendar->dayOfWeek(date) + 1);
00341
00342 setDate(date);
00343 }
00344
00345 void
00346 KDatePicker::selectMonthClicked()
00347 {
00348
00349 const KCalendarSystem * calendar = KGlobal::locale()->calendar();
00350 QDate date = table->getDate();
00351 int i, month, months = calendar->monthsInYear(date);
00352
00353 QPopupMenu popup(selectMonth);
00354
00355 for (i = 1; i <= months; i++)
00356 popup.insertItem(calendar->monthName(i, calendar->year(date)), i);
00357
00358 popup.setActiveItem(calendar->month(date) - 1);
00359
00360 if ( (month = popup.exec(selectMonth->mapToGlobal(QPoint(0, 0)), calendar->month(date) - 1)) == -1 ) return;
00361
00362 int day = calendar->day(date);
00363
00364
00365
00366 calendar->setYMD(date, calendar->year(date), month,
00367 QMIN(day, calendar->daysInMonth(date)));
00368
00369 setDate(date);
00370 }
00371
00372 void
00373 KDatePicker::selectYearClicked()
00374 {
00375 const KCalendarSystem * calendar = KGlobal::locale()->calendar();
00376
00377 if (selectYear->state() == QButton::Off)
00378 {
00379 return;
00380 }
00381
00382 int year;
00383 KPopupFrame* popup = new KPopupFrame(this);
00384 KDateInternalYearSelector* picker = new KDateInternalYearSelector(popup);
00385
00386 picker->resize(picker->sizeHint());
00387 popup->setMainWidget(picker);
00388 connect(picker, SIGNAL(closeMe(int)), popup, SLOT(close(int)));
00389 picker->setFocus();
00390 if(popup->exec(selectYear->mapToGlobal(QPoint(0, selectMonth->height()))))
00391 {
00392 QDate date;
00393 int day;
00394
00395 year=picker->getYear();
00396 date=table->getDate();
00397 day=calendar->day(date);
00398
00399
00400
00401 calendar->setYMD(date, year, calendar->month(date),
00402 QMIN(day, calendar->daysInMonth(date)));
00403
00404 setDate(date);
00405 } else {
00406 KNotifyClient::beep();
00407 }
00408 delete popup;
00409 }
00410
00411 void
00412 KDatePicker::setEnabled(bool enable)
00413 {
00414 QWidget *widgets[]= {
00415 yearForward, yearBackward, monthForward, monthBackward,
00416 selectMonth, selectYear,
00417 line, table, d->selectWeek, d->todayButton };
00418 const int Size=sizeof(widgets)/sizeof(widgets[0]);
00419 int count;
00420
00421 for(count=0; count<Size; ++count)
00422 {
00423 widgets[count]->setEnabled(enable);
00424 }
00425 }
00426
00427 void
00428 KDatePicker::lineEnterPressed()
00429 {
00430 QDate temp;
00431
00432 if(val->date(line->text(), temp)==QValidator::Acceptable)
00433 {
00434 kdDebug(298) << "KDatePicker::lineEnterPressed: valid date entered." << endl;
00435 emit(dateEntered(temp));
00436 setDate(temp);
00437 } else {
00438 KNotifyClient::beep();
00439 kdDebug(298) << "KDatePicker::lineEnterPressed: invalid date entered." << endl;
00440 }
00441 }
00442
00443 void
00444 KDatePicker::todayButtonClicked()
00445 {
00446 setDate(QDate::currentDate());
00447 }
00448
00449 QSize
00450 KDatePicker::sizeHint() const
00451 {
00452 return QWidget::sizeHint();
00453 }
00454
00455 void
00456 KDatePicker::setFontSize(int s)
00457 {
00458 QWidget *buttons[]= {
00459
00460
00461 selectMonth,
00462 selectYear,
00463
00464
00465 };
00466 const int NoOfButtons=sizeof(buttons)/sizeof(buttons[0]);
00467 int count;
00468 QFont font;
00469 QRect r;
00470
00471 fontsize=s;
00472 for(count=0; count<NoOfButtons; ++count)
00473 {
00474 font=buttons[count]->font();
00475 font.setPointSize(s);
00476 buttons[count]->setFont(font);
00477 }
00478 QFontMetrics metrics(selectMonth->fontMetrics());
00479
00480 for (int i = 1; ; ++i)
00481 {
00482 QString str = KGlobal::locale()->calendar()->monthName(i,
00483 KGlobal::locale()->calendar()->year(table->getDate()), false);
00484 if (str.isNull()) break;
00485 r=metrics.boundingRect(str);
00486 maxMonthRect.setWidth(QMAX(r.width(), maxMonthRect.width()));
00487 maxMonthRect.setHeight(QMAX(r.height(), maxMonthRect.height()));
00488 }
00489
00490 QSize metricBound = style().sizeFromContents(QStyle::CT_ToolButton,
00491 selectMonth,
00492 maxMonthRect);
00493 selectMonth->setMinimumSize(metricBound);
00494
00495 table->setFontSize(s);
00496 }
00497
00498 void
00499 KDatePicker::setCloseButton( bool enable )
00500 {
00501 if ( enable == (d->closeButton != 0L) )
00502 return;
00503
00504 if ( enable ) {
00505 d->closeButton = new QToolButton( this );
00506 d->closeButton->setAutoRaise(true);
00507 d->navigationLayout->addSpacing(KDialog::spacingHint());
00508 d->navigationLayout->addWidget(d->closeButton);
00509 QToolTip::add(d->closeButton, i18n("Close"));
00510 d->closeButton->setPixmap( SmallIcon("remove") );
00511 connect( d->closeButton, SIGNAL( clicked() ),
00512 topLevelWidget(), SLOT( close() ) );
00513 }
00514 else {
00515 delete d->closeButton;
00516 d->closeButton = 0L;
00517 }
00518
00519 updateGeometry();
00520 }
00521
00522 bool KDatePicker::hasCloseButton() const
00523 {
00524 return (d->closeButton != 0L);
00525 }
00526
00527 void KDatePicker::virtual_hook( int , void* )
00528 { }
00529