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