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