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
00374
00375 calendar->setYMD(date, calendar->year(date), month,
00376 QMIN(day, calendar->daysInMonth(date)));
00377
00378 setDate(date);
00379 }
00380
00381 void
00382 KDatePicker::selectYearClicked()
00383 {
00384 const KCalendarSystem * calendar = KGlobal::locale()->calendar();
00385
00386 if (selectYear->state() == QButton::Off)
00387 {
00388 return;
00389 }
00390
00391 int year;
00392 KPopupFrame* popup = new KPopupFrame(this);
00393 KDateInternalYearSelector* picker = new KDateInternalYearSelector(popup);
00394
00395 picker->resize(picker->sizeHint());
00396 picker->setYear( table->getDate().year() );
00397 picker->selectAll();
00398 popup->setMainWidget(picker);
00399 connect(picker, SIGNAL(closeMe(int)), popup, SLOT(close(int)));
00400 picker->setFocus();
00401 if(popup->exec(selectYear->mapToGlobal(QPoint(0, selectMonth->height()))))
00402 {
00403 QDate date;
00404 int day;
00405
00406 year=picker->getYear();
00407 date=table->getDate();
00408 day=calendar->day(date);
00409
00410
00411
00412 calendar->setYMD(date, year, calendar->month(date),
00413 QMIN(day, calendar->daysInMonth(date)));
00414
00415 setDate(date);
00416 } else {
00417 KNotifyClient::beep();
00418 }
00419
00420 delete popup;
00421 QTimer::singleShot(0, this, SLOT(ensureSelectYearIsUp()));
00422 }
00423
00424 void
00425 KDatePicker::ensureSelectYearIsUp()
00426 {
00427 if (!selectYear->isDown())
00428 {
00429 selectYear->setOn( false );
00430 }
00431 }
00432
00433 void
00434 KDatePicker::setEnabled(bool enable)
00435 {
00436 QWidget *widgets[]= {
00437 yearForward, yearBackward, monthForward, monthBackward,
00438 selectMonth, selectYear,
00439 line, table, d->selectWeek, d->todayButton };
00440 const int Size=sizeof(widgets)/sizeof(widgets[0]);
00441 int count;
00442
00443 for(count=0; count<Size; ++count)
00444 {
00445 widgets[count]->setEnabled(enable);
00446 }
00447 }
00448
00449 void
00450 KDatePicker::lineEnterPressed()
00451 {
00452 QDate temp;
00453
00454 if(val->date(line->text(), temp)==QValidator::Acceptable)
00455 {
00456 kdDebug(298) << "KDatePicker::lineEnterPressed: valid date entered." << endl;
00457 emit(dateEntered(temp));
00458 setDate(temp);
00459 } else {
00460 KNotifyClient::beep();
00461 kdDebug(298) << "KDatePicker::lineEnterPressed: invalid date entered." << endl;
00462 }
00463 }
00464
00465 void
00466 KDatePicker::todayButtonClicked()
00467 {
00468 setDate(QDate::currentDate());
00469 }
00470
00471 QSize
00472 KDatePicker::sizeHint() const
00473 {
00474 return QWidget::sizeHint();
00475 }
00476
00477 void
00478 KDatePicker::setFontSize(int s)
00479 {
00480 QWidget *buttons[]= {
00481
00482
00483 selectMonth,
00484 selectYear,
00485
00486
00487 };
00488 const int NoOfButtons=sizeof(buttons)/sizeof(buttons[0]);
00489 int count;
00490 QFont font;
00491 QRect r;
00492
00493 fontsize=s;
00494 for(count=0; count<NoOfButtons; ++count)
00495 {
00496 font=buttons[count]->font();
00497 font.setPointSize(s);
00498 buttons[count]->setFont(font);
00499 }
00500 QFontMetrics metrics(selectMonth->fontMetrics());
00501
00502 for (int i = 1; ; ++i)
00503 {
00504 QString str = KGlobal::locale()->calendar()->monthName(i,
00505 KGlobal::locale()->calendar()->year(table->getDate()), false);
00506 if (str.isNull()) break;
00507 r=metrics.boundingRect(str);
00508 maxMonthRect.setWidth(QMAX(r.width(), maxMonthRect.width()));
00509 maxMonthRect.setHeight(QMAX(r.height(), maxMonthRect.height()));
00510 }
00511
00512 QSize metricBound = style().sizeFromContents(QStyle::CT_ToolButton,
00513 selectMonth,
00514 maxMonthRect);
00515 selectMonth->setMinimumSize(metricBound);
00516
00517 table->setFontSize(s);
00518 }
00519
00520 void
00521 KDatePicker::setCloseButton( bool enable )
00522 {
00523 if ( enable == (d->closeButton != 0L) )
00524 return;
00525
00526 if ( enable ) {
00527 d->closeButton = new QToolButton( this );
00528 d->closeButton->setAutoRaise(true);
00529 d->navigationLayout->addSpacing(KDialog::spacingHint());
00530 d->navigationLayout->addWidget(d->closeButton);
00531 QToolTip::add(d->closeButton, i18n("Close"));
00532 d->closeButton->setPixmap( SmallIcon("remove") );
00533 connect( d->closeButton, SIGNAL( clicked() ),
00534 topLevelWidget(), SLOT( close() ) );
00535 }
00536 else {
00537 delete d->closeButton;
00538 d->closeButton = 0L;
00539 }
00540
00541 updateGeometry();
00542 }
00543
00544 bool KDatePicker::hasCloseButton() const
00545 {
00546 return (d->closeButton);
00547 }
00548
00549 void KDatePicker::virtual_hook( int , void* )
00550 { }
00551