korganizer Library API Documentation

kdatenavigator.cpp

00001 /*
00002     This file is part of KOrganizer.
00003     Copyright (c) 2001,2002 Cornelius Schumacher <schumacher@kde.org>
00004 
00005     This program is free software; you can redistribute it and/or modify
00006     it under the terms of the GNU General Public License as published by
00007     the Free Software Foundation; either version 2 of the License, or
00008     (at your option) any later version.
00009 
00010     This program 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
00013     GNU General Public License for more details.
00014 
00015     You should have received a copy of the GNU General Public License
00016     along with this program; if not, write to the Free Software
00017     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00018 
00019     As a special exception, permission is given to link this program
00020     with any edition of Qt, and distribute the resulting executable,
00021     without including the source code for Qt in the source distribution.
00022 */
00023 
00024 #include <qstring.h>
00025 #include <qtooltip.h>
00026 #include <qkeycode.h>
00027 #include <qpushbutton.h>
00028 #include <qlayout.h>
00029 #include <qtimer.h>
00030 
00031 #include <kdebug.h>
00032 #include <klocale.h>
00033 #include <kglobal.h>
00034 #include <kiconloader.h>
00035 
00036 #include "koprefs.h"
00037 #ifndef KORG_NOPLUGINS
00038 #include "kocore.h"
00039 #endif
00040 
00041 #include <calendarsystem/kcalendarsystem.h>
00042 
00043 #include "kdatenavigator.h"
00044 #include "kdatenavigator.moc"
00045 
00046 KDateNavigator::KDateNavigator( QWidget *parent, Calendar *calendar,
00047                                 bool show_week_nums, const char *name,
00048                                 QDate startDate )
00049   : QFrame(parent, name),
00050     updateTimer(0L)
00051 {
00052   mCalendar = calendar;
00053 
00054   setFrameStyle(QFrame::NoFrame);
00055 
00056   QGridLayout *topLayout = new QGridLayout(this,8,8);
00057 
00058   if (! startDate.isValid()) {
00059     kdDebug() << "KDateNavigator::KDateNavigator(): an invalid date was passed as a parameter!" << endl;
00060     startDate = QDate::currentDate();
00061   }
00062 
00063   mSelectedDates.append(startDate);
00064   m_MthYr = startDate;
00065   m_bShowWeekNums = show_week_nums;
00066 
00067   // Set up the control buttons and date label
00068   ctrlFrame = new QFrame(this, "KDateNavigator::CtrlFrame");
00069   ctrlFrame->setFrameStyle(QFrame::Panel|QFrame::Raised);
00070   ctrlFrame->setLineWidth(1);
00071 
00072   topLayout->addMultiCellWidget(ctrlFrame,0,0,0,7);
00073 
00074   QFont tfont = font();
00075   tfont.setPointSize(10);
00076   tfont.setBold(FALSE);
00077 
00078   bool isRTL = QApplication::reverseLayout();
00079 
00080   // Create backward navigation buttons
00081   prevYear = new QPushButton(ctrlFrame);
00082   prevYear->setPixmap(SmallIcon(isRTL ? "2rightarrow" : "2leftarrow"));
00083   QToolTip::add(prevYear, i18n("Previous Year"));
00084 
00085   prevMonth = new QPushButton(ctrlFrame);
00086   prevMonth->setPixmap(SmallIcon(isRTL ? "1rightarrow" : "1leftarrow"));
00087   QToolTip::add(prevMonth, i18n("Previous Month"));
00088 
00089   // Create forward navigation buttons
00090   nextMonth = new QPushButton(ctrlFrame);
00091   nextMonth->setPixmap(SmallIcon(isRTL ? "1leftarrow" : "1rightarrow"));
00092   QToolTip::add(nextMonth, i18n("Next Month"));
00093 
00094   nextYear = new QPushButton(ctrlFrame);
00095   nextYear->setPixmap(SmallIcon(isRTL ? "2leftarrow" : "2rightarrow"));
00096   QToolTip::add(nextYear, i18n("Next Year"));
00097 
00098   // Create month name label
00099   dateLabel = new QLabel(ctrlFrame);
00100   dateLabel->setFont(tfont);
00101   dateLabel->setAlignment(AlignCenter);
00102 
00103   // Set minimum width to width of widest month name label
00104   int i;
00105   int maxwidth = 0;
00106   QFontMetrics fm = dateLabel->fontMetrics();
00107 
00108   for(i=1;i<=12;++i) {
00109     int width = fm.width( KOCore::self()->calendarSystem()->monthName(i) + " 2000" );
00110     if (width > maxwidth) maxwidth = width;
00111   }
00112   dateLabel->setMinimumWidth(maxwidth);
00113 
00114   // set up control frame layout
00115   QBoxLayout *ctrlLayout = new QHBoxLayout(ctrlFrame,1);
00116   ctrlLayout->addWidget(prevYear,3);
00117   ctrlLayout->addWidget(prevMonth,3);
00118   ctrlLayout->addStretch(1);
00119   ctrlLayout->addSpacing(2);
00120   ctrlLayout->addWidget(dateLabel);
00121   ctrlLayout->addSpacing(2);
00122   ctrlLayout->addStretch(1);
00123   ctrlLayout->addWidget(nextMonth,3);
00124   ctrlLayout->addWidget(nextYear,3);
00125 
00126   connect( prevYear, SIGNAL( clicked() ), SIGNAL( goPrevYear() ) );
00127   connect( prevMonth, SIGNAL( clicked() ), SIGNAL( goPrevMonth() ) );
00128   connect( nextMonth, SIGNAL( clicked() ), SIGNAL( goNextMonth() ) );
00129   connect( nextYear, SIGNAL( clicked() ), SIGNAL( goNextYear() ) );
00130 
00131   // get the day of the week on the first day
00132   QDate dayone(m_MthYr.year(), m_MthYr.month(), 1);
00133   m_fstDayOfWk = dayone.dayOfWeek();
00134 
00135   // Set up the heading fields.
00136   for(i=0; i<7; i++) {
00137     headings[i] = new QLabel("",this);
00138     headings[i]->setFont(QFont("Arial", 10, QFont::Bold));
00139     headings[i]->setAlignment(AlignCenter);
00140 
00141     topLayout->addWidget(headings[i],1,i+1);
00142   }
00143 
00144   // Create the weeknumber labels
00145   for(i=0; i<6; i++) {
00146     weeknos[i] = new QLabel(this);
00147     weeknos[i]->setAlignment(AlignCenter);
00148     weeknos[i]->setFont(QFont("Arial", 10));
00149     if(!show_week_nums) {
00150       weeknos[i]->hide();
00151     }
00152     weeknos[i]->installEventFilter(this);
00153 
00154     topLayout->addWidget(weeknos[i],i+2,0);
00155   }
00156 
00157   daymatrix = new KODayMatrix( this, mCalendar, dayone,
00158                                "KDateNavigator::DayMatrix");
00159   daymatrix->setFrameStyle(QFrame::Panel|QFrame::Sunken);
00160   daymatrix->setLineWidth(1);
00161 
00162   connect( daymatrix, SIGNAL( selected( const KCal::DateList & ) ),
00163            SIGNAL( datesSelected( const KCal::DateList & ) ) );
00164 
00165   connect( daymatrix, SIGNAL( eventDropped( Event * ) ),
00166            SIGNAL( eventDropped( Event * ) ) );
00167 
00168   topLayout->addMultiCellWidget(daymatrix,2,7,1,7);
00169 
00170   // read settings from configuration file.
00171   updateConfig();
00172   enableRollover(FollowMonth);
00173 }
00174 
00175 void KDateNavigator::enableRollover(RolloverType r)
00176 {
00177   switch(r)
00178   {
00179   case None :
00180     if (updateTimer)
00181     {
00182       updateTimer->stop();
00183       delete updateTimer;
00184       updateTimer=0L;
00185     }
00186     break;
00187   case FollowDay :
00188   case FollowMonth :
00189     if (!updateTimer)
00190     {
00191       updateTimer = new QTimer(this);
00192       QObject::connect(updateTimer,SIGNAL(timeout()),
00193         this,SLOT(possiblyPastMidnight()));
00194     }
00195     updateTimer->start(0,true);
00196     lastDayChecked = QDate::currentDate();
00197   }
00198   updateRollover=r;
00199 }
00200 
00201 
00202 KDateNavigator::~KDateNavigator()
00203 {
00204 }
00205 
00206 
00207 void KDateNavigator::passedMidnight()
00208 {
00209     QDate today = QDate::currentDate();
00210     bool emitMonth = false;
00211 
00212     if (today.month() != lastDayChecked.month())
00213     {
00214        if (updateRollover==FollowMonth &&
00215            daymatrix->isEndOfMonth()) {
00216          goNextMonth();
00217          emitMonth=true;
00218        }
00219     }
00220     daymatrix->recalculateToday();
00221     daymatrix->repaint();
00222     emit dayPassed(today);
00223     if (emitMonth) { emit monthPassed(today); }
00224 }
00225 
00226 /* slot */ void KDateNavigator::possiblyPastMidnight()
00227 {
00228   if (lastDayChecked!=QDate::currentDate())
00229   {
00230     passedMidnight();
00231     lastDayChecked=QDate::currentDate();
00232   }
00233   // Set the timer to go off 1 second after midnight
00234   // or after 8 minutes, whichever comes first.
00235   if (updateTimer)
00236   {
00237     QTime now = QTime::currentTime();
00238     QTime midnight = QTime(23,59,59);
00239     int msecsWait = QMIN(480000,now.msecsTo(midnight)+2000);
00240 
00241     // qDebug(QString("Waiting %1 msec from %2 to %3.").arg(msecsWait)
00242     //  .arg(now.toString()).arg(midnight.toString()));
00243 
00244     updateTimer->stop();
00245     updateTimer->start(msecsWait,true);
00246   }
00247 }
00248 
00249 void KDateNavigator::updateDates()
00250 {
00251   // Find the first day of the week of the current month.
00252   //int d1 = KOCore::self()->calendarSystem()->day( m_MthYr );
00253   QDate dayone( m_MthYr.year(), m_MthYr.month(), m_MthYr.day() );
00254   int d2 = KOCore::self()->calendarSystem()->day( dayone );
00255   //int di = d1 - d2 + 1;
00256   dayone = dayone.addDays( -d2 + 1 );
00257 
00258   int m_fstDayOfWkCalsys = KOCore::self()->calendarSystem()->dayOfTheWeek( dayone );
00259 
00260   // If month begins on Monday and Monday is first day of week,
00261   // month should begin on second line. Sunday doesn't have this problem.
00262   int nextLine = ( ( m_fstDayOfWkCalsys == 1) &&
00263                    ( KGlobal::locale()->weekStartsMonday() == 1 ) ) ? 7 : 0;
00264 
00265   // update the matrix dates
00266   int index = (KGlobal::locale()->weekStartsMonday() ? 1 : 0) - m_fstDayOfWkCalsys - nextLine;
00267 
00268 
00269   daymatrix->updateView(dayone.addDays(index));
00270 //each updateDates is followed by an updateView -> repaint is issued there !
00271 //  daymatrix->repaint();
00272 }
00273 
00274 void KDateNavigator::updateDayMatrix()
00275 {
00276   daymatrix->updateView();
00277   daymatrix->repaint();
00278 }
00279 
00280 
00281 void KDateNavigator::updateView()
00282 {
00283   setUpdatesEnabled( false );
00284 
00285   // compute the label at the top of the navigator
00286   QDate cT( m_MthYr.year(), m_MthYr.month(), m_MthYr.day() );
00287   QString dtstr = KOCore::self()->calendarSystem()->monthName( cT ) + " " +
00288                   QString::number(KOCore::self()->calendarSystem()->year( cT ) );
00289   dateLabel->setText(dtstr);
00290 
00291   int i;
00292 
00293 //  kdDebug() << "updateView() -> daymatrix->updateView()" << endl;
00294   daymatrix->updateView();
00295 
00296   // set the week numbers.
00297   for(i = 0; i < 6; i++) {
00298     QString weeknum;
00299     // remember, according to ISO 8601, the first week of the year is the
00300     // first week that contains a thursday.  Thus we must subtract off 4,
00301     // not just 1.
00302 
00303     //ET int dayOfYear = buttons[(i + 1) * 7 - 4]->date().dayOfYear();
00304     int dayOfYear = KOCore::self()->calendarSystem()->numberOfDayInYear((daymatrix->getDate((i+1)*7-4)));
00305 
00306     if (dayOfYear % 7 != 0)
00307       weeknum.setNum(dayOfYear / 7 + 1);
00308     else
00309       weeknum.setNum(dayOfYear / 7);
00310     weeknos[i]->setText(weeknum);
00311   }
00312 
00313   setUpdatesEnabled( true );
00314 //  kdDebug() << "updateView() -> repaint()" << endl;
00315   repaint();
00316   daymatrix->repaint();
00317 }
00318 
00319 void KDateNavigator::updateConfig()
00320 {
00321   int day;
00322   for(int i=0; i<7; i++) {
00323     // take the first letter of the day name to be the abbreviation
00324     if (KGlobal::locale()->weekStartsMonday()) {
00325       day = i+1;
00326     } else {
00327       if (i==0) day = 7;
00328       else day = i;
00329     }
00330     headings[i]->setText( KOCore::self()->calendarSystem()->weekDayName(day, true) );
00331   }
00332   kdDebug() << "updateConfig() -> updateDates()" << endl;
00333   updateDates();
00334 
00335   kdDebug() << "updateConfig() -> updateView()" << endl;
00336   updateView();
00337 }
00338 
00339 void KDateNavigator::setShowWeekNums(bool enabled)
00340 {
00341   m_bShowWeekNums = enabled;
00342   for(int i=0; i<6; i++) {
00343     if(enabled)
00344       weeknos[i]->show();
00345     else
00346       weeknos[i]->hide();
00347   }
00348   resize(size());
00349 }
00350 
00351 void KDateNavigator::selectDates(const DateList& dateList)
00352 {
00353   if (dateList.count() > 0) {
00354     mSelectedDates = dateList;
00355 
00356     // set our record of the month and year that this datetbl is
00357     // displaying.
00358     m_MthYr = mSelectedDates.first();
00359 
00360     // set our record of the first day of the week of the current
00361     // month. This needs to be done before calling dayToIndex, since it
00362     // relies on this information being up to date.
00363     QDate dayone(m_MthYr.year(), m_MthYr.month(), 1);
00364     m_fstDayOfWk = dayone.dayOfWeek();
00365 
00366     updateDates();
00367 
00368     daymatrix->setSelectedDaysFrom(*(dateList.begin()), *(--dateList.end()));
00369 
00370     updateView();
00371   }
00372 }
00373 
00374 int KDateNavigator::dayNum(int row, int col)
00375 {
00376   return 7 * (row - 1) + (col + 1) - m_fstDayOfWk;
00377 }
00378 
00379 int KDateNavigator::dayToIndex(int dayNum)
00380 {
00381   int row, col;
00382 
00383   row = (dayNum+m_fstDayOfWk-1-(KGlobal::locale()->weekStartsMonday() ? 1 : 0)) / 7;
00384   if (KGlobal::locale()->weekStartsMonday() && (m_fstDayOfWk == 1))
00385     row++;
00386   col = (dayNum+m_fstDayOfWk-1-(KGlobal::locale()->weekStartsMonday() ? 1 : 0)) % 7;
00387   return row * 7 + col;
00388 }
00389 
00390 void KDateNavigator::wheelEvent (QWheelEvent *e)
00391 {
00392   if(e->delta()>0) emit goPrevious();
00393   else emit goNext();
00394 
00395   e->accept();
00396 }
00397 
00398 bool KDateNavigator::eventFilter (QObject *o,QEvent *e)
00399 {
00400   if (e->type() == QEvent::MouseButtonPress) {
00401     int i;
00402     for(i=0;i<6;++i) {
00403       if (o == weeknos[i]) {
00404         QDate weekstart = daymatrix->getDate(i*7);
00405         emit weekClicked(weekstart);
00406         break;
00407       }
00408     }
00409     return true;
00410   } else {
00411     return false;
00412   }
00413 }
KDE Logo
This file is part of the documentation for kdelibs Version 3.1.4.
Documentation copyright © 1996-2002 the KDE developers.
Generated on Sat Oct 18 02:47:30 2003 by doxygen 1.3.4 written by Dimitri van Heesch, © 1997-2001