| # kdeui Library API Documentation
Overview | Class Hierarchy | Classes | Classes (annotated) | Members | Namespaces | Source Files

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

This file is part of the documentation for kdeui Library Version 3.4.1.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Sat Jun 11 20:20:15 2005 by doxygen 1.4.1 written by Dimitri van Heesch, © 1997-2003