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"
KDE Home | KDE Accessibility Home | Description of Access Keys