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