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