kplato

kptdatetable.cc

00001 /* This file is part of the KDE project
00002     Copyright (C) 1997 Tim D. Gilman (tdgilman@best.org)
00003               (C) 1998-2001 Mirko Boehm (mirko@kde.org)
00004               (C) 2004-2006 Dag Andersen <danders@get2net.dk>
00005 
00006    This library is free software; you can redistribute it and/or
00007    modify it under the terms of the GNU Library General Public
00008    License as published by the Free Software Foundation; either
00009    version 2 of the License, or (at your option) any later version.
00010 
00011    This library is distributed in the hope that it will be useful,
00012    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014    Library General Public License for more details.
00015 
00016    You should have received a copy of the GNU Library General Public License
00017    along with this library; see the file COPYING.LIB.  If not, write to
00018    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00019  * Boston, MA 02110-1301, USA.
00020 */
00021 
00022 #include "kptdatetable.h"
00023 #include "kptmap.h"
00024 
00025 #include <kapplication.h>
00026 #include <knotifyclient.h>
00027 #include <kcalendarsystem.h>
00028 
00029 #include <qdatetime.h>
00030 #include <qstring.h>
00031 #include <qpen.h>
00032 #include <qpainter.h>
00033 #include <qdialog.h>
00034 #include <assert.h>
00035 #include <qlayout.h>
00036 #include <qvaluelist.h>
00037 #include <kglobalsettings.h>
00038 
00039 #include <kdebug.h>
00040 
00041 namespace KPlato
00042 {
00043 
00044 DateValidator::DateValidator(QWidget* parent, const char* name)
00045     : QValidator(parent, name)
00046 {
00047 }
00048 
00049 QValidator::State
00050 DateValidator::validate(QString& text, int&) const
00051 {
00052   QDate temp;
00053   // ----- everything is tested in date():
00054   return date(text, temp);
00055 }
00056 
00057 QValidator::State
00058 DateValidator::date(const QString& text, QDate& d) const
00059 {
00060   QDate tmp = KGlobal::locale()->readDate(text);
00061   if (!tmp.isNull())
00062     {
00063       d = tmp;
00064       return Acceptable;
00065     } else
00066       return Valid;
00067 }
00068 
00069 void
00070 DateValidator::fixup( QString& ) const
00071 {
00072 
00073 }
00074 
00075 
00076 DateTable::DateTable(QWidget *parent, QDate date_, const char* name, WFlags f)
00077     : QGridView(parent, name, f),
00078       m_enabled(true)
00079 {
00080     //kdDebug()<<k_funcinfo<<endl;
00081     m_dateStartCol = 1;
00082     m_selectedDates.clear();
00083     m_selectedWeekdays.clear();
00084 
00085     QPair<int, int> p(0,0);
00086     m_weeks.fill(p, 7);
00087 
00088     setFontSize(10);
00089     if(!date_.isValid()) {
00090         kdError() <<k_funcinfo<<"Given date is invalid, using current date." << endl;
00091         date_=QDate::currentDate();
00092     }
00093     setFocusPolicy( QWidget::StrongFocus );
00094     setNumCols(7+m_dateStartCol); // 7 days a week + maybe 1 for weeknumbers
00095     setNumRows(7); // 6 weeks max + headline
00096 
00097     setHScrollBarMode(AlwaysOff);
00098     setVScrollBarMode(AlwaysOff);
00099     viewport()->setEraseColor(KGlobalSettings::baseColor());
00100     setDate(date_); // this initializes firstday, numdays, numDaysPrevMonth
00101 
00102     colorBackgroundHoliday = QColor(0, 245, 255, QColor::Hsv);
00103     //colorBackgroundHoliday = colorBackgroundHoliday.light();
00104     colorBackgroundWorkday = QColor(208, 230, 240, QColor::Hsv);;
00105     //colorBackgroundWorkday = colorBackgroundWorkday.light();
00106     colorTextHoliday = black;
00107     colorTextWorkday = black;
00108     colorLine = black;
00109     backgroundSelectColor = KGlobalSettings::highlightColor();
00110     penSelectColor=KGlobalSettings::baseColor();
00111 
00112 }
00113 
00114 void DateTable::paintWeekday(QPainter *painter, int col) {
00115     QRect rect;
00116     int w=cellWidth();
00117     int h=cellHeight();
00118 
00119     QFont font = KGlobalSettings::generalFont();
00120     font.setBold(true);
00121     if (!m_enabled)
00122         font.setItalic(true);
00123     painter->setFont(font);
00124 
00125     int day = weekday(col);
00126 
00127     //kdDebug()<<k_funcinfo<<" col="<<col<<" day="<<day<<" name="<<daystr<<endl;
00128 
00129     painter->setBrush(KGlobalSettings::baseColor());
00130     painter->setPen(KGlobalSettings::baseColor());
00131     painter->drawRect(0, 0, w, h);
00132     painter->setPen(KGlobalSettings::textColor());
00133 
00134     if (m_markedWeekdays.state(day) == Map::Working) {
00135         painter->setPen(colorBackgroundWorkday);
00136         painter->setBrush(colorBackgroundWorkday);
00137         painter->drawRect(0, 0, w, h);
00138         painter->setPen(colorTextWorkday);
00139     } else if (m_markedWeekdays.state(day) == Map::NonWorking) {
00140         painter->setPen(colorBackgroundHoliday);
00141         painter->setBrush(colorBackgroundHoliday);
00142         painter->drawRect(0, 0, w, h);
00143         painter->setPen(colorTextHoliday);
00144     }
00145     if (m_selectedWeekdays.contains(day)) {
00146         painter->setPen(backgroundSelectColor);
00147         painter->setBrush(backgroundSelectColor);
00148         painter->drawRect(2, 2, w-4, h-4);
00149         painter->setPen(penSelectColor);
00150     }
00151     painter->drawText(0, 0, w, h-1, AlignCenter, KGlobal::locale()->calendar()->weekDayName(day, true), -1, &rect);
00152     painter->setPen(colorLine);
00153     painter->moveTo(0, h-1);
00154     painter->lineTo(w-1, h-1);
00155 
00156     if(rect.width()>maxCell.width()) maxCell.setWidth(rect.width());
00157     if(rect.height()>maxCell.height()) maxCell.setHeight(rect.height());
00158 
00159     //kdDebug()<<k_funcinfo<<"headline: row,col=("<<row<<","<<col<<")"<<" day="<<daystr<<endl;
00160 }
00161 
00162 void DateTable::paintWeekNumber(QPainter *painter, int row) {
00163     QRect rect;
00164     int w=cellWidth();
00165     int h=cellHeight();
00166 
00167     QFont font=KGlobalSettings::generalFont();
00168     font.setBold(true);
00169     if (!m_enabled)
00170         font.setItalic(true);
00171     painter->setFont(font);
00172 
00173     painter->setBrush(KGlobalSettings::baseColor());
00174     painter->setPen(KGlobalSettings::baseColor());
00175     painter->drawRect(0, 0, w, h);
00176     painter->setPen(KGlobalSettings::textColor());
00177     
00178     painter->drawText(0, 0, w, h-1, AlignCenter, QString("%1").arg(m_weeks[row].first), -1, &rect);
00179     painter->setPen(colorLine);
00180     painter->moveTo(w-1, 0);
00181     painter->lineTo(w-1, h-1);
00182 
00183     if(rect.width()>maxCell.width()) maxCell.setWidth(rect.width());
00184     if(rect.height()>maxCell.height()) maxCell.setHeight(rect.height());
00185 }
00186 
00187 void DateTable::paintDay(QPainter *painter, int row, int col) {
00188     //kdDebug()<<k_funcinfo<<"row,col=("<<row<<","<<col<<")"<<" num col="<<numCols()<<endl;
00189     QRect rect;
00190     int w=cellWidth();
00191     int h=cellHeight();
00192 
00193     QFont font=KGlobalSettings::generalFont();
00194     font.setPointSize(fontsize);
00195     if (!m_enabled)
00196         font.setItalic(true);
00197     painter->setFont(font);
00198 
00199     QDate d = getDate(position(row, col));
00200 
00201     painter->setBrush(KGlobalSettings::baseColor());
00202     painter->setPen(KGlobalSettings::baseColor());
00203     painter->drawRect(0, 0, w, h);
00204 
00205     // First paint the dates background
00206     if (m_markedDates.state(d) == Map::NonWorking) {
00207         //kdDebug()<<k_funcinfo<<"Marked date: "<<d<<"  row,col=("<<row<<","<<col<<")=NonWorking"<<endl;
00208         painter->setPen(colorBackgroundHoliday);
00209         painter->setBrush(colorBackgroundHoliday);
00210         painter->drawRect(0, 0, w, h);
00211     } else if (m_markedDates.state(d) == Map::Working) {
00212         //kdDebug()<<k_funcinfo<<"Marked date: "<<d<<"  row,col=("<<row<<","<<col<<")=Working"<<endl;
00213         painter->setPen(colorBackgroundWorkday);
00214         painter->setBrush(colorBackgroundWorkday);
00215         painter->drawRect(0, 0, w, h);
00216     }
00217     if(m_selectedDates.contains(d)) {
00218         //kdDebug()<<k_funcinfo<<"Selected: "<<d<<" row,col=("<<row<<","<<col<<")"<<endl;
00219         painter->setPen(backgroundSelectColor);
00220         painter->setBrush(backgroundSelectColor);
00221         painter->drawRect(2, 2, w-4, h-4);
00222     }
00223     // If weeks or weekdays are selected/marked we draw lines around the date
00224     QPen pen = painter->pen();
00225     if (m_markedWeekdays.state(weekday(col)) == Map::Working) {
00226         //kdDebug()<<k_funcinfo<<"Marked weekday: row,dayCol=("<<row<<","<<dayCol<<")=Working"<<endl;
00227         pen.setColor(colorBackgroundWorkday);
00228         painter->setPen(pen);
00229         painter->moveTo(0, 0);
00230         painter->lineTo(0, h-1);
00231         painter->moveTo(w-1, 0);
00232         painter->lineTo(w-1, h-1);
00233     }
00234     // then paint square if current date
00235     if (d  == QDate::currentDate()) {
00236         painter->setPen(colorLine);
00237         painter->drawRect(1, 1, w-2, h-2);
00238     }
00239 
00240     // and now the day number
00241     d.month() == date.month() ? painter->setPen(KGlobalSettings::textColor()) : painter->setPen(gray);
00242     painter->drawText(0, 0, w, h, AlignCenter, QString().setNum(d.day()), -1, &rect);
00243 
00244     if(rect.width()>maxCell.width()) maxCell.setWidth(rect.width());
00245     if(rect.height()>maxCell.height()) maxCell.setHeight(rect.height());
00246 }
00247 
00248 void DateTable::paintCell(QPainter *painter, int row, int col) {
00249     //kdDebug()<<k_funcinfo<<"row,col=("<<row<<","<<col<<")"<<"enabled="<<m_enabled<<endl;
00250     if (row == 0 && col == 0) {
00251         painter->save();
00252         int w=cellWidth();
00253         int h=cellHeight();
00254         painter->setPen(colorLine);
00255         painter->setBrush(KGlobalSettings::baseColor());
00256         painter->moveTo(w-1, 0);
00257         painter->lineTo(w-1, h-1);
00258         painter->lineTo(0, h-1);
00259         painter->restore();
00260         return;
00261     }
00262     painter->save();
00263     if(row==0) { // we are drawing the weekdays
00264         paintWeekday(painter, col);
00265     } else if (col == 0) { // draw week numbers
00266         paintWeekNumber(painter, row);
00267     } else { // draw the day
00268         paintDay(painter, row, col);
00269     }
00270     painter->restore();
00271 }
00272 
00273 //FIXME
00274 void DateTable::keyPressEvent( QKeyEvent *e ) {
00275     if (!m_enabled)
00276         return;
00277     if ( e->key() == Qt::Key_Prior ) {
00278         setDate(date.addMonths(-1));
00279         return;
00280     }
00281     if ( e->key() == Qt::Key_Next ) {
00282         setDate(date.addMonths(1));
00283         return;
00284     }
00285 
00286     if ( e->key() == Qt::Key_Up ) {
00287         if ( date.day() > 7 ) {
00288             setDate(date.addDays(-7));
00289             return;
00290         }
00291     }
00292     if ( e->key() == Qt::Key_Down ) {
00293         if ( date.day() <= date.daysInMonth()-7 ) {
00294             setDate(date.addDays(7));
00295             return;
00296         }
00297     }
00298     if ( e->key() == Qt::Key_Left ) {
00299         if ( date.day() > 1 ) {
00300             setDate(date.addDays(-1));
00301             return;
00302         }
00303     }
00304     if ( e->key() == Qt::Key_Right ) {
00305         if ( date.day() < date.daysInMonth() ) {
00306             setDate(date.addDays(1));
00307             return;
00308         }
00309     }
00310 
00311     if ( e->key() == Qt::Key_Minus ) {
00312         setDate(date.addDays(-1));
00313         return;
00314     }
00315     if ( e->key() == Qt::Key_Plus ) {
00316         setDate(date.addDays(1));
00317         return;
00318     }
00319     if ( e->key() == Qt::Key_N ) {
00320         setDate(QDate::currentDate());
00321         return;
00322     }
00323     if ( e->key() == Qt::Key_Control ) {
00324         return;
00325     }
00326     if ( e->key() == Qt::Key_Shift ) {
00327         return;
00328     }
00329 
00330     KNotifyClient::beep();
00331 }
00332 
00333 void DateTable::viewportResizeEvent(QResizeEvent * e) {
00334   QGridView::viewportResizeEvent(e);
00335 
00336   setCellWidth(viewport()->width()/numCols());
00337   setCellHeight(viewport()->height()/numRows());
00338 }
00339 
00340 void DateTable::setFontSize(int size) {
00341   int count;
00342   QFontMetrics metrics(fontMetrics());
00343   QRect rect;
00344   // ----- store rectangles:
00345   fontsize=size;
00346   // ----- find largest day name:
00347   maxCell.setWidth(0);
00348   maxCell.setHeight(0);
00349   for(count=0; count<7; ++count)
00350     {
00351       rect=metrics.boundingRect(KGlobal::locale()->calendar()->weekDayName(count+1, true));
00352       maxCell.setWidth(QMAX(maxCell.width(), rect.width()));
00353       maxCell.setHeight(QMAX(maxCell.height(), rect.height()));
00354     }
00355   // ----- compare with a real wide number and add some space:
00356   rect=metrics.boundingRect(QString::fromLatin1("88"));
00357   maxCell.setWidth(QMAX(maxCell.width()+2, rect.width()));
00358   maxCell.setHeight(QMAX(maxCell.height()+4, rect.height()));
00359 }
00360 
00361 //FIXME
00362 void DateTable::wheelEvent ( QWheelEvent * e ) {
00363     setDate(date.addMonths( -(int)(e->delta()/120)) );
00364     e->accept();
00365 }
00366 
00367 
00368 void DateTable::contentsMousePressEvent(QMouseEvent *e) {
00369     if (!m_enabled)
00370         return;
00371     //kdDebug()<<k_funcinfo<<endl;
00372     if(e->type()!=QEvent::MouseButtonPress) {
00373         return;
00374     }
00375     QPoint mouseCoord = e->pos();
00376     int row=rowAt(mouseCoord.y());
00377     int col=columnAt(mouseCoord.x());
00378     if (row == 0 && col == 0) { // user clicked on (unused) upper left square
00379         updateSelectedCells();
00380         m_selectedWeekdays.clear();
00381         m_selectedDates.clear();
00382         repaintContents(false);
00383         emit selectionCleared();
00384         return;
00385     }
00386     if (col == 0) { // user clicked on week numbers
00387         updateSelectedCells();
00388         m_selectedWeekdays.clear();
00389         m_selectedDates.clear();
00390         updateSelectedCells();
00391         repaintContents(false);
00392         return;
00393     }
00394     if (row==0 && col>0) { // the user clicked on weekdays
00395         updateSelectedCells();
00396         m_selectedDates.clear();
00397         int day = weekday(col);
00398         if (e->state() & ShiftButton) {
00399             // select all days between this and the furthest away selected day,
00400             // check first downside - then upside, clear all others
00401             bool select = false;
00402             for(int i=m_dateStartCol; i < col; ++i) {
00403                 //kdDebug()<<"Down["<<i<<"]: col="<<col<<" day="<<day<<" column(i)="<<column(i)<<endl;
00404                 if (m_selectedWeekdays.contains(weekday(i))) {
00405                     select = true; // we have hit a selected day; select the rest
00406                 } else if (select) {
00407                     m_selectedWeekdays.toggle(weekday(i)); // select
00408                 }
00409             }
00410             bool selected = select;
00411             select = false;
00412             for(int i=7; i > col; --i) {
00413                 //kdDebug()<<"Up["<<i<<"]: col="<<col<<" day="<<day<<" column(i)="<<column(i)<<endl;
00414                 if (m_selectedWeekdays.contains(weekday(i))) {
00415                     if (selected) m_selectedWeekdays.toggle(weekday(i)); // deselect
00416                     else select = true;
00417                 } else if (select) {
00418                     m_selectedWeekdays.toggle(weekday(i)); // select
00419                 }
00420             }
00421             if (!m_selectedWeekdays.contains(day)) {
00422                 m_selectedWeekdays.toggle(day); // always select
00423             }
00424         } else if (e->state() & ControlButton) {
00425             // toggle select this date
00426             m_selectedWeekdays.toggle(day);
00427         } else {
00428             // toggle select this, clear all others
00429             m_selectedWeekdays.toggleClear(day);
00430         }
00431         updateSelectedCells();
00432         repaintContents(false);
00433         if (m_enabled) {
00434             //kdDebug()<<k_funcinfo<<"emit weekdaySelected("<<day<<")"<<endl;
00435             emit weekdaySelected(day); // day= 1..7
00436         }
00437         return;
00438     }
00439 
00440     if (contentsMousePressEvent_internal(e)) {
00441         // Date hit,
00442         m_selectedWeekdays.clear();
00443         if (e->state() & ShiftButton) {
00444             // find first&last date
00445             QDate first;
00446             QDate last;
00447             DateMap::ConstIterator it;
00448             for (it = m_selectedDates.constBegin(); it != m_selectedDates.constEnd(); ++it) {
00449                 //kdDebug()<<k_funcinfo<<it.key()<<endl;
00450                 QDate d = QDate::fromString(it.key(), Qt::ISODate);
00451                 if (!d.isValid())
00452                     continue;
00453                 if (!first.isValid() || first > d)
00454                     first = d;
00455                 if (!last.isValid() || last < d)
00456                     last = d;
00457             }
00458             // select between anchor and pressed date inclusive
00459             m_selectedDates.clear();
00460             if (first.isValid() && last.isValid()) {
00461                 QDate anchor = first < date ? first : last;
00462                 int i = anchor > date ? -1 : 1;
00463                 while (anchor != date) {
00464                     //kdDebug()<<k_funcinfo<<anchor.toString(Qt::ISODate)<<endl;
00465                     m_selectedDates.toggle(anchor);
00466                     anchor = anchor.addDays(i);
00467                 }
00468             }
00469             m_selectedDates.toggle(date);
00470         } else if (e->state() & ControlButton) {
00471             // toggle select this date
00472             m_selectedDates.toggle(date);
00473             //kdDebug()<<k_funcinfo<<"toggle date: "<<date.toString()<<" state="<<m_selectedDates.state(date)<<endl;
00474         } else {
00475             // Select this, clear all others
00476             m_selectedDates.clear();
00477             m_selectedDates.toggleClear(date);
00478             //kdDebug()<<k_funcinfo<<"toggleClear date: "<<date.toString()<<" state="<<m_selectedDates.state(date)<<endl;
00479         }
00480     }
00481     repaintContents(false);
00482 }
00483 
00484 bool DateTable::contentsMousePressEvent_internal(QMouseEvent *e) {
00485     QPoint mouseCoord = e->pos();
00486     int row=rowAt(mouseCoord.y());
00487     int col=columnAt(mouseCoord.x());
00488     if(row<1 || col<0) { // the user clicked on the frame of the table
00489         return false;
00490     }
00491     //kdDebug()<<k_funcinfo<<"pos["<<row<<","<<col<<"]="<<position(row,col)<<" firstday="<<firstday<<endl;
00492     selectDate(getDate(position(row, col)));
00493     return true;
00494 }
00495 
00496 bool DateTable::selectDate(const QDate& date_) {
00497     //kdDebug()<<k_funcinfo<<"date="<<date_.toString()<<endl;
00498     bool changed=false;
00499     QDate temp;
00500     // -----
00501     if(!date_.isValid()) {
00502         return false;
00503     }
00504     if(date!=date_) {
00505         date=date_;
00506         changed=true;
00507     }
00508 
00509     temp.setYMD(date.year(), date.month(), 1);
00510     firstday=column(KGlobal::locale()->calendar()->dayOfWeek(temp));
00511     if(firstday==1) firstday=8; // Reserve row 1 for previous month
00512     numdays=date.daysInMonth();
00513     if(date.month()==1) { // set to december of previous year
00514         temp.setYMD(date.year()-1, 12, 1);
00515         setWeekNumbers(QDate(date.year()-1, 12, 31));
00516     } else { // set to previous month
00517         temp.setYMD(date.year(), date.month()-1, 1);
00518         QDate d(date.year(), date.month()-1,1);
00519         setWeekNumbers(d.addDays(d.daysInMonth()-1));
00520     }
00521     numDaysPrevMonth=temp.daysInMonth();
00522     if(changed) {
00523         repaintContents(false);
00524     }
00525     if (m_enabled)
00526         emit(dateChanged(date));
00527     return true;
00528 }
00529 
00530 bool DateTable::setDate(const QDate& date_, bool repaint) {
00531     //kdDebug()<<k_funcinfo<<"date="<<date_.toString()<<endl;
00532     bool changed=false;
00533     QDate temp;
00534     // -----
00535     if(!date_.isValid()) {
00536         //kdDebug() << "DateTable::setDate: refusing to set invalid date." << endl;
00537         return false;
00538         }
00539     if(date!=date_) {
00540         date=date_;
00541         changed=true;
00542     }
00543     //m_selectedDates.clear();
00544 
00545     temp.setYMD(date.year(), date.month(), 1);
00546     firstday=column(KGlobal::locale()->calendar()->dayOfWeek(temp));
00547     if(firstday==1) firstday=8;
00548     //kdDebug()<<k_funcinfo<<"date="<<temp<<"day="<<(KGlobal::locale()->calendar()->dayOfWeek(temp))<<" firstday="<<firstday<<endl;
00549     numdays=date.daysInMonth();
00550     if(date.month()==1) { // set to december of previous year
00551         temp.setYMD(date.year()-1, 12, 1);
00552         setWeekNumbers(QDate(date.year()-1, 12, 31));
00553     } else { // set to previous month
00554         temp.setYMD(date.year(), date.month()-1, 1);
00555         QDate d(date.year(), date.month()-1,1);
00556         setWeekNumbers(d.addDays(d.daysInMonth()-1));
00557     }
00558 /*    if (m_selectedWeekdays.isEmpty() &&
00559         !m_selectedDates.isEmpty() && !m_selectedDates.contains(date))
00560     {
00561         //kdDebug()<<k_funcinfo<<"date inserted"<<endl;
00562         m_selectedDates.insert(date);
00563     }*/
00564     numDaysPrevMonth=temp.daysInMonth();
00565     if(changed && repaint) {
00566         repaintContents(false);
00567     }
00568     if (m_enabled)
00569       emit(dateChanged(date));
00570     return true;
00571 }
00572 
00573 const QDate& DateTable::getDate() const {
00574   return date;
00575 }
00576 
00577 void DateTable::focusInEvent( QFocusEvent *e ) {
00578     QGridView::focusInEvent( e );
00579 }
00580 
00581 void DateTable::focusOutEvent( QFocusEvent *e ) {
00582     QGridView::focusOutEvent( e );
00583 }
00584 
00585 QSize DateTable::sizeHint() const {
00586     if(maxCell.height()>0 && maxCell.width()>0) {
00587       return QSize(maxCell.width()*numCols()+2*frameWidth(),
00588              (maxCell.height()+2)*numRows()+2*frameWidth());
00589     } else {
00590       //kdDebug() << "DateTable::sizeHint: obscure failure - " << endl;
00591       return QSize(-1, -1);
00592     }
00593 }
00594 
00595 void DateTable::setWeekNumbers(QDate date) {
00596     if (!date.isValid()) {
00597         kdError()<<k_funcinfo<<"Invalid date"<<endl;
00598     }
00599     QDate d(date);
00600     for (int i = 1; i < 7; ++i) {
00601         m_weeks[i].first = d.weekNumber(&(m_weeks[i].second));
00602         //kdDebug()<<k_funcinfo<<"date="<<d.toString()<<" week=("<<m_weeks[i].first<<","<<m_weeks[i].second<<")"<<endl;
00603         d = d.addDays(7);
00604     }
00605 }
00606 
00607 void DateTable::updateCells() {
00608     //kdDebug()<<k_funcinfo<<endl;
00609     for (int row=0; row < numRows(); ++row) {
00610         for (int col=0; col < numCols(); ++col) {
00611             updateCell(row, col);
00612         }
00613     }
00614 }
00615 
00616 void DateTable::updateSelectedCells() {
00617     //kdDebug()<<k_funcinfo<<endl;
00618     QDate dt(date.year(), date.month(), 1);
00619     dt = dt.addDays(-firstday);
00620     for (int pos=0; pos < 42; ++pos) {
00621         if (m_selectedDates.contains(dt.addDays(pos)) ||
00622             m_selectedWeekdays.contains(pos%7+1))
00623         {
00624             updateCell(pos/7+1, pos%7+1);
00625             //kdDebug()<<k_funcinfo<<" update cell ("<<pos/7+1<<","<<pos%7+1<<") date="<<dt.addDays(pos).toString()<<endl;
00626         }
00627     }
00628 }
00629 
00630 void DateTable::updateMarkedCells() {
00631     QDate dt(date.year(), date.month(), 1);
00632     dt = dt.addDays(-firstday);
00633     for (int pos=0; pos < 42; ++pos) {
00634         if (m_markedDates.contains(dt.addDays(pos)) ||
00635             m_markedWeekdays.contains(pos%7+1))
00636         {
00637             updateCell(pos/7+1, pos%7+1);
00638             //kdDebug()<<k_funcinfo<<" update cell ("<<pos/7+1<<","<<pos%7+1<<") date="<<dt.addDays(pos).toString()<<endl;
00639         }
00640     }
00641 }
00642 
00643 void DateTable::setMarkedWeekdays(const IntMap days) {
00644     updateMarkedCells();
00645     m_markedWeekdays.clear();
00646     m_markedWeekdays = days;
00647     updateMarkedCells();
00648     repaintContents(false);
00649 }
00650 
00651 bool DateTable::weekdayMarked(int day) {
00652     return m_markedWeekdays.contains(day);
00653 }
00654 
00655 bool DateTable::dateMarked(QDate date) {
00656     return m_markedDates[date.toString()];
00657 }
00658 
00659 QDate DateTable::getDate(int pos) const {
00660     return QDate(date.year(), date.month(), 1).addDays(pos-firstday); 
00661 }
00662 
00663 int DateTable::weekday(int col) const {
00664     int day = col - m_dateStartCol + KGlobal::locale()->weekStartDay();
00665     if (day > 7) day %= 7;
00666     //kdDebug()<<k_funcinfo<<"col="<<col<<" day="<<day<<" StartCol="<<m_dateStartCol<<" weekStartDay="<<KGlobal::locale()->weekStartDay()<<endl;
00667     return day;
00668 }
00669 
00670 int DateTable::column(int weekday) const {
00671     int col = weekday - KGlobal::locale()->weekStartDay();
00672     if (col < 0) col += 7;
00673     //kdDebug()<<k_funcinfo<<"col="<<col<<" day="<<col<<" StartCol="<<m_dateStartCol<<" weekStartDay="<<KGlobal::locale()->weekStartDay()<<endl;
00674     return col + m_dateStartCol;
00675 }
00676 
00677 void DateTable::clear() {
00678     clearSelection();
00679     m_markedDates.clear();
00680     m_markedWeekdays.clear();
00681     repaintContents(false);
00682 }
00683 
00684 void DateTable::clearSelection() {
00685     m_selectedDates.clear();
00686     m_selectedWeekdays.clear();
00687     repaintContents(false);
00688 }
00689 
00690  void DateTable::setEnabled(bool yes) {
00691     if (m_enabled == yes)
00692         return;
00693     m_enabled=yes;
00694     updateCells();
00695 }
00696 
00697 void DateTable::markSelected(int state) {
00698     if (!m_selectedDates.isEmpty()) {
00699         DateMap::iterator it;
00700         for(it = m_selectedDates.begin(); it != m_selectedDates.end(); ++it) {
00701             m_markedDates.insert(it.key(), state);
00702             //kdDebug()<<k_funcinfo<<"marked date: "<<it.key()<<"="<<state<<endl;
00703         }
00704     } else if (!m_selectedWeekdays.isEmpty()) {
00705         IntMap::iterator it;
00706         for(it = m_selectedWeekdays.begin(); it != m_selectedWeekdays.end(); ++it) {
00707             m_markedWeekdays.insert(it.key(), state);
00708             //kdDebug()<<k_funcinfo<<"marked weekday: "<<it.key()<<"="<<state<<endl;
00709         }
00710     }
00711     updateSelectedCells();
00712     repaintContents(false);
00713 }
00714 
00715 DateInternalWeekSelector::DateInternalWeekSelector
00716 (int fontsize, QWidget* parent, const char* name)
00717   : QLineEdit(parent, name),
00718     val(new QIntValidator(this)),
00719     result(0)
00720 {
00721   QFont font;
00722   // -----
00723   font=KGlobalSettings::generalFont();
00724   font.setPointSize(fontsize);
00725   setFont(font);
00726   setFrameStyle(QFrame::NoFrame);
00727   val->setRange(1, 53);
00728   setValidator(val);
00729   connect(this, SIGNAL(returnPressed()), SLOT(weekEnteredSlot()));
00730 }
00731 
00732 void
00733 DateInternalWeekSelector::weekEnteredSlot()
00734 {
00735   bool ok;
00736   int week;
00737   // ----- check if this is a valid week:
00738   week=text().toInt(&ok);
00739   if(!ok)
00740     {
00741       KNotifyClient::beep();
00742       return;
00743     }
00744   result=week;
00745   emit(closeMe(1));
00746 }
00747 
00748 int
00749 DateInternalWeekSelector::getWeek() const
00750 {
00751   return result;
00752 }
00753 
00754 void
00755 DateInternalWeekSelector::setWeek(int week)
00756 {
00757   QString temp;
00758   // -----
00759   temp.setNum(week);
00760   setText(temp);
00761 }
00762 
00763 DateInternalMonthPicker::DateInternalMonthPicker
00764 (int fontsize, QWidget* parent, const char* name)
00765   : QGridView(parent, name),
00766     result(0) // invalid
00767 {
00768   QRect rect;
00769   QFont font;
00770   // -----
00771   activeCol = -1;
00772   activeRow = -1;
00773   font=KGlobalSettings::generalFont();
00774   font.setPointSize(fontsize);
00775   setFont(font);
00776   setHScrollBarMode(AlwaysOff);
00777   setVScrollBarMode(AlwaysOff);
00778   setFrameStyle(QFrame::NoFrame);
00779   setNumRows(4);
00780   setNumCols(3);
00781   // enable to find drawing failures:
00782   // setTableFlags(Tbl_clipCellPainting);
00783   viewport()->setEraseColor(KGlobalSettings::baseColor()); // for consistency with the datepicker
00784   // ----- find the preferred size
00785   //       (this is slow, possibly, but unfortunatly it is needed here):
00786   QFontMetrics metrics(font);
00787   for(int i=1; i <= 12; ++i)
00788     {
00789       rect=metrics.boundingRect(KGlobal::locale()->calendar()->monthName(i, false));
00790       if(max.width()<rect.width()) max.setWidth(rect.width());
00791       if(max.height()<rect.height()) max.setHeight(rect.height());
00792     }
00793 
00794 }
00795 
00796 QSize
00797 DateInternalMonthPicker::sizeHint() const
00798 {
00799   return QSize((max.width()+6)*numCols()+2*frameWidth(),
00800          (max.height()+6)*numRows()+2*frameWidth());
00801 }
00802 
00803 int
00804 DateInternalMonthPicker::getResult() const
00805 {
00806   return result;
00807 }
00808 
00809 void
00810 DateInternalMonthPicker::setupPainter(QPainter *p)
00811 {
00812   p->setPen(KGlobalSettings::textColor());
00813 }
00814 
00815 void
00816 DateInternalMonthPicker::viewportResizeEvent(QResizeEvent*)
00817 {
00818   setCellWidth(width()/3);
00819   setCellHeight(height()/4);
00820 }
00821 
00822 void
00823 DateInternalMonthPicker::paintCell(QPainter* painter, int row, int col)
00824 {
00825   int index;
00826   QString text;
00827   // ----- find the number of the cell:
00828   index=3*row+col+1;
00829   text=KGlobal::locale()->calendar()->monthName(index, false);
00830   painter->drawText(0, 0, cellWidth(), cellHeight(), AlignCenter, text);
00831   if ( activeCol == col && activeRow == row )
00832       painter->drawRect( 0, 0, cellWidth(), cellHeight() );
00833 }
00834 
00835 void
00836 DateInternalMonthPicker::contentsMousePressEvent(QMouseEvent *e)
00837 {
00838   if(!isEnabled() || e->button() != LeftButton)
00839     {
00840       KNotifyClient::beep();
00841       return;
00842     }
00843   // -----
00844   int row, col;
00845   QPoint mouseCoord;
00846   // -----
00847   mouseCoord = e->pos();
00848   row=rowAt(mouseCoord.y());
00849   col=columnAt(mouseCoord.x());
00850 
00851   if(row<0 || col<0)
00852     { // the user clicked on the frame of the table
00853       activeCol = -1;
00854       activeRow = -1;
00855     } else {
00856       activeCol = col;
00857       activeRow = row;
00858       updateCell( row, col /*, false */ );
00859   }
00860 }
00861 
00862 void
00863 DateInternalMonthPicker::contentsMouseMoveEvent(QMouseEvent *e)
00864 {
00865   if (e->state() & LeftButton)
00866     {
00867       int row, col;
00868       QPoint mouseCoord;
00869       // -----
00870       mouseCoord = e->pos();
00871       row=rowAt(mouseCoord.y());
00872       col=columnAt(mouseCoord.x());
00873       int tmpRow = -1, tmpCol = -1;
00874       if(row<0 || col<0)
00875         { // the user clicked on the frame of the table
00876           if ( activeCol > -1 )
00877             {
00878               tmpRow = activeRow;
00879               tmpCol = activeCol;
00880             }
00881           activeCol = -1;
00882           activeRow = -1;
00883         } else {
00884           bool differentCell = (activeRow != row || activeCol != col);
00885           if ( activeCol > -1 && differentCell)
00886             {
00887               tmpRow = activeRow;
00888               tmpCol = activeCol;
00889             }
00890           if ( differentCell)
00891             {
00892               activeRow = row;
00893               activeCol = col;
00894               updateCell( row, col /*, false */ ); // mark the new active cell
00895             }
00896         }
00897       if ( tmpRow > -1 ) // repaint the former active cell
00898           updateCell( tmpRow, tmpCol /*, true */ );
00899     }
00900 }
00901 
00902 void
00903 DateInternalMonthPicker::contentsMouseReleaseEvent(QMouseEvent *e)
00904 {
00905   if(!isEnabled())
00906     {
00907       return;
00908     }
00909   // -----
00910   int row, col, pos;
00911   QPoint mouseCoord;
00912   // -----
00913   mouseCoord = e->pos();
00914   row=rowAt(mouseCoord.y());
00915   col=columnAt(mouseCoord.x());
00916   if(row<0 || col<0)
00917     { // the user clicked on the frame of the table
00918       emit(closeMe(0));
00919     }
00920   pos=3*row+col+1;
00921   result=pos;
00922   emit(closeMe(1));
00923 }
00924 
00925 
00926 
00927 DateInternalYearSelector::DateInternalYearSelector
00928 (int fontsize, QWidget* parent, const char* name)
00929   : QLineEdit(parent, name),
00930     val(new QIntValidator(this)),
00931     result(0)
00932 {
00933   QFont font;
00934   // -----
00935   font=KGlobalSettings::generalFont();
00936   font.setPointSize(fontsize);
00937   setFont(font);
00938   setFrameStyle(QFrame::NoFrame);
00939   // we have to respect the limits of QDate here, I fear:
00940   val->setRange(0, 8000);
00941   setValidator(val);
00942   connect(this, SIGNAL(returnPressed()), SLOT(yearEnteredSlot()));
00943 }
00944 
00945 void
00946 DateInternalYearSelector::yearEnteredSlot()
00947 {
00948   bool ok;
00949   int year;
00950   QDate date;
00951   // ----- check if this is a valid year:
00952   year=text().toInt(&ok);
00953   if(!ok)
00954     {
00955       KNotifyClient::beep();
00956       return;
00957     }
00958   date.setYMD(year, 1, 1);
00959   if(!date.isValid())
00960     {
00961       KNotifyClient::beep();
00962       return;
00963     }
00964   result=year;
00965   emit(closeMe(1));
00966 }
00967 
00968 int
00969 DateInternalYearSelector::getYear() const
00970 {
00971   return result;
00972 }
00973 
00974 void
00975 DateInternalYearSelector::setYear(int year)
00976 {
00977   QString temp;
00978   // -----
00979   temp.setNum(year);
00980   setText(temp);
00981 }
00982 
00983 PopupFrame::PopupFrame(QWidget* parent, const char*  name)
00984   : QFrame(parent, name, WType_Popup),
00985     result(0), // rejected
00986     main(0)
00987 {
00988   setFrameStyle(QFrame::Box|QFrame::Raised);
00989   setMidLineWidth(2);
00990 }
00991 
00992 void
00993 PopupFrame::keyPressEvent(QKeyEvent* e)
00994 {
00995   if(e->key()==Key_Escape)
00996     {
00997       result=0; // rejected
00998       qApp->exit_loop();
00999     }
01000 }
01001 
01002 void
01003 PopupFrame::close(int r)
01004 {
01005   result=r;
01006   qApp->exit_loop();
01007 }
01008 
01009 void
01010 PopupFrame::setMainWidget(QWidget* m)
01011 {
01012   main=m;
01013   if(main!=0)
01014     {
01015       resize(main->width()+2*frameWidth(), main->height()+2*frameWidth());
01016     }
01017 }
01018 
01019 void
01020 PopupFrame::resizeEvent(QResizeEvent*)
01021 {
01022   if(main!=0)
01023     {
01024       main->setGeometry(frameWidth(), frameWidth(),
01025           width()-2*frameWidth(), height()-2*frameWidth());
01026     }
01027 }
01028 
01029 void
01030 PopupFrame::popup(const QPoint &pos)
01031 {
01032   // Make sure the whole popup is visible.
01033   QRect d = QApplication::desktop()->screenGeometry(QApplication::desktop()->screenNumber(pos));
01034   int x = pos.x();
01035   int y = pos.y();
01036   int w = width();
01037   int h = height();
01038   if (x+w > d.x()+d.width())
01039     x = d.width() - w;
01040   if (y+h > d.y()+d.height())
01041     y = d.height() - h;
01042   if (x < d.x())
01043     x = 0;
01044   if (y < d.y())
01045     y = 0;
01046 
01047   // Pop the thingy up.
01048   move(x, y);
01049   show();
01050 }
01051 
01052 int
01053 PopupFrame::exec(QPoint pos)
01054 {
01055   popup(pos);
01056   repaint();
01057   qApp->enter_loop();
01058   hide();
01059   return result;
01060 }
01061 
01062 int
01063 PopupFrame::exec(int x, int y)
01064 {
01065   return exec(QPoint(x, y));
01066 }
01067 
01068 void PopupFrame::virtual_hook( int, void* )
01069 { /*BASE::virtual_hook( id, data );*/ }
01070 
01071 void DateTable::virtual_hook( int, void* )
01072 { /*BASE::virtual_hook( id, data );*/ }
01073 
01074 }  //KPlato namespace
01075 
01076 #include "kptdatetable.moc"
KDE Home | KDE Accessibility Home | Description of Access Keys