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 <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 // Week numbers are defined by ISO 8601 00048 // See http://www.merlyn.demon.co.uk/weekinfo.htm for details 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 // 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 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++; // Make a little bigger 00132 00133 d->selectWeek = new QComboBox(false, this); // read only week selection 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); // needed because table emits changed only when newDate != oldDate 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; // eat event 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 // calculate the item num in the week combo box; normalize selected day so as if 1.1. is the first day of the week 00235 QDate firstDay(date.year(), 1, 1); 00236 d->selectWeek->setCurrentItem((calendar->dayOfYear(date) + calendar->dayOfWeek(firstDay) - 2) / 7/*calendar->daysInWeek()*/); 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); // this also emits dateChanged() which then calls our dateChangedSlot() 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() {} // ### in 3.2 obsolete; kept for binary compatibility 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); // first day of selected year 00325 00326 // calculate the first day in the selected week (day 1 is first day of week) 00327 date = calendar->addDays(date, week * 7/*calendar->daysOfWeek()*/ -calendar->dayOfWeek(date) + 1); 00328 00329 setDate(date); 00330 } 00331 00332 void 00333 KDatePicker::selectMonthClicked() 00334 { 00335 // every year can have different month names (in some calendar systems) 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; // canceled 00348 00349 int day = calendar->day(date); 00350 // ----- construct a valid date in this month: 00351 //date.setYMD(date.year(), month, 1); 00352 //date.setYMD(date.year(), month, QMIN(day, date.daysInMonth())); 00353 calendar->setYMD(date, calendar->year(date), month, 00354 QMIN(day, calendar->daysInMonth(date))); 00355 // ----- set this month 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 // ----- construct a valid date in this month: 00381 //date.setYMD(year, date.month(), 1); 00382 //date.setYMD(year, date.month(), QMIN(day, date.daysInMonth())); 00383 calendar->setYMD(date, year, calendar->month(date), 00384 QMIN(day, calendar->daysInMonth(date))); 00385 // ----- set this month 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 // yearBackward, 00442 // monthBackward, 00443 selectMonth, 00444 selectYear, 00445 // monthForward, 00446 // yearForward 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 /*id*/, void* /*data*/ ) 00507 { /*BASE::virtual_hook( id, data );*/ } 00508
KDE Logo
This file is part of the documentation for kdeui Library Version 3.2.3.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Mon Aug 30 22:53:55 2004 by doxygen 1.3.8 written by Dimitri van Heesch, © 1997-2003