kdeui Library API Documentation

kdatepicker.cpp

00001 /* -*- C++ -*- 00002 This file is part of the KDE libraries 00003 Copyright (C) 1997 Tim D. Gilman (tdgilman@best.org) 00004 (C) 1998-2001 Mirko Boehm (mirko@kde.org) 00005 This library is free software; you can redistribute it and/or 00006 modify it under the terms of the GNU Library General Public 00007 License as published by the Free Software Foundation; either 00008 version 2 of the License, or (at your option) any later version. 00009 00010 This library is distributed in the hope that it will be useful, 00011 but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00013 Library General Public License for more details. 00014 00015 You should have received a copy of the GNU Library General Public License 00016 along with this library; see the file COPYING.LIB. If not, write to 00017 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, 00018 Boston, MA 02111-1307, USA. 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 // Week numbers are defined by ISO 8601 00049 // See http://www.merlyn.demon.co.uk/weekinfo.htm for details 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 // every year can have a different number of weeks 00067 const KCalendarSystem * calendar = KGlobal::locale()->calendar(); 00068 00069 // it could be that we had 53,1..52 and now 1..53 which is the same number but different 00070 // so always fill with new values 00071 00072 d->selectWeek->clear(); 00073 00074 // We show all week numbers for all weeks between first day of year to last day of year 00075 // This of course can be a list like 53,1,2..52 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 /*calendar->daysOfWeek()*/) ) 00082 { 00083 int year = 0; 00084 QString week = i18n("Week %1").arg(calendar->weekNumber(day, &year)); 00085 if ( year != date.year() ) week += "*"; // show that this is a week from a different year 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++; // Make a little bigger 00149 00150 d->selectWeek = new QComboBox(false, this); // read only week selection 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); // needed because table emits changed only when newDate != oldDate 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; // eat event 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 // calculate the item num in the week combo box; normalize selected day so as if 1.1. is the first day of the week 00248 QDate firstDay(date.year(), 1, 1); 00249 d->selectWeek->setCurrentItem((calendar->dayOfYear(date) + calendar->dayOfWeek(firstDay) - 2) / 7/*calendar->daysInWeek()*/); 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); // this also emits dateChanged() which then calls our dateChangedSlot() 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() {} // ### in 3.2 obsolete; kept for binary compatibility 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); // first day of selected year 00338 00339 // calculate the first day in the selected week (day 1 is first day of week) 00340 date = calendar->addDays(date, week * 7/*calendar->daysOfWeek()*/ -calendar->dayOfWeek(date) + 1); 00341 00342 setDate(date); 00343 } 00344 00345 void 00346 KDatePicker::selectMonthClicked() 00347 { 00348 // every year can have different month names (in some calendar systems) 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; // canceled 00361 00362 int day = calendar->day(date); 00363 // ----- construct a valid date in this month: 00364 //date.setYMD(date.year(), month, 1); 00365 //date.setYMD(date.year(), month, QMIN(day, date.daysInMonth())); 00366 calendar->setYMD(date, calendar->year(date), month, 00367 QMIN(day, calendar->daysInMonth(date))); 00368 // ----- set this month 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 // ----- construct a valid date in this month: 00399 //date.setYMD(year, date.month(), 1); 00400 //date.setYMD(year, date.month(), QMIN(day, date.daysInMonth())); 00401 calendar->setYMD(date, year, calendar->month(date), 00402 QMIN(day, calendar->daysInMonth(date))); 00403 // ----- set this month 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 // yearBackward, 00460 // monthBackward, 00461 selectMonth, 00462 selectYear, 00463 // monthForward, 00464 // yearForward 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 /*id*/, void* /*data*/ ) 00528 { /*BASE::virtual_hook( id, data );*/ } 00529
KDE Logo
This file is part of the documentation for kdeui Library Version 3.3.0.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Wed Sep 29 09:40:32 2004 by doxygen 1.3.8 written by Dimitri van Heesch, © 1997-2003