00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "kptcalendarpanel.h"
00025 #include "kptdatetable.h"
00026 #include "kptcalendar.h"
00027
00028
00029 #include <kglobal.h>
00030 #include <kapplication.h>
00031 #include <klocale.h>
00032 #include <kcalendarsystem.h>
00033 #include <kiconloader.h>
00034 #include <q3frame.h>
00035 #include <qpainter.h>
00036 #include <qdialog.h>
00037 #include <qstyle.h>
00038 #include <qtoolbutton.h>
00039 #include <QToolTip>
00040 #include <QFont>
00041
00042 #include <QKeyEvent>
00043 #include <QEvent>
00044 #include <QResizeEvent>
00045 #include <klineedit.h>
00046 #include <qvalidator.h>
00047 #include <kdebug.h>
00048 #include <knotification.h>
00049
00050 namespace KPlato
00051 {
00052
00053 class CalendarPanel::CalendarPanelPrivate
00054 {
00055 public:
00056 CalendarPanelPrivate() : closeButton(0L), selectWeek(0L) {}
00057
00058 QToolButton *closeButton;
00059 QToolButton *selectWeek;
00060 };
00061
00062
00063 CalendarPanel::CalendarPanel(QWidget *parent, QDate dt, const char *name, Qt::WFlags f)
00064 : Q3Frame(parent,name, f)
00065 {
00066 init( dt );
00067 }
00068
00069 CalendarPanel::CalendarPanel( QWidget *parent, const char *name )
00070 : Q3Frame(parent,name)
00071 {
00072 init( QDate::currentDate() );
00073 }
00074
00075 void CalendarPanel::init( const QDate &dt )
00076 {
00077 yearForward = new QToolButton(this);
00078 yearBackward = new QToolButton(this);
00079 monthForward = new QToolButton(this);
00080 monthBackward = new QToolButton(this);
00081 selectMonth = new QToolButton(this);
00082 selectYear = new QToolButton(this);
00083 line = new KLineEdit(this);
00084 val = new DateValidator(this);
00085 table = new DateTable(this, dt, "Calendar table", 0);
00086 fontsize = 10;
00087
00088 d = new CalendarPanelPrivate();
00089 d->selectWeek = new QToolButton( this );
00090
00091 yearForward->setToolTip( i18n("Next year"));
00092 yearBackward->setToolTip( i18n("Previous year"));
00093 monthForward->setToolTip( i18n("Next month"));
00094 monthBackward->setToolTip( i18n("Previous month"));
00095 d->selectWeek->setToolTip( i18n("Select a week"));
00096 selectMonth->setToolTip( i18n("Select a month"));
00097 selectYear->setToolTip( i18n("Select a year"));
00098
00099
00100 setFontSize(10);
00101 line->setValidator(val);
00102 line->installEventFilter( this );
00103 yearForward->setPixmap(BarIcon(QString::fromLatin1("2rightarrow")));
00104 yearBackward->setPixmap(BarIcon(QString::fromLatin1("2leftarrow")));
00105 monthForward->setPixmap(BarIcon(QString::fromLatin1("1rightarrow")));
00106 monthBackward->setPixmap(BarIcon(QString::fromLatin1("1leftarrow")));
00107 setDate(dt);
00108 connect(table, SIGNAL(dateChanged(QDate)), SLOT(dateChangedSlot(QDate)));
00109 connect(table, SIGNAL(tableClicked()), SLOT(tableClickedSlot()));
00110 connect(monthForward, SIGNAL(clicked()), SLOT(monthForwardClicked()));
00111 connect(monthBackward, SIGNAL(clicked()), SLOT(monthBackwardClicked()));
00112 connect(yearForward, SIGNAL(clicked()), SLOT(yearForwardClicked()));
00113 connect(yearBackward, SIGNAL(clicked()), SLOT(yearBackwardClicked()));
00114 connect(d->selectWeek, SIGNAL(clicked()), SLOT(selectWeekClicked()));
00115 connect(selectMonth, SIGNAL(clicked()), SLOT(selectMonthClicked()));
00116 connect(selectYear, SIGNAL(clicked()), SLOT(selectYearClicked()));
00117 connect(line, SIGNAL(returnPressed()), SLOT(lineEnterPressed()));
00118
00119 connect(table, SIGNAL(weekdaySelected(int)), SLOT(slotWeekdaySelected(int)));
00120 connect(table, SIGNAL(weekSelected(int, int)), SLOT(slotWeekSelected(int, int)));
00121 connect(table, SIGNAL(selectionCleared()), SLOT(slotSelectionCleared()));
00122
00123 table->setFocus();
00124 }
00125
00126 CalendarPanel::~CalendarPanel()
00127 {
00128 delete d;
00129 }
00130
00131 bool
00132 CalendarPanel::eventFilter(QObject *o, QEvent *e )
00133 {
00134 if ( e->type() == QEvent::KeyPress ) {
00135 QKeyEvent *k = (QKeyEvent *)e;
00136
00137 if ( (k->key() == Qt::Key_PageUp) ||
00138 (k->key() == Qt::Key_PageDown) ||
00139 (k->key() == Qt::Key_Up) ||
00140 (k->key() == Qt::Key_Down) )
00141 {
00142 QApplication::sendEvent( table, e );
00143 table->setFocus();
00144 return TRUE;
00145 }
00146 }
00147 return Q3Frame::eventFilter( o, e );
00148 }
00149
00150 void
00151 CalendarPanel::resizeEvent(QResizeEvent*)
00152 {
00153 QWidget *buttons[] = {
00154 yearBackward,
00155 monthBackward,
00156 selectMonth,
00157 selectYear,
00158 monthForward,
00159 yearForward,
00160 d->closeButton
00161 };
00162 const int NoOfButtons=sizeof(buttons)/sizeof(buttons[0]);
00163 QSize sizes[NoOfButtons];
00164 int buttonHeight=0;
00165 int count;
00166 int w=0;
00167 int x=0;
00168
00169 for(count=0; count<NoOfButtons; ++count) {
00170 if ( buttons[count] ) {
00171 sizes[count]=buttons[count]->sizeHint();
00172 buttonHeight=qMax(buttonHeight, sizes[count].height());
00173 }
00174 else
00175 sizes[count] = QSize(0,0);
00176 }
00177
00178
00179 for(count=0; count<NoOfButtons; ++count) {
00180 if(buttons[count]==selectMonth) {
00181
00182
00183 sizes[count].setWidth( selectMonth->sizeHint().width() );
00184 }
00185 }
00186
00187 w=0;
00188 for(count=0; count<NoOfButtons; ++count)
00189 {
00190 w +=sizes[count].width();
00191 }
00192 x = (qMax(w, width())-w)/2;
00193
00194
00195 for(count=0; count<NoOfButtons; ++count)
00196 {
00197 w=sizes[count].width();
00198 if ( buttons[count] )
00199 buttons[count]->setGeometry(x, 0, w, buttonHeight);
00200 x+=w;
00201 }
00202
00203 sizes[0]=line->sizeHint();
00204 int week_width=d->selectWeek->fontMetrics().width(i18n("Week XX"))+((d->closeButton != 0L) ? 50 : 20);
00205 line->setGeometry(0, height()-sizes[0].height(), width()-week_width, sizes[0].height());
00206 d->selectWeek->setGeometry(width()-week_width, height()-sizes[0].height(), week_width, sizes[0].height());
00207
00208 table->setGeometry(0, buttonHeight, width(),
00209 height()-buttonHeight-sizes[0].height());
00210 }
00211
00212 void
00213 CalendarPanel::dateChangedSlot(QDate date)
00214 {
00215
00216 line->setText(KGlobal::locale()->formatDate(date, true));
00217 d->selectWeek->setText(i18n("Week %1", weekOfYear(date)));
00218 selectMonth->setText(KGlobal::locale()->calendar()->monthName(date.month(), false));
00219 selectYear->setText(date.toString("yyyy"));
00220 emit(dateChanged(date));
00221 }
00222
00223 void
00224 CalendarPanel::tableClickedSlot()
00225 {
00226
00227 emit(dateSelected(table->getDate()));
00228 emit(tableClicked());
00229 }
00230
00231 const QDate&
00232 CalendarPanel::getDate() const
00233 {
00234 return table->getDate();
00235 }
00236
00237 const QDate &
00238 CalendarPanel::date() const
00239 {
00240 return table->getDate();
00241 }
00242
00243 bool
00244 CalendarPanel::setDate(const QDate& date)
00245 {
00246 if(date.isValid()) {
00247 QString temp;
00248
00249 table->setDate(date);
00250 d->selectWeek->setText(i18n("Week %1", weekOfYear(date)));
00251 selectMonth->setText(KGlobal::locale()->calendar()->monthName(date.month(), false));
00252 temp.setNum(date.year());
00253 selectYear->setText(temp);
00254 line->setText(KGlobal::locale()->formatDate(date, true));
00255 return true;
00256 } else {
00257 kDebug() << "CalendarPanel::setDate: refusing to set invalid date." << endl;
00258 return false;
00259 }
00260 }
00261
00262 void
00263 CalendarPanel::monthForwardClicked()
00264 {
00265 setDate( table->getDate().addMonths(1) );
00266 }
00267
00268 void
00269 CalendarPanel::monthBackwardClicked()
00270 {
00271 setDate( table->getDate().addMonths(-1) );
00272 }
00273
00274 void
00275 CalendarPanel::yearForwardClicked()
00276 {
00277 setDate( table->getDate().addYears(1) );
00278 }
00279
00280 void
00281 CalendarPanel::yearBackwardClicked()
00282 {
00283 setDate( table->getDate().addYears(-1) );
00284 }
00285
00286 void
00287 CalendarPanel::selectWeekClicked()
00288 {
00289 int week;
00290 PopupFrame* popup = new PopupFrame(this);
00291 DateInternalWeekSelector* picker = new DateInternalWeekSelector(fontsize, popup);
00292
00293 picker->resize(picker->sizeHint());
00294 popup->setMainWidget(picker);
00295 connect(picker, SIGNAL(closeMe(int)), popup, SLOT(close(int)));
00296 picker->setFocus();
00297 if(popup->exec(d->selectWeek->mapToGlobal(QPoint(0, d->selectWeek->height()))))
00298 {
00299 QDate date;
00300 int year;
00301
00302 week=picker->getWeek();
00303 date=table->getDate();
00304 year=date.year();
00305
00306 date.setYMD(year, 1, 1);
00307 while (weekOfYear(date)>50)
00308 date=date.addDays(1);
00309 while (weekOfYear(date)<week && (week!=53 || (week==53 &&
00310 (weekOfYear(date)!=52 || weekOfYear(date.addDays(1))!=1))))
00311 date=date.addDays(1);
00312 if (week==53 && weekOfYear(date)==52)
00313 while (weekOfYear(date.addDays(-1))==52)
00314 date=date.addDays(-1);
00315
00316 setDate(date);
00317 } else {
00318 KNotification::beep();
00319 }
00320 delete popup;
00321 }
00322
00323 void
00324 CalendarPanel::selectMonthClicked()
00325 {
00326 int month;
00327 PopupFrame* popup = new PopupFrame(this);
00328 DateInternalMonthPicker* picker = new DateInternalMonthPicker(fontsize, popup);
00329
00330 picker->resize(picker->sizeHint());
00331 popup->setMainWidget(picker);
00332 picker->setFocus();
00333 connect(picker, SIGNAL(closeMe(int)), popup, SLOT(close(int)));
00334 if(popup->exec(selectMonth->mapToGlobal(QPoint(0, selectMonth->height()))))
00335 {
00336 QDate date;
00337 int day;
00338
00339 month=picker->getResult();
00340 date=table->getDate();
00341 day=date.day();
00342
00343 date.setYMD(date.year(), month, 1);
00344 date.setYMD(date.year(), month, qMin(day, date.daysInMonth()));
00345
00346 setDate(date);
00347 } else {
00348 KNotification::beep();
00349 }
00350 delete popup;
00351 }
00352
00353 void
00354 CalendarPanel::selectYearClicked()
00355 {
00356 int year;
00357 PopupFrame* popup = new PopupFrame(this);
00358 DateInternalYearSelector* picker = new DateInternalYearSelector(fontsize, popup);
00359
00360 picker->resize(picker->sizeHint());
00361 popup->setMainWidget(picker);
00362 connect(picker, SIGNAL(closeMe(int)), popup, SLOT(close(int)));
00363 picker->setFocus();
00364 if(popup->exec(selectYear->mapToGlobal(QPoint(0, selectMonth->height()))))
00365 {
00366 QDate date;
00367 int day;
00368
00369 year=picker->getYear();
00370 date=table->getDate();
00371 day=date.day();
00372
00373 date.setYMD(year, date.month(), 1);
00374 date.setYMD(year, date.month(), qMin(day, date.daysInMonth()));
00375
00376 setDate(date);
00377 } else {
00378 KNotification::beep();
00379 }
00380 delete popup;
00381 }
00382
00383 void
00384 CalendarPanel::setEnabled(bool enable)
00385 {
00386 QWidget *widgets[]= {
00387 yearForward, yearBackward, monthForward, monthBackward,
00388 selectMonth, selectYear,
00389 line, table, d->selectWeek };
00390 const int Size=sizeof(widgets)/sizeof(widgets[0]);
00391 int count;
00392
00393 for(count=0; count<Size; ++count)
00394 {
00395 widgets[count]->setEnabled(enable);
00396 }
00397 table->setEnabled(enable);
00398 }
00399
00400 void
00401 CalendarPanel::lineEnterPressed()
00402 {
00403 QDate temp;
00404
00405 if(val->date(line->text(), temp)==QValidator::Acceptable)
00406 {
00407
00408 emit(dateEntered(temp));
00409 setDate(temp);
00410 } else {
00411 KNotification::beep();
00412
00413 }
00414 }
00415
00416 QSize
00417 CalendarPanel::sizeHint() const
00418 {
00419 QSize tableSize=table->sizeHint();
00420 QWidget *buttons[]={
00421 yearBackward,
00422 monthBackward,
00423 selectMonth,
00424 selectYear,
00425 monthForward,
00426 yearForward,
00427 d->closeButton
00428 };
00429 const int NoOfButtons=sizeof(buttons)/sizeof(buttons[0]);
00430 QSize sizes[NoOfButtons];
00431 int cx=0, cy=0, count;
00432
00433 for(count=0; count<NoOfButtons; ++count) {
00434 if ( buttons[count] )
00435 sizes[count]=buttons[count]->sizeHint();
00436 else
00437 sizes[count] = QSize(0,0);
00438
00439 if(buttons[count]==selectMonth) {
00440
00441
00442
00443 cx += qMax( selectMonth->sizeHint().width(), maxMonthRect.width()+2*QApplication::style()->pixelMetric(QStyle::PM_ButtonMargin) );
00444 } else {
00445 cx+=sizes[count].width();
00446 }
00447 cy=qMax(sizes[count].height(), cy);
00448 }
00449
00450 cx=qMax(cx, tableSize.width());
00451
00452 cy+=tableSize.height()+line->sizeHint().height();
00453 return QSize(cx, cy);
00454 }
00455
00456 void
00457 CalendarPanel::setFontSize(int s)
00458 {
00459 QWidget *buttons[]= {
00460
00461
00462 selectMonth,
00463 selectYear,
00464
00465
00466 };
00467 const int NoOfButtons=sizeof(buttons)/sizeof(buttons[0]);
00468 int count;
00469 QFont font;
00470 QRect r;
00471
00472 fontsize=s;
00473 for(count=0; count<NoOfButtons; ++count)
00474 {
00475 font=buttons[count]->font();
00476 font.setPointSize(s);
00477 buttons[count]->setFont(font);
00478 }
00479 QFontMetrics metrics(selectMonth->fontMetrics());
00480 for(int i=1; i <= 12; ++i)
00481 {
00482 r=metrics.boundingRect(KGlobal::locale()->calendar()->monthName(i, false));
00483 maxMonthRect.setWidth(qMax(r.width(), maxMonthRect.width()));
00484 maxMonthRect.setHeight(qMax(r.height(), maxMonthRect.height()));
00485 }
00486 table->setFontSize(s);
00487 }
00488
00489 void
00490 CalendarPanel::setCloseButton( bool enable )
00491 {
00492 if ( enable == (d->closeButton != 0L) )
00493 return;
00494
00495 if ( enable ) {
00496 d->closeButton = new QToolButton( this );
00497 d->closeButton->setToolTip( i18n("Close"));
00498 d->closeButton->setPixmap( SmallIcon("remove") );
00499 connect( d->closeButton, SIGNAL( clicked() ),
00500 topLevelWidget(), SLOT( close() ) );
00501 }
00502 else {
00503 delete d->closeButton;
00504 d->closeButton = 0L;
00505 }
00506
00507 updateGeometry();
00508 }
00509
00510 bool CalendarPanel::hasCloseButton() const
00511 {
00512 return (d->closeButton != 0L);
00513 }
00514
00515 int CalendarPanel::weekOfYear(QDate date)
00516 {
00517
00518 int year, week, wday, jan1wday, nextjan1wday;
00519 QDate jan1date, nextjan1date;
00520
00521 year=date.year();
00522 wday=date.dayOfWeek();
00523
00524 jan1date=QDate(year,1,1);
00525 jan1wday=jan1date.dayOfWeek();
00526
00527 week = (date.dayOfYear()-1 + jan1wday-1)/7 + ((jan1wday-1) == 0 ? 1 : 0);
00528
00529
00530 if ((week == 0) && (jan1wday > 4 )) {
00531 QDate tmpdate=QDate(year-1,12,31);
00532 return weekOfYear(tmpdate);
00533 }
00534
00535 if ((jan1wday <= 4 ) && (jan1wday > 1 ))
00536 week++;
00537
00538 if (week == 53) {
00539 nextjan1date=QDate(year+1, 1, 1);
00540 nextjan1wday = nextjan1date.dayOfWeek();
00541 if (nextjan1wday <= 4 )
00542 week = 1;
00543 }
00544
00545 return week;
00546 }
00547
00548 void CalendarPanel::slotWeekdaySelected(int day) {
00549
00550 emit weekdaySelected(day);
00551 }
00552
00553 void CalendarPanel::slotWeekSelected(int week, int year) {
00554
00555 emit weekSelected(week, year);
00556 }
00557
00558 void CalendarPanel::setCalendar(Calendar *cal) {
00559
00560 table->clear();
00561 if (cal) {
00562 table->setMarkedWeekdays(cal->weekdaysMap());
00563
00564 foreach (CalendarDay *d, cal->days()) {
00565 if (d->state() != Map::None) {
00566 table->addMarkedDate(d->date(), d->state());
00567
00568 }
00569 }
00570 setEnabled(true);
00571 table->setFocus();
00572 }
00573 }
00574
00575 DateMap CalendarPanel::selectedDates() {
00576 return table->selectedDates();
00577 }
00578
00579 IntMap CalendarPanel::selectedWeekdays() {
00580 return table->selectedWeekdays();
00581 }
00582
00583 DateMap CalendarPanel::markedDates() {
00584 return table->markedDates();
00585 }
00586
00587 IntMap CalendarPanel::markedWeekdays() {
00588 return table->markedWeekdays();
00589 }
00590
00591 void CalendarPanel::clear() {
00592 table->clear();
00593 setEnabled(false);
00594 }
00595
00596 void CalendarPanel::markSelected(int state) {
00597 table->markSelected(state);
00598 }
00599
00600 void CalendarPanel::slotSelectionCleared() {
00601 emit selectionCleared();
00602 }
00603
00604 void CalendarPanel::virtual_hook( int , void* )
00605 { }
00606
00607 }
00608
00609 #include "kptcalendarpanel.moc"