kdatetbl.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., 51 Franklin Street, Fifth Floor, 00018 Boston, MA 02110-1301, USA. 00019 */ 00020 00022 // 00023 // Copyright (C) 1997 Tim D. Gilman 00024 // (C) 1998-2001 Mirko Boehm 00025 // Written using Qt (http://www.troll.no) for the 00026 // KDE project (http://www.kde.org) 00027 // 00028 // This is a support class for the KDatePicker class. It just 00029 // draws the calender table without titles, but could theoretically 00030 // be used as a standalone. 00031 // 00032 // When a date is selected by the user, it emits a signal: 00033 // dateSelected(QDate) 00034 00035 #include <kconfig.h> 00036 #include <kglobal.h> 00037 #include <kglobalsettings.h> 00038 #include <kapplication.h> 00039 #include <kaccel.h> 00040 #include <klocale.h> 00041 #include <kdebug.h> 00042 #include <knotifyclient.h> 00043 #include <kcalendarsystem.h> 00044 #include <kshortcut.h> 00045 #include <kstdaccel.h> 00046 #include "kdatepicker.h" 00047 #include "kdatetbl.h" 00048 #include "kpopupmenu.h" 00049 #include <qdatetime.h> 00050 #include <qstring.h> 00051 #include <qpen.h> 00052 #include <qpainter.h> 00053 #include <qdialog.h> 00054 #include <qdict.h> 00055 #include <assert.h> 00056 00057 00058 class KDateTable::KDateTablePrivate 00059 { 00060 public: 00061 KDateTablePrivate() 00062 { 00063 popupMenuEnabled=false; 00064 useCustomColors=false; 00065 } 00066 00067 ~KDateTablePrivate() 00068 { 00069 } 00070 00071 bool popupMenuEnabled; 00072 bool useCustomColors; 00073 00074 struct DatePaintingMode 00075 { 00076 QColor fgColor; 00077 QColor bgColor; 00078 BackgroundMode bgMode; 00079 }; 00080 QDict <DatePaintingMode> customPaintingModes; 00081 00082 }; 00083 00084 00085 KDateValidator::KDateValidator(QWidget* parent, const char* name) 00086 : QValidator(parent, name) 00087 { 00088 } 00089 00090 QValidator::State 00091 KDateValidator::validate(QString& text, int&) const 00092 { 00093 QDate temp; 00094 // ----- everything is tested in date(): 00095 return date(text, temp); 00096 } 00097 00098 QValidator::State 00099 KDateValidator::date(const QString& text, QDate& d) const 00100 { 00101 QDate tmp = KGlobal::locale()->readDate(text); 00102 if (!tmp.isNull()) 00103 { 00104 d = tmp; 00105 return Acceptable; 00106 } else 00107 return Valid; 00108 } 00109 00110 void 00111 KDateValidator::fixup( QString& ) const 00112 { 00113 00114 } 00115 00116 KDateTable::KDateTable(QWidget *parent, QDate date_, const char* name, WFlags f) 00117 : QGridView(parent, name, (f | WNoAutoErase)) 00118 { 00119 d = new KDateTablePrivate; 00120 setFontSize(10); 00121 if(!date_.isValid()) 00122 { 00123 kdDebug() << "KDateTable ctor: WARNING: Given date is invalid, using current date." << endl; 00124 date_=QDate::currentDate(); 00125 } 00126 setFocusPolicy( QWidget::StrongFocus ); 00127 setNumRows(7); // 6 weeks max + headline 00128 setNumCols(7); // 7 days a week 00129 setHScrollBarMode(AlwaysOff); 00130 setVScrollBarMode(AlwaysOff); 00131 viewport()->setEraseColor(KGlobalSettings::baseColor()); 00132 setDate(date_); // this initializes firstday, numdays, numDaysPrevMonth 00133 00134 initAccels(); 00135 } 00136 00137 KDateTable::KDateTable(QWidget *parent, const char* name, WFlags f) 00138 : QGridView(parent, name, (f | WNoAutoErase)) 00139 { 00140 d = new KDateTablePrivate; 00141 setFontSize(10); 00142 setFocusPolicy( QWidget::StrongFocus ); 00143 setNumRows(7); // 6 weeks max + headline 00144 setNumCols(7); // 7 days a week 00145 setHScrollBarMode(AlwaysOff); 00146 setVScrollBarMode(AlwaysOff); 00147 viewport()->setEraseColor(KGlobalSettings::baseColor()); 00148 setDate(QDate::currentDate()); // this initializes firstday, numdays, numDaysPrevMonth 00149 initAccels(); 00150 } 00151 00152 KDateTable::~KDateTable() 00153 { 00154 delete d; 00155 } 00156 00157 void KDateTable::initAccels() 00158 { 00159 KAccel* accel = new KAccel(this, "date table accel"); 00160 accel->insert(KStdAccel::Next, this, SLOT(nextMonth())); 00161 accel->insert(KStdAccel::Prior, this, SLOT(previousMonth())); 00162 accel->insert(KStdAccel::Home, this, SLOT(beginningOfMonth())); 00163 accel->insert(KStdAccel::End, this, SLOT(endOfMonth())); 00164 accel->insert(KStdAccel::BeginningOfLine, this, SLOT(beginningOfWeek())); 00165 accel->insert(KStdAccel::EndOfLine, this, SLOT(endOfWeek())); 00166 accel->readSettings(); 00167 } 00168 00169 int KDateTable::posFromDate( const QDate &dt ) 00170 { 00171 const KCalendarSystem * calendar = KGlobal::locale()->calendar(); 00172 const int firstWeekDay = KGlobal::locale()->weekStartDay(); 00173 int pos = calendar->day( dt ); 00174 int offset = (firstday - firstWeekDay + 7) % 7; 00175 // make sure at least one day of the previous month is visible. 00176 // adjust this <1 if more days should be forced visible: 00177 if ( offset < 1 ) offset += 7; 00178 return pos + offset; 00179 } 00180 00181 QDate KDateTable::dateFromPos( int pos ) 00182 { 00183 QDate pCellDate; 00184 const KCalendarSystem * calendar = KGlobal::locale()->calendar(); 00185 calendar->setYMD(pCellDate, calendar->year(date), calendar->month(date), 1); 00186 00187 int firstWeekDay = KGlobal::locale()->weekStartDay(); 00188 int offset = (firstday - firstWeekDay + 7) % 7; 00189 // make sure at least one day of the previous month is visible. 00190 // adjust this <1 if more days should be forced visible: 00191 if ( offset < 1 ) offset += 7; 00192 pCellDate = calendar->addDays( pCellDate, pos - offset ); 00193 return pCellDate; 00194 } 00195 00196 void 00197 KDateTable::paintEmptyArea(QPainter *paint, int, int, int, int) 00198 { 00199 // Erase the unused areas on the right and bottom. 00200 QRect unusedRight = frameRect(); 00201 unusedRight.setLeft(gridSize().width()); 00202 00203 QRect unusedBottom = frameRect(); 00204 unusedBottom.setTop(gridSize().height()); 00205 00206 paint->eraseRect(unusedRight); 00207 paint->eraseRect(unusedBottom); 00208 } 00209 00210 void 00211 KDateTable::paintCell(QPainter *painter, int row, int col) 00212 { 00213 const KCalendarSystem * calendar = KGlobal::locale()->calendar(); 00214 00215 QRect rect; 00216 QString text; 00217 QPen pen; 00218 int w=cellWidth(); 00219 int h=cellHeight(); 00220 QFont font=KGlobalSettings::generalFont(); 00221 // ----- 00222 00223 if(row == 0) 00224 { // we are drawing the headline 00225 font.setBold(true); 00226 painter->setFont(font); 00227 bool normalday = true; 00228 int firstWeekDay = KGlobal::locale()->weekStartDay(); 00229 int daynum = ( col+firstWeekDay < 8 ) ? col+firstWeekDay : 00230 col+firstWeekDay-7; 00231 if ( daynum == calendar->weekDayOfPray() || 00232 ( daynum == 6 && calendar->calendarName() == "gregorian" ) ) 00233 normalday=false; 00234 00235 QBrush brushInvertTitle(colorGroup().base()); 00236 QColor titleColor(isEnabled()?( KGlobalSettings::activeTitleColor() ):( KGlobalSettings::inactiveTitleColor() ) ); 00237 QColor textColor(isEnabled()?( KGlobalSettings::activeTextColor() ):( KGlobalSettings::inactiveTextColor() ) ); 00238 if (!normalday) 00239 { 00240 painter->setPen(textColor); 00241 painter->setBrush(textColor); 00242 painter->drawRect(0, 0, w, h); 00243 painter->setPen(titleColor); 00244 } else { 00245 painter->setPen(titleColor); 00246 painter->setBrush(titleColor); 00247 painter->drawRect(0, 0, w, h); 00248 painter->setPen(textColor); 00249 } 00250 painter->drawText(0, 0, w, h-1, AlignCenter, 00251 calendar->weekDayName(daynum, true), -1, &rect); 00252 painter->setPen(colorGroup().text()); 00253 painter->moveTo(0, h-1); 00254 painter->lineTo(w-1, h-1); 00255 // ----- draw the weekday: 00256 } else { 00257 bool paintRect=true; 00258 painter->setFont(font); 00259 int pos=7*(row-1)+col; 00260 00261 QDate pCellDate = dateFromPos( pos ); 00262 // First day of month 00263 text = calendar->dayString(pCellDate, true); 00264 if( calendar->month(pCellDate) != calendar->month(date) ) 00265 { // we are either 00266 // ° painting a day of the previous month or 00267 // ° painting a day of the following month 00268 // TODO: don't hardcode gray here! Use a color with less contrast to the background than normal text. 00269 painter->setPen( colorGroup().mid() ); 00270 // painter->setPen(gray); 00271 } else { // paint a day of the current month 00272 if ( d->useCustomColors ) 00273 { 00274 KDateTablePrivate::DatePaintingMode *mode=d->customPaintingModes[pCellDate.toString()]; 00275 if (mode) 00276 { 00277 if (mode->bgMode != NoBgMode) 00278 { 00279 QBrush oldbrush=painter->brush(); 00280 painter->setBrush( mode->bgColor ); 00281 switch(mode->bgMode) 00282 { 00283 case(CircleMode) : painter->drawEllipse(0,0,w,h);break; 00284 case(RectangleMode) : painter->drawRect(0,0,w,h);break; 00285 case(NoBgMode) : // Should never be here, but just to get one 00286 // less warning when compiling 00287 default: break; 00288 } 00289 painter->setBrush( oldbrush ); 00290 paintRect=false; 00291 } 00292 painter->setPen( mode->fgColor ); 00293 } else 00294 painter->setPen(colorGroup().text()); 00295 } else //if ( firstWeekDay < 4 ) // <- this doesn' make sense at all! 00296 painter->setPen(colorGroup().text()); 00297 } 00298 00299 pen=painter->pen(); 00300 int firstWeekDay=KGlobal::locale()->weekStartDay(); 00301 int offset=firstday-firstWeekDay; 00302 if(offset<1) 00303 offset+=7; 00304 int d = calendar->day(date); 00305 if( (offset+d) == (pos+1)) 00306 { 00307 // draw the currently selected date 00308 if (isEnabled()) 00309 { 00310 painter->setPen(colorGroup().highlight()); 00311 painter->setBrush(colorGroup().highlight()); 00312 } 00313 else 00314 { 00315 painter->setPen(colorGroup().text()); 00316 painter->setBrush(colorGroup().text()); 00317 } 00318 pen=colorGroup().highlightedText(); 00319 } else { 00320 painter->setBrush(paletteBackgroundColor()); 00321 painter->setPen(paletteBackgroundColor()); 00322 // painter->setBrush(colorGroup().base()); 00323 // painter->setPen(colorGroup().base()); 00324 } 00325 00326 if ( pCellDate == QDate::currentDate() ) 00327 { 00328 painter->setPen(colorGroup().text()); 00329 } 00330 00331 if ( paintRect ) painter->drawRect(0, 0, w, h); 00332 painter->setPen(pen); 00333 painter->drawText(0, 0, w, h, AlignCenter, text, -1, &rect); 00334 } 00335 if(rect.width()>maxCell.width()) maxCell.setWidth(rect.width()); 00336 if(rect.height()>maxCell.height()) maxCell.setHeight(rect.height()); 00337 } 00338 00339 void KDateTable::nextMonth() 00340 { 00341 const KCalendarSystem * calendar = KGlobal::locale()->calendar(); 00342 setDate(calendar->addMonths( date, 1 )); 00343 } 00344 00345 void KDateTable::previousMonth() 00346 { 00347 const KCalendarSystem * calendar = KGlobal::locale()->calendar(); 00348 setDate(calendar->addMonths( date, -1 )); 00349 } 00350 00351 void KDateTable::beginningOfMonth() 00352 { 00353 setDate(date.addDays(1 - date.day())); 00354 } 00355 00356 void KDateTable::endOfMonth() 00357 { 00358 setDate(date.addDays(date.daysInMonth() - date.day())); 00359 } 00360 00361 void KDateTable::beginningOfWeek() 00362 { 00363 setDate(date.addDays(1 - date.dayOfWeek())); 00364 } 00365 00366 void KDateTable::endOfWeek() 00367 { 00368 setDate(date.addDays(7 - date.dayOfWeek())); 00369 } 00370 00371 void 00372 KDateTable::keyPressEvent( QKeyEvent *e ) 00373 { 00374 switch( e->key() ) { 00375 case Key_Up: 00376 setDate(date.addDays(-7)); 00377 break; 00378 case Key_Down: 00379 setDate(date.addDays(7)); 00380 break; 00381 case Key_Left: 00382 setDate(date.addDays(-1)); 00383 break; 00384 case Key_Right: 00385 setDate(date.addDays(1)); 00386 break; 00387 case Key_Minus: 00388 setDate(date.addDays(-1)); 00389 break; 00390 case Key_Plus: 00391 setDate(date.addDays(1)); 00392 break; 00393 case Key_N: 00394 setDate(QDate::currentDate()); 00395 break; 00396 case Key_Return: 00397 case Key_Enter: 00398 emit tableClicked(); 00399 break; 00400 case Key_Control: 00401 case Key_Alt: 00402 case Key_Meta: 00403 case Key_Shift: 00404 // Don't beep for modifiers 00405 break; 00406 default: 00407 if (!e->state()) { // hm 00408 KNotifyClient::beep(); 00409 } 00410 } 00411 } 00412 00413 void 00414 KDateTable::viewportResizeEvent(QResizeEvent * e) 00415 { 00416 QGridView::viewportResizeEvent(e); 00417 00418 setCellWidth(viewport()->width()/7); 00419 setCellHeight(viewport()->height()/7); 00420 } 00421 00422 void 00423 KDateTable::setFontSize(int size) 00424 { 00425 int count; 00426 QFontMetrics metrics(fontMetrics()); 00427 QRect rect; 00428 // ----- store rectangles: 00429 fontsize=size; 00430 // ----- find largest day name: 00431 maxCell.setWidth(0); 00432 maxCell.setHeight(0); 00433 for(count=0; count<7; ++count) 00434 { 00435 rect=metrics.boundingRect(KGlobal::locale()->calendar() 00436 ->weekDayName(count+1, true)); 00437 maxCell.setWidth(QMAX(maxCell.width(), rect.width())); 00438 maxCell.setHeight(QMAX(maxCell.height(), rect.height())); 00439 } 00440 // ----- compare with a real wide number and add some space: 00441 rect=metrics.boundingRect(QString::fromLatin1("88")); 00442 maxCell.setWidth(QMAX(maxCell.width()+2, rect.width())); 00443 maxCell.setHeight(QMAX(maxCell.height()+4, rect.height())); 00444 } 00445 00446 void 00447 KDateTable::wheelEvent ( QWheelEvent * e ) 00448 { 00449 setDate(date.addMonths( -(int)(e->delta()/120)) ); 00450 e->accept(); 00451 } 00452 00453 void 00454 KDateTable::contentsMousePressEvent(QMouseEvent *e) 00455 { 00456 00457 if(e->type()!=QEvent::MouseButtonPress) 00458 { // the KDatePicker only reacts on mouse press events: 00459 return; 00460 } 00461 if(!isEnabled()) 00462 { 00463 KNotifyClient::beep(); 00464 return; 00465 } 00466 00467 // ----- 00468 int row, col, pos, temp; 00469 QPoint mouseCoord; 00470 // ----- 00471 mouseCoord = e->pos(); 00472 row=rowAt(mouseCoord.y()); 00473 col=columnAt(mouseCoord.x()); 00474 if(row<1 || col<0) 00475 { // the user clicked on the frame of the table 00476 return; 00477 } 00478 00479 // Rows and columns are zero indexed. The (row - 1) below is to avoid counting 00480 // the row with the days of the week in the calculation. 00481 00482 // old selected date: 00483 temp = posFromDate( date ); 00484 // new position and date 00485 pos = (7 * (row - 1)) + col; 00486 QDate clickedDate = dateFromPos( pos ); 00487 00488 // set the new date. If it is in the previous or next month, the month will 00489 // automatically be changed, no need to do that manually... 00490 setDate( clickedDate ); 00491 00492 // call updateCell on the old and new selection. If setDate switched to a different 00493 // month, these cells will be painted twice, but that's no problem. 00494 updateCell( temp/7+1, temp%7 ); 00495 updateCell( row, col ); 00496 00497 emit tableClicked(); 00498 00499 if ( e->button() == Qt::RightButton && d->popupMenuEnabled ) 00500 { 00501 KPopupMenu *menu = new KPopupMenu(); 00502 menu->insertTitle( KGlobal::locale()->formatDate(clickedDate) ); 00503 emit aboutToShowContextMenu( menu, clickedDate ); 00504 menu->popup(e->globalPos()); 00505 } 00506 } 00507 00508 bool 00509 KDateTable::setDate(const QDate& date_) 00510 { 00511 bool changed=false; 00512 QDate temp; 00513 // ----- 00514 if(!date_.isValid()) 00515 { 00516 kdDebug() << "KDateTable::setDate: refusing to set invalid date." << endl; 00517 return false; 00518 } 00519 if(date!=date_) 00520 { 00521 emit(dateChanged(date, date_)); 00522 date=date_; 00523 emit(dateChanged(date)); 00524 changed=true; 00525 } 00526 const KCalendarSystem * calendar = KGlobal::locale()->calendar(); 00527 00528 calendar->setYMD(temp, calendar->year(date), calendar->month(date), 1); 00529 //temp.setYMD(date.year(), date.month(), 1); 00530 //kdDebug() << "firstDayInWeek: " << temp.toString() << endl; 00531 firstday=temp.dayOfWeek(); 00532 numdays=calendar->daysInMonth(date); 00533 00534 temp = calendar->addMonths(temp, -1); 00535 numDaysPrevMonth=calendar->daysInMonth(temp); 00536 if(changed) 00537 { 00538 repaintContents(false); 00539 } 00540 return true; 00541 } 00542 00543 const QDate& 00544 KDateTable::getDate() const 00545 { 00546 return date; 00547 } 00548 00549 // what are those repaintContents() good for? (pfeiffer) 00550 void KDateTable::focusInEvent( QFocusEvent *e ) 00551 { 00552 // repaintContents(false); 00553 QGridView::focusInEvent( e ); 00554 } 00555 00556 void KDateTable::focusOutEvent( QFocusEvent *e ) 00557 { 00558 // repaintContents(false); 00559 QGridView::focusOutEvent( e ); 00560 } 00561 00562 QSize 00563 KDateTable::sizeHint() const 00564 { 00565 if(maxCell.height()>0 && maxCell.width()>0) 00566 { 00567 return QSize(maxCell.width()*numCols()+2*frameWidth(), 00568 (maxCell.height()+2)*numRows()+2*frameWidth()); 00569 } else { 00570 kdDebug() << "KDateTable::sizeHint: obscure failure - " << endl; 00571 return QSize(-1, -1); 00572 } 00573 } 00574 00575 void KDateTable::setPopupMenuEnabled( bool enable ) 00576 { 00577 d->popupMenuEnabled=enable; 00578 } 00579 00580 bool KDateTable::popupMenuEnabled() const 00581 { 00582 return d->popupMenuEnabled; 00583 } 00584 00585 void KDateTable::setCustomDatePainting(const QDate &date, const QColor &fgColor, BackgroundMode bgMode, const QColor &bgColor) 00586 { 00587 if (!fgColor.isValid()) 00588 { 00589 unsetCustomDatePainting( date ); 00590 return; 00591 } 00592 00593 KDateTablePrivate::DatePaintingMode *mode=new KDateTablePrivate::DatePaintingMode; 00594 mode->bgMode=bgMode; 00595 mode->fgColor=fgColor; 00596 mode->bgColor=bgColor; 00597 00598 d->customPaintingModes.replace( date.toString(), mode ); 00599 d->useCustomColors=true; 00600 update(); 00601 } 00602 00603 void KDateTable::unsetCustomDatePainting( const QDate &date ) 00604 { 00605 d->customPaintingModes.remove( date.toString() ); 00606 } 00607 00608 KDateInternalWeekSelector::KDateInternalWeekSelector 00609 (QWidget* parent, const char* name) 00610 : QLineEdit(parent, name), 00611 val(new QIntValidator(this)), 00612 result(0) 00613 { 00614 QFont font; 00615 // ----- 00616 font=KGlobalSettings::generalFont(); 00617 setFont(font); 00618 setFrameStyle(QFrame::NoFrame); 00619 setValidator(val); 00620 connect(this, SIGNAL(returnPressed()), SLOT(weekEnteredSlot())); 00621 } 00622 00623 void 00624 KDateInternalWeekSelector::weekEnteredSlot() 00625 { 00626 bool ok; 00627 int week; 00628 // ----- check if this is a valid week: 00629 week=text().toInt(&ok); 00630 if(!ok) 00631 { 00632 KNotifyClient::beep(); 00633 emit(closeMe(0)); 00634 return; 00635 } 00636 result=week; 00637 emit(closeMe(1)); 00638 } 00639 00640 int 00641 KDateInternalWeekSelector::getWeek() 00642 { 00643 return result; 00644 } 00645 00646 void 00647 KDateInternalWeekSelector::setWeek(int week) 00648 { 00649 QString temp; 00650 // ----- 00651 temp.setNum(week); 00652 setText(temp); 00653 } 00654 00655 void 00656 KDateInternalWeekSelector::setMaxWeek(int max) 00657 { 00658 val->setRange(1, max); 00659 } 00660 00661 // ### CFM To avoid binary incompatibility. 00662 // In future releases, remove this and replace by a QDate 00663 // private member, needed in KDateInternalMonthPicker::paintCell 00664 class KDateInternalMonthPicker::KDateInternalMonthPrivate { 00665 public: 00666 KDateInternalMonthPrivate (int y, int m, int d) 00667 : year(y), month(m), day(d) 00668 {} 00669 int year; 00670 int month; 00671 int day; 00672 }; 00673 00674 KDateInternalMonthPicker::~KDateInternalMonthPicker() { 00675 delete d; 00676 } 00677 00678 KDateInternalMonthPicker::KDateInternalMonthPicker 00679 (const QDate & date, QWidget* parent, const char* name) 00680 : QGridView(parent, name), 00681 result(0) // invalid 00682 { 00683 QRect rect; 00684 QFont font; 00685 // ----- 00686 activeCol = -1; 00687 activeRow = -1; 00688 font=KGlobalSettings::generalFont(); 00689 setFont(font); 00690 setHScrollBarMode(AlwaysOff); 00691 setVScrollBarMode(AlwaysOff); 00692 setFrameStyle(QFrame::NoFrame); 00693 setNumCols(3); 00694 d = new KDateInternalMonthPrivate(date.year(), date.month(), date.day()); 00695 // For monthsInYear != 12 00696 setNumRows( (KGlobal::locale()->calendar()->monthsInYear(date) + 2) / 3); 00697 // enable to find drawing failures: 00698 // setTableFlags(Tbl_clipCellPainting); 00699 viewport()->setEraseColor(KGlobalSettings::baseColor()); // for consistency with the datepicker 00700 // ----- find the preferred size 00701 // (this is slow, possibly, but unfortunately it is needed here): 00702 QFontMetrics metrics(font); 00703 for(int i = 1; ; ++i) 00704 { 00705 QString str = KGlobal::locale()->calendar()->monthName(i, 00706 KGlobal::locale()->calendar()->year(date), false); 00707 if (str.isNull()) break; 00708 rect=metrics.boundingRect(str); 00709 if(max.width()<rect.width()) max.setWidth(rect.width()); 00710 if(max.height()<rect.height()) max.setHeight(rect.height()); 00711 } 00712 } 00713 00714 QSize 00715 KDateInternalMonthPicker::sizeHint() const 00716 { 00717 return QSize((max.width()+6)*numCols()+2*frameWidth(), 00718 (max.height()+6)*numRows()+2*frameWidth()); 00719 } 00720 00721 int 00722 KDateInternalMonthPicker::getResult() const 00723 { 00724 return result; 00725 } 00726 00727 void 00728 KDateInternalMonthPicker::setupPainter(QPainter *p) 00729 { 00730 p->setPen(KGlobalSettings::textColor()); 00731 } 00732 00733 void 00734 KDateInternalMonthPicker::viewportResizeEvent(QResizeEvent*) 00735 { 00736 setCellWidth(width() / numCols()); 00737 setCellHeight(height() / numRows()); 00738 } 00739 00740 void 00741 KDateInternalMonthPicker::paintCell(QPainter* painter, int row, int col) 00742 { 00743 int index; 00744 QString text; 00745 // ----- find the number of the cell: 00746 index=3*row+col+1; 00747 text=KGlobal::locale()->calendar()->monthName(index, 00748 KGlobal::locale()->calendar()->year(QDate(d->year, d->month, 00749 d->day)), false); 00750 painter->drawText(0, 0, cellWidth(), cellHeight(), AlignCenter, text); 00751 if ( activeCol == col && activeRow == row ) 00752 painter->drawRect( 0, 0, cellWidth(), cellHeight() ); 00753 } 00754 00755 void 00756 KDateInternalMonthPicker::contentsMousePressEvent(QMouseEvent *e) 00757 { 00758 if(!isEnabled() || e->button() != LeftButton) 00759 { 00760 KNotifyClient::beep(); 00761 return; 00762 } 00763 // ----- 00764 int row, col; 00765 QPoint mouseCoord; 00766 // ----- 00767 mouseCoord = e->pos(); 00768 row=rowAt(mouseCoord.y()); 00769 col=columnAt(mouseCoord.x()); 00770 00771 if(row<0 || col<0) 00772 { // the user clicked on the frame of the table 00773 activeCol = -1; 00774 activeRow = -1; 00775 } else { 00776 activeCol = col; 00777 activeRow = row; 00778 updateCell( row, col /*, false */ ); 00779 } 00780 } 00781 00782 void 00783 KDateInternalMonthPicker::contentsMouseMoveEvent(QMouseEvent *e) 00784 { 00785 if (e->state() & LeftButton) 00786 { 00787 int row, col; 00788 QPoint mouseCoord; 00789 // ----- 00790 mouseCoord = e->pos(); 00791 row=rowAt(mouseCoord.y()); 00792 col=columnAt(mouseCoord.x()); 00793 int tmpRow = -1, tmpCol = -1; 00794 if(row<0 || col<0) 00795 { // the user clicked on the frame of the table 00796 if ( activeCol > -1 ) 00797 { 00798 tmpRow = activeRow; 00799 tmpCol = activeCol; 00800 } 00801 activeCol = -1; 00802 activeRow = -1; 00803 } else { 00804 bool differentCell = (activeRow != row || activeCol != col); 00805 if ( activeCol > -1 && differentCell) 00806 { 00807 tmpRow = activeRow; 00808 tmpCol = activeCol; 00809 } 00810 if ( differentCell) 00811 { 00812 activeRow = row; 00813 activeCol = col; 00814 updateCell( row, col /*, false */ ); // mark the new active cell 00815 } 00816 } 00817 if ( tmpRow > -1 ) // repaint the former active cell 00818 updateCell( tmpRow, tmpCol /*, true */ ); 00819 } 00820 } 00821 00822 void 00823 KDateInternalMonthPicker::contentsMouseReleaseEvent(QMouseEvent *e) 00824 { 00825 if(!isEnabled()) 00826 { 00827 return; 00828 } 00829 // ----- 00830 int row, col, pos; 00831 QPoint mouseCoord; 00832 // ----- 00833 mouseCoord = e->pos(); 00834 row=rowAt(mouseCoord.y()); 00835 col=columnAt(mouseCoord.x()); 00836 if(row<0 || col<0) 00837 { // the user clicked on the frame of the table 00838 emit(closeMe(0)); 00839 return; 00840 } 00841 00842 pos=3*row+col+1; 00843 result=pos; 00844 emit(closeMe(1)); 00845 } 00846 00847 00848 00849 KDateInternalYearSelector::KDateInternalYearSelector 00850 (QWidget* parent, const char* name) 00851 : QLineEdit(parent, name), 00852 val(new QIntValidator(this)), 00853 result(0) 00854 { 00855 QFont font; 00856 // ----- 00857 font=KGlobalSettings::generalFont(); 00858 setFont(font); 00859 setFrameStyle(QFrame::NoFrame); 00860 // we have to respect the limits of QDate here, I fear: 00861 val->setRange(0, 8000); 00862 setValidator(val); 00863 connect(this, SIGNAL(returnPressed()), SLOT(yearEnteredSlot())); 00864 } 00865 00866 void 00867 KDateInternalYearSelector::yearEnteredSlot() 00868 { 00869 bool ok; 00870 int year; 00871 QDate date; 00872 // ----- check if this is a valid year: 00873 year=text().toInt(&ok); 00874 if(!ok) 00875 { 00876 KNotifyClient::beep(); 00877 emit(closeMe(0)); 00878 return; 00879 } 00880 //date.setYMD(year, 1, 1); 00881 KGlobal::locale()->calendar()->setYMD(date, year, 1, 1); 00882 if(!date.isValid()) 00883 { 00884 KNotifyClient::beep(); 00885 emit(closeMe(0)); 00886 return; 00887 } 00888 result=year; 00889 emit(closeMe(1)); 00890 } 00891 00892 int 00893 KDateInternalYearSelector::getYear() 00894 { 00895 return result; 00896 } 00897 00898 void 00899 KDateInternalYearSelector::setYear(int year) 00900 { 00901 QString temp; 00902 // ----- 00903 temp.setNum(year); 00904 setText(temp); 00905 } 00906 00907 class KPopupFrame::KPopupFramePrivate 00908 { 00909 public: 00910 KPopupFramePrivate() : exec(false) {} 00911 00912 bool exec; 00913 }; 00914 00915 KPopupFrame::KPopupFrame(QWidget* parent, const char* name) 00916 : QFrame(parent, name, WType_Popup), 00917 result(0), // rejected 00918 main(0), 00919 d(new KPopupFramePrivate) 00920 { 00921 setFrameStyle(QFrame::Box|QFrame::Raised); 00922 setMidLineWidth(2); 00923 } 00924 00925 KPopupFrame::~KPopupFrame() 00926 { 00927 delete d; 00928 } 00929 00930 void 00931 KPopupFrame::keyPressEvent(QKeyEvent* e) 00932 { 00933 if(e->key()==Key_Escape) 00934 { 00935 result=0; // rejected 00936 d->exec = false; 00937 qApp->exit_loop(); 00938 } 00939 } 00940 00941 void 00942 KPopupFrame::close(int r) 00943 { 00944 result=r; 00945 d->exec = false; 00946 qApp->exit_loop(); 00947 } 00948 00949 void 00950 KPopupFrame::hide() 00951 { 00952 QFrame::hide(); 00953 if (d->exec) 00954 { 00955 d->exec = false; 00956 qApp->exit_loop(); 00957 } 00958 } 00959 00960 void 00961 KPopupFrame::setMainWidget(QWidget* m) 00962 { 00963 main=m; 00964 if(main) 00965 { 00966 resize(main->width()+2*frameWidth(), main->height()+2*frameWidth()); 00967 } 00968 } 00969 00970 void 00971 KPopupFrame::resizeEvent(QResizeEvent*) 00972 { 00973 if(main) 00974 { 00975 main->setGeometry(frameWidth(), frameWidth(), 00976 width()-2*frameWidth(), height()-2*frameWidth()); 00977 } 00978 } 00979 00980 void 00981 KPopupFrame::popup(const QPoint &pos) 00982 { 00983 // Make sure the whole popup is visible. 00984 QRect d = KGlobalSettings::desktopGeometry(pos); 00985 00986 int x = pos.x(); 00987 int y = pos.y(); 00988 int w = width(); 00989 int h = height(); 00990 if (x+w > d.x()+d.width()) 00991 x = d.width() - w; 00992 if (y+h > d.y()+d.height()) 00993 y = d.height() - h; 00994 if (x < d.x()) 00995 x = 0; 00996 if (y < d.y()) 00997 y = 0; 00998 00999 // Pop the thingy up. 01000 move(x, y); 01001 show(); 01002 } 01003 01004 int 01005 KPopupFrame::exec(QPoint pos) 01006 { 01007 popup(pos); 01008 repaint(); 01009 d->exec = true; 01010 qApp->enter_loop(); 01011 hide(); 01012 return result; 01013 } 01014 01015 int 01016 KPopupFrame::exec(int x, int y) 01017 { 01018 return exec(QPoint(x, y)); 01019 } 01020 01021 void KPopupFrame::virtual_hook( int, void* ) 01022 { /*BASE::virtual_hook( id, data );*/ } 01023 01024 void KDateTable::virtual_hook( int, void* ) 01025 { /*BASE::virtual_hook( id, data );*/ } 01026 01027 #include "kdatetbl.moc"