• Skip to content
  • Skip to link menu
KDE 3.5 API Reference
  • KDE API Reference
  • API Reference
  • Sitemap
  • Contact Us
 

kdeui

kdatepicker.cpp

Go to the documentation of this file.
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., 51 Franklin Street, Fifth Floor,
00018     Boston, MA 02110-1301, 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 #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 // Week numbers are defined by ISO 8601
00050 // See http://www.merlyn.demon.co.uk/weekinfo.htm for details
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   // every year can have a different number of weeks
00068   const KCalendarSystem * calendar = KGlobal::locale()->calendar();
00069 
00070   // it could be that we had 53,1..52 and now 1..53 which is the same number but different
00071   // so always fill with new values
00072 
00073   d->selectWeek->clear();
00074 
00075   // We show all week numbers for all weeks between first day of year to last day of year
00076   // This of course can be a list like 53,1,2..52
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 /*calendar->daysOfWeek()*/) )
00087   {
00088     QString week = i18n("Week %1").arg(calendar->weekNumber(day, &year));
00089     if ( year != calendar->year(day) ) week += "*";  // show that this is a week from a different year
00090     d->selectWeek->insertItem(week);
00091 
00092     // make sure that the week of the lastDay is always inserted: in Chinese calendar
00093     // system, this is not always the case
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++; // Make a little bigger
00158 
00159   d->selectWeek = new QComboBox(false, this);  // read only week selection
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);  // needed because table emits changed only when newDate != oldDate
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; // eat event
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     // calculate the item num in the week combo box; normalize selected day so as if 1.1. is the first day of the week
00257     QDate firstDay;
00258     calendar->setYMD(firstDay, calendar->year(date), 1, 1);
00259     d->selectWeek->setCurrentItem((calendar->dayOfYear(date) + calendar->dayOfWeek(firstDay) - 2) / 7/*calendar->daysInWeek()*/);
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);  // this also emits dateChanged() which then calls our dateChangedSlot()
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() {}  // ### in 3.2 obsolete; kept for binary compatibility
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);  // first day of selected year
00347 
00348   // calculate the first day in the selected week (day 1 is first day of week)
00349   date = calendar->addDays(date, week * 7/*calendar->daysOfWeek()*/ -calendar->dayOfWeek(date) + 1);
00350 
00351   setDate(date);
00352 }
00353 
00354 void
00355 KDatePicker::selectMonthClicked()
00356 {
00357   // every year can have different month names (in some calendar systems)
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;  // canceled
00370 
00371   int day = calendar->day(date);
00372   // ----- construct a valid date in this month:
00373   calendar->setYMD(date, calendar->year(date), month, 1);
00374   date = date.addDays(QMIN(day, calendar->daysInMonth(date)) - 1);
00375   // ----- set this month
00376   setDate(date);
00377 }
00378 
00379 void
00380 KDatePicker::selectYearClicked()
00381 {
00382   const KCalendarSystem * calendar = KGlobal::locale()->calendar();
00383 
00384   if (selectYear->state() == QButton::Off)
00385   {
00386     return;
00387   }
00388 
00389   int year;
00390   KPopupFrame* popup = new KPopupFrame(this);
00391   KDateInternalYearSelector* picker = new KDateInternalYearSelector(popup);
00392   // -----
00393   picker->resize(picker->sizeHint());
00394   picker->setYear( table->getDate().year() );
00395   picker->selectAll();
00396   popup->setMainWidget(picker);
00397   connect(picker, SIGNAL(closeMe(int)), popup, SLOT(close(int)));
00398   picker->setFocus();
00399   if(popup->exec(selectYear->mapToGlobal(QPoint(0, selectMonth->height()))))
00400     {
00401       QDate date;
00402       int day;
00403       // -----
00404       year=picker->getYear();
00405       date=table->getDate();
00406       day=calendar->day(date);
00407       // ----- construct a valid date in this month:
00408       //date.setYMD(year, date.month(), 1);
00409       //date.setYMD(year, date.month(), QMIN(day, date.daysInMonth()));
00410       calendar->setYMD(date, year, calendar->month(date),
00411                        QMIN(day, calendar->daysInMonth(date)));
00412       // ----- set this month
00413       setDate(date);
00414     } else {
00415       KNotifyClient::beep();
00416     }
00417 
00418   delete popup;
00419   QTimer::singleShot(0, this, SLOT(ensureSelectYearIsUp()));
00420 }
00421 
00422 void
00423 KDatePicker::ensureSelectYearIsUp()
00424 {
00425   if (!selectYear->isDown())
00426   {
00427     selectYear->setOn( false );
00428   }
00429 }
00430 
00431 void
00432 KDatePicker::setEnabled(bool enable)
00433 {
00434   QWidget *widgets[]= {
00435     yearForward, yearBackward, monthForward, monthBackward,
00436     selectMonth, selectYear,
00437     line, table, d->selectWeek, d->todayButton };
00438   const int Size=sizeof(widgets)/sizeof(widgets[0]);
00439   int count;
00440   // -----
00441   for(count=0; count<Size; ++count)
00442     {
00443       widgets[count]->setEnabled(enable);
00444     }
00445 }
00446 
00447 void
00448 KDatePicker::lineEnterPressed()
00449 {
00450   QDate temp;
00451   // -----
00452   if(val->date(line->text(), temp)==QValidator::Acceptable)
00453     {
00454         kdDebug(298) << "KDatePicker::lineEnterPressed: valid date entered." << endl;
00455         emit(dateEntered(temp));
00456         setDate(temp);
00457     } else {
00458       KNotifyClient::beep();
00459       kdDebug(298) << "KDatePicker::lineEnterPressed: invalid date entered." << endl;
00460     }
00461 }
00462 
00463 void
00464 KDatePicker::todayButtonClicked()
00465 {
00466   setDate(QDate::currentDate());
00467 }
00468 
00469 QSize
00470 KDatePicker::sizeHint() const
00471 {
00472   return QWidget::sizeHint();
00473 }
00474 
00475 void
00476 KDatePicker::setFontSize(int s)
00477 {
00478   QWidget *buttons[]= {
00479     // yearBackward,
00480     // monthBackward,
00481     selectMonth,
00482     selectYear,
00483     // monthForward,
00484     // yearForward
00485   };
00486   const int NoOfButtons=sizeof(buttons)/sizeof(buttons[0]);
00487   int count;
00488   QFont font;
00489   QRect r;
00490   // -----
00491   fontsize=s;
00492   for(count=0; count<NoOfButtons; ++count)
00493     {
00494       font=buttons[count]->font();
00495       font.setPointSize(s);
00496       buttons[count]->setFont(font);
00497     }
00498   QFontMetrics metrics(selectMonth->fontMetrics());
00499 
00500   for (int i = 1; ; ++i)
00501     {
00502       QString str = KGlobal::locale()->calendar()->monthName(i,
00503          KGlobal::locale()->calendar()->year(table->getDate()), false);
00504       if (str.isNull()) break;
00505       r=metrics.boundingRect(str);
00506       maxMonthRect.setWidth(QMAX(r.width(), maxMonthRect.width()));
00507       maxMonthRect.setHeight(QMAX(r.height(),  maxMonthRect.height()));
00508     }
00509 
00510   QSize metricBound = style().sizeFromContents(QStyle::CT_ToolButton,
00511                                                selectMonth,
00512                                                maxMonthRect);
00513   selectMonth->setMinimumSize(metricBound);
00514 
00515   table->setFontSize(s);
00516 }
00517 
00518 void
00519 KDatePicker::setCloseButton( bool enable )
00520 {
00521     if ( enable == (d->closeButton != 0L) )
00522         return;
00523 
00524     if ( enable ) {
00525         d->closeButton = new QToolButton( this );
00526         d->closeButton->setAutoRaise(true);
00527         d->navigationLayout->addSpacing(KDialog::spacingHint());
00528         d->navigationLayout->addWidget(d->closeButton);
00529         QToolTip::add(d->closeButton, i18n("Close"));
00530         d->closeButton->setPixmap( SmallIcon("remove") );
00531         connect( d->closeButton, SIGNAL( clicked() ),
00532                  topLevelWidget(), SLOT( close() ) );
00533     }
00534     else {
00535         delete d->closeButton;
00536         d->closeButton = 0L;
00537     }
00538 
00539     updateGeometry();
00540 }
00541 
00542 bool KDatePicker::hasCloseButton() const
00543 {
00544     return (d->closeButton);
00545 }
00546 
00547 void KDatePicker::virtual_hook( int /*id*/, void* /*data*/ )
00548 { /*BASE::virtual_hook( id, data );*/ }
00549 

kdeui

Skip menu "kdeui"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

API Reference

Skip menu "API Reference"
  • dcop
  • DNSSD
  • interfaces
  • Kate
  • kconf_update
  • KDECore
  • KDED
  • kdefx
  • KDEsu
  • kdeui
  • KDocTools
  • KHTML
  • KImgIO
  • KInit
  • kio
  • kioslave
  • KJS
  • KNewStuff
  • KParts
  • KUtils
Generated for API Reference by doxygen 1.5.9
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal