Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

repeatentry.cpp

Go to the documentation of this file.
00001 /*
00002                              This file is part of the Opie Project
00003 
00004                              Copyright (C) Opie Team <opie-devel@handhelds.org>
00005               =.
00006             .=l.
00007            .>+-=
00008  _;:,     .>    :=|.         This program is free software; you can
00009 .> <`_,   >  .   <=          redistribute it and/or  modify it under
00010 :`=1 )Y*s>-.--   :           the terms of the GNU Library General Public
00011 .="- .-=="i,     .._         License as published by the Free Software
00012  - .   .-<_>     .<>         Foundation; either version 2 of the License,
00013      ._= =}       :          or (at your option) any later version.
00014     .%`+i>       _;_.
00015     .i_,=:_.      -<s.       This program is distributed in the hope that
00016      +  .  -:.       =       it will be useful,  but WITHOUT ANY WARRANTY;
00017     : ..    .:,     . . .    without even the implied warranty of
00018     =_        +     =;=|`    MERCHANTABILITY or FITNESS FOR A
00019   _.=:.       :    :=>`:     PARTICULAR PURPOSE. See the GNU
00020 ..}^=.=       =       ;      Library General Public License for more
00021 ++=   -.     .`     .:       details.
00022 :     =  ...= . :.=-
00023  -.   .:....=;==+<;          You should have received a copy of the GNU
00024   -_. . .   )=.  =           Library General Public License along with
00025     --        :-=`           this library; see the file COPYING.LIB.
00026                              If not, write to the Free Software Foundation,
00027                              Inc., 59 Temple Place - Suite 330,
00028                              Boston, MA 02111-1307, USA.
00029 */
00030 
00031 #include "repeatentry.h"
00032 
00033 #include <qpe/datebookmonth.h>
00034 #include <qpe/qpeapplication.h>
00035 
00036 #include <qlabel.h>
00037 #include <qspinbox.h>
00038 
00039 #include <time.h>
00040 
00041 // Global Templates for use in setting up the repeat label...
00042 // the problem is these strings get initialized before QPEApplication can install the translator -zecke
00043 namespace {
00044 QString strDayTemplate;
00045 QString strYearTemplate;
00046 QString strMonthDateTemplate;
00047 QString strMonthDayTemplate;
00048 QString strWeekTemplate;
00049 QString dayLabel[7];
00050 }
00051 
00052 /*
00053  * static linkage to not polute the symbol table...
00054  * The problem is that const and static linkage are resolved prior to installing a translator
00055  * leading to that the above strings are translted but to the original we delay the init of these strings...
00056  * -zecke
00057  */
00058 static void fillStrings() {
00059     strDayTemplate = QObject::tr("Every");
00060     strYearTemplate = QObject::tr("%1 %2 every ");
00061     strMonthDateTemplate = QObject::tr("The %1 every ");
00062     strMonthDayTemplate = QObject::tr("The %1 %1 of every");
00063     strWeekTemplate = QObject::tr("Every ");
00064     dayLabel[0] = QObject::tr("Monday");
00065     dayLabel[1] = QObject::tr("Tuesday");
00066     dayLabel[2] = QObject::tr("Wednesday");
00067     dayLabel[3] = QObject::tr("Thursday");
00068     dayLabel[4] = QObject::tr("Friday");
00069     dayLabel[5] = QObject::tr("Saturday");
00070     dayLabel[6] = QObject::tr("Sunday");
00071 }
00072 
00073 static QString numberPlacing( int x );  // return the proper word format for
00074                                         // x (1st, 2nd, etc)
00075 static int week( const QDate &dt );    // what week in the month is dt?
00076 
00077 RepeatEntry::RepeatEntry( bool startOnMonday,
00078                           const QDate &newStart, QWidget *parent,
00079                           const char *name, bool modal, WFlags fl )
00080     : RepeatEntryBase( parent, name, modal, fl ),
00081       start( newStart ),
00082       currInterval( NONE ),
00083       startWeekOnMonday( startOnMonday )
00084 {
00085     if (strDayTemplate.isEmpty() )
00086         fillStrings();
00087 
00088     init();
00089     fraType->setButton( currInterval );
00090     chkNoEnd->setChecked( TRUE );
00091     setupNone();
00092 }
00093 
00094 RepeatEntry::RepeatEntry( bool startOnMonday, const Event::RepeatPattern &rp,
00095                           const QDate &startDate,
00096                           QWidget *parent, const char *name, bool modal,
00097                           WFlags fl )
00098     : RepeatEntryBase( parent, name, modal, fl ),
00099       start( startDate ),
00100       end( rp.endDate() ),
00101       startWeekOnMonday( startOnMonday )
00102 {
00103     if (strDayTemplate.isEmpty() )
00104         fillStrings();
00105     // do some stuff with the repeat pattern
00106     init();
00107     switch ( rp.type ) {
00108         default:
00109         case Event::NoRepeat:
00110             currInterval = NONE;
00111             setupNone();
00112             break;
00113         case Event::Daily:
00114             currInterval = DAY;
00115             setupDaily();
00116             break;
00117         case Event::Weekly:
00118             currInterval = WEEK;
00119             setupWeekly();
00120             int day, buttons;
00121             for ( day = 0x01, buttons = 0; buttons < 7;
00122                   day = day << 1, buttons++ ) {
00123                 if ( rp.days & day ) {
00124                     if ( startWeekOnMonday )
00125                         fraExtra->setButton( buttons );
00126                     else {
00127                         if ( buttons == 7 )
00128                             fraExtra->setButton( 0 );
00129                         else
00130                             fraExtra->setButton( buttons + 1 );
00131                     }
00132                 }
00133             }
00134             slotWeekLabel();
00135             break;
00136         case Event::MonthlyDay:
00137             currInterval = MONTH;
00138             setupMonthly();
00139             fraExtra->setButton( 0 );
00140             slotMonthLabel( 0 );
00141             break;
00142         case Event::MonthlyDate:
00143             currInterval = MONTH;
00144             setupMonthly();
00145             fraExtra->setButton( 1 );
00146             slotMonthLabel( 1 );
00147             break;
00148         case Event::Yearly:
00149             currInterval = YEAR;
00150             setupYearly();
00151             break;
00152     }
00153     fraType->setButton( currInterval );
00154     spinFreq->setValue( rp.frequency );
00155     if ( !rp.hasEndDate ) {
00156         cmdEnd->setText( RepeatEntryBase::tr("No End Date") );
00157         chkNoEnd->setChecked( TRUE );
00158     } else
00159         cmdEnd->setText( TimeString::shortDate( end ) );
00160 }
00161 
00162 RepeatEntry::~RepeatEntry()
00163 {
00164 }
00165 
00166 Event::RepeatPattern RepeatEntry::repeatPattern()
00167 {
00168     QListIterator<QToolButton> it( listRTypeButtons );
00169     QListIterator<QToolButton> itExtra( listExtra );
00170     Event::RepeatPattern rpTmp;
00171     int i;
00172     for ( i = 0; *it; ++it, i++ ) {
00173         if ( (*it)->isOn() ) {
00174             switch ( i ) {
00175                 case NONE:
00176                    rpTmp.type = Event::NoRepeat;
00177                    break;
00178                 case DAY:
00179                     rpTmp.type = Event::Daily;
00180                     break;
00181                 case WEEK:
00182                     rpTmp.type = Event::Weekly;
00183                     rpTmp.days = 0;
00184                     int day;
00185                     for ( day = 1; *itExtra; ++itExtra, day = day << 1 ) {
00186                         if ( (*itExtra)->isOn() ) {
00187                             if ( startWeekOnMonday )
00188                                 rpTmp.days |= day;
00189                             else {
00190                                 if ( day == 1 )
00191                                     rpTmp.days |= Event::SUN;
00192                                 else
00193                                     rpTmp.days |= day >> 1;
00194                             }
00195                         }
00196                     }
00197                     break;
00198                 case MONTH:
00199                     if ( cmdExtra1->isOn() )
00200                         rpTmp.type = Event::MonthlyDay;
00201                     else if ( cmdExtra2->isOn() )
00202                         rpTmp.type = Event::MonthlyDate;
00203                         // figure out the montly day...
00204                         rpTmp.position = week( start );
00205                     break;
00206                 case YEAR:
00207                     rpTmp.type = Event::Yearly;
00208                     break;
00209             }
00210             break;  // no need to keep looking!
00211         }
00212     }
00213     rpTmp.frequency = spinFreq->value();
00214     rpTmp.hasEndDate = !chkNoEnd->isChecked();
00215     if ( rpTmp.hasEndDate ) {
00216         rpTmp.setEndDate( end );
00217     }
00218     // timestamp it...
00219     rpTmp.createTime = time( NULL );
00220     return rpTmp;
00221 }
00222 
00223 void RepeatEntry::slotSetRType( int rtype )
00224 {
00225     // now call the right function based on the type...
00226     currInterval = static_cast<repeatButtons>(rtype);
00227     switch ( currInterval ) {
00228         case NONE:
00229             setupNone();
00230             break;
00231         case DAY:
00232             setupDaily();
00233             break;
00234         case WEEK:
00235             setupWeekly();
00236             slotWeekLabel();
00237             break;
00238         case MONTH:
00239             setupMonthly();
00240             cmdExtra2->setOn( TRUE );
00241             slotMonthLabel( 1 );
00242             break;
00243         case YEAR:
00244             setupYearly();
00245             break;
00246     }
00247 }
00248 
00249 void RepeatEntry::setupNone()
00250 {
00251     lblRepeat->setText( tr("No Repeat") );
00252     lblVar1->hide();
00253     lblVar2->hide();
00254     hideExtras();
00255     cmdEnd->hide();
00256     lblFreq->hide();
00257     lblEvery->hide();
00258     lblFreq->hide();
00259     spinFreq->hide();
00260     lblEnd->hide();
00261     lblWeekVar->hide();
00262 }
00263 
00264 void RepeatEntry::setupDaily()
00265 {
00266     hideExtras();
00267     lblWeekVar->hide();
00268     spinFreq->setValue( 1 );
00269     lblFreq->setText( tr("day(s)") );
00270     lblVar2->show();
00271     showRepeatStuff();
00272     lblRepeat->setText( strDayTemplate );
00273     setupRepeatLabel( 1 );
00274 }
00275 
00276 void RepeatEntry::setupWeekly()
00277 {
00278     // reshow the buttons...
00279     fraExtra->setTitle( RepeatEntryBase::tr("Repeat On") );
00280     fraExtra->setExclusive( FALSE );
00281     fraExtra->show();
00282     if ( startWeekOnMonday ) {
00283         cmdExtra1->setText( RepeatEntryBase::tr("Mon") );
00284         cmdExtra2->setText( RepeatEntryBase::tr("Tue") );
00285         cmdExtra3->setText( RepeatEntryBase::tr("Wed") );
00286         cmdExtra4->setText( RepeatEntryBase::tr("Thu") );
00287         cmdExtra5->setText( RepeatEntryBase::tr("Fri") );
00288         cmdExtra6->setText( RepeatEntryBase::tr("Sat") );
00289         cmdExtra7->setText( RepeatEntryBase::tr("Sun") );
00290     } else {
00291         cmdExtra1->setText( RepeatEntryBase::tr("Sun") );
00292         cmdExtra2->setText( RepeatEntryBase::tr("Mon") );
00293         cmdExtra3->setText( RepeatEntryBase::tr("Tue") );
00294         cmdExtra4->setText( RepeatEntryBase::tr("Wed") );
00295         cmdExtra5->setText( RepeatEntryBase::tr("Thu") );
00296         cmdExtra6->setText( RepeatEntryBase::tr("Fri") );
00297         cmdExtra7->setText( RepeatEntryBase::tr("Sat") );
00298     }
00299     // I hope clustering these improve performance....
00300     cmdExtra1->setOn( FALSE );
00301     cmdExtra2->setOn( FALSE );
00302     cmdExtra3->setOn( FALSE );
00303     cmdExtra4->setOn( FALSE );
00304     cmdExtra5->setOn( FALSE );
00305     cmdExtra6->setOn( FALSE );
00306     cmdExtra7->setOn( FALSE );
00307 
00308     cmdExtra1->show();
00309     cmdExtra2->show();
00310     cmdExtra3->show();
00311     cmdExtra4->show();
00312     cmdExtra5->show();
00313     cmdExtra6->show();
00314     cmdExtra7->show();
00315 
00316     lblWeekVar->show();
00317     spinFreq->setValue( 1 );
00318     // might as well set the day too...
00319     if ( startWeekOnMonday ) {
00320         fraExtra->setButton( start.dayOfWeek() - 1 );
00321     } else {
00322         fraExtra->setButton( start.dayOfWeek() % 7 );
00323     }
00324     lblFreq->setText( tr("week(s)") );
00325     lblVar2->show();
00326     showRepeatStuff();
00327     setupRepeatLabel( 1 );
00328 }
00329 
00330 void RepeatEntry::setupMonthly()
00331 {
00332     hideExtras();
00333     lblWeekVar->hide();
00334     fraExtra->setTitle( tr("Repeat By") );
00335     fraExtra->setExclusive( TRUE );
00336     fraExtra->show();
00337     cmdExtra1->setText( tr("Day") );
00338     cmdExtra1->show();
00339     cmdExtra2->setText( tr("Date") );
00340     cmdExtra2->show();
00341     spinFreq->setValue( 1 );
00342     lblFreq->setText( tr("month(s)") );
00343     lblVar2->show();
00344     showRepeatStuff();
00345     setupRepeatLabel( 1 );
00346 }
00347 
00348 void RepeatEntry::setupYearly()
00349 {
00350     hideExtras();
00351     lblWeekVar->hide();
00352     spinFreq->setValue( 1 );
00353     lblFreq->setText( tr("year(s)") );
00354     lblFreq->show();
00355     lblFreq->show();
00356     showRepeatStuff();
00357     lblVar2->show();
00358     QString strEvery = strYearTemplate.arg( start.monthName(start.month()) ).arg( numberPlacing(start.day()) );
00359     lblRepeat->setText( strEvery );
00360     setupRepeatLabel( 1 );
00361 
00362 }
00363 
00364 void RepeatEntry::init()
00365 {
00366     QPopupMenu *m1 = new QPopupMenu( this );
00367     repeatPicker = new DateBookMonth( m1, 0, TRUE );
00368     m1->insertItem( repeatPicker );
00369     cmdEnd->setPopup( m1 );
00370     cmdEnd->setPopupDelay( 0 );
00371 
00372     QObject::connect( repeatPicker, SIGNAL(dateClicked(int,int,int)),
00373                       this, SLOT(endDateChanged(int,int,int)) );
00374     QObject::connect( qApp, SIGNAL(weekChanged(bool)),
00375                       this, SLOT(slotChangeStartOfWeek(bool)) );
00376 
00377     listRTypeButtons.setAutoDelete( TRUE );
00378     listRTypeButtons.append( cmdNone );
00379     listRTypeButtons.append( cmdDay );
00380     listRTypeButtons.append( cmdWeek );
00381     listRTypeButtons.append( cmdMonth );
00382     listRTypeButtons.append( cmdYear );
00383 
00384     listExtra.setAutoDelete( TRUE );
00385     listExtra.append( cmdExtra1 );
00386     listExtra.append( cmdExtra2 );
00387     listExtra.append( cmdExtra3 );
00388     listExtra.append( cmdExtra4 );
00389     listExtra.append( cmdExtra5 );
00390     listExtra.append( cmdExtra6 );
00391     listExtra.append( cmdExtra7 );
00392 }
00393 
00394 void RepeatEntry::slotNoEnd( bool unused )
00395 {
00396     // if the item was toggled, then go ahead and set it to the maximum date
00397     if ( unused ) {
00398         end.setYMD( 3000, 12, 31 );
00399         cmdEnd->setText( RepeatEntryBase::tr("No End Date") );
00400     } else {
00401         end = start;
00402         cmdEnd->setText( TimeString::shortDate(end) );
00403     }
00404 }
00405 
00406 void RepeatEntry::endDateChanged( int y, int m, int d )
00407 {
00408     end.setYMD( y, m, d );
00409     if ( end < start )
00410         end = start;
00411     cmdEnd->setText(  TimeString::shortDate( end ) );
00412     repeatPicker->setDate( end.year(), end.month(), end.day() );
00413 }
00414 
00415 void RepeatEntry::setupRepeatLabel( const QString &s )
00416 {
00417     lblVar1->setText( s );
00418 }
00419 
00420 void RepeatEntry::setupRepeatLabel( int x )
00421 {
00422     // change the spelling based on the value of x
00423     QString strVar2;
00424 
00425     if ( x > 1 )
00426         lblVar1->show();
00427     else
00428         lblVar1->hide();
00429 
00430     switch ( currInterval ) {
00431         case NONE:
00432             break;
00433         case DAY:
00434             if ( x > 1 )
00435                 strVar2 = tr( "days" );
00436             else
00437                 strVar2 = tr( "day" );
00438             break;
00439         case WEEK:
00440             if ( x > 1 )
00441                 strVar2 = tr( "weeks" );
00442             else
00443                 strVar2 = tr( "week" );
00444             break;
00445         case MONTH:
00446             if ( x > 1 )
00447                 strVar2 = RepeatEntryBase::tr( "months" );
00448             else
00449                 strVar2 = tr( "month" );
00450             break;
00451         case YEAR:
00452             if ( x > 1 )
00453                 strVar2 = RepeatEntryBase::tr( "years" );
00454             else
00455                 strVar2 = tr( "year" );
00456             break;
00457     }
00458     if ( !strVar2.isNull() )
00459         lblVar2->setText( strVar2 );
00460 }
00461 
00462 void RepeatEntry::showRepeatStuff()
00463 {
00464     cmdEnd->show();
00465     chkNoEnd->show();
00466     lblFreq->show();
00467     lblEvery->show();
00468     lblFreq->show();
00469     spinFreq->show();
00470     lblEnd->show();
00471     lblRepeat->setText( RepeatEntryBase::tr("Every") );
00472 }
00473 
00474 void RepeatEntry::slotWeekLabel()
00475 {
00476     QString str;
00477     QListIterator<QToolButton> it( listExtra );
00478     unsigned int i;
00479     unsigned int keepMe;
00480     bool bNeedCarriage = FALSE;
00481     // don't do something we'll regret!!!
00482     if ( currInterval != WEEK )
00483         return;
00484 
00485     if ( startWeekOnMonday )
00486         keepMe = start.dayOfWeek() - 1;
00487     else
00488         keepMe = start.dayOfWeek() % 7;
00489 
00490     QStringList list;
00491     for ( i = 0; *it; ++it, i++ ) {
00492         // a crazy check, if you are repeating weekly, the current day
00493         // must be selected!!!
00494         if ( i == keepMe && !( (*it)->isOn() ) )
00495             (*it)->setOn( TRUE );
00496         if ( (*it)->isOn() ) {
00497             if ( startWeekOnMonday )
00498                 list.append( dayLabel[i] );
00499             else {
00500                 if ( i == 0 )
00501                     list.append( dayLabel[6] );
00502                 else
00503                     list.append( dayLabel[i - 1] );
00504             }
00505         }
00506     }
00507     QStringList::Iterator itStr;
00508     for ( i = 0, itStr = list.begin(); itStr != list.end(); ++itStr, i++ ) {
00509         if ( i == 3 )
00510             bNeedCarriage = TRUE;
00511         else
00512             bNeedCarriage = FALSE;
00513         if ( str.isNull() )
00514             str = *itStr;
00515         else if ( i == list.count() - 1 ) {
00516             if ( i < 2 )
00517                 str += tr(" and ") + *itStr;
00518             else {
00519                 if ( bNeedCarriage )
00520                     str += tr( ",\nand " ) + *itStr;
00521                 else
00522                     str += tr( ", and " ) + *itStr;
00523             }
00524         } else {
00525             if ( bNeedCarriage )
00526                 str += ",\n" + *itStr;
00527             else
00528                 str += ", " + *itStr;
00529         }
00530     }
00531     str = str.prepend( tr("on ") );
00532     lblWeekVar->setText( str );
00533 }
00534 
00535 void RepeatEntry::slotMonthLabel( int type )
00536 {
00537     QString str;
00538     if ( currInterval != MONTH || type > 1 )
00539         return;
00540     if ( type == 1 )
00541         str = strMonthDateTemplate.arg( numberPlacing(start.day()) );
00542     else
00543         str = strMonthDayTemplate.arg( numberPlacing(week(start)))
00544               .arg( dayLabel[start.dayOfWeek() - 1] );
00545     lblRepeat->setText( str );
00546 }
00547 
00548 void RepeatEntry::slotChangeStartOfWeek( bool onMonday )
00549 {
00550     startWeekOnMonday = onMonday;
00551     // we need to make this unintrusive as possible...
00552     int saveSpin = spinFreq->value();
00553     char days = 0;
00554     int day;
00555     QListIterator<QToolButton> itExtra( listExtra );
00556     for ( day = 1; *itExtra; ++itExtra, day = day << 1 ) {
00557         if ( (*itExtra)->isOn() ) {
00558             if ( !startWeekOnMonday )
00559                 days |= day;
00560             else {
00561                 if ( day == 1 )
00562                     days |= Event::SUN;
00563                 else
00564                     days |= day >> 1;
00565             }
00566         }
00567     }
00568     setupWeekly();
00569     spinFreq->setValue( saveSpin );
00570     int buttons;
00571     for ( day = 0x01, buttons = 0; buttons < 7;
00572           day = day << 1, buttons++ ) {
00573         if ( days & day ) {
00574             if ( startWeekOnMonday )
00575                 fraExtra->setButton( buttons );
00576             else {
00577                 if ( buttons == 7 )
00578                     fraExtra->setButton( 0 );
00579                 else
00580                     fraExtra->setButton( buttons + 1 );
00581             }
00582         }
00583     }
00584     slotWeekLabel();
00585 }
00586 
00587 static int week( const QDate &start )
00588 {
00589     // figure out the week...
00590     int stop = start.day(),
00591         sentinel = start.dayOfWeek(),
00592         dayOfWeek = QDate( start.year(), start.month(), 1 ).dayOfWeek(),
00593         week = 1,
00594         i;
00595     for ( i = 1; i < stop; i++ ) {
00596         if ( dayOfWeek++ == sentinel )
00597             week++;
00598         if ( dayOfWeek > 7 )
00599             dayOfWeek = 0;
00600     }
00601     return week;
00602 }
00603 
00604 static QString numberPlacing( int x )
00605 {
00606     // I hope this works in other languages besides english...
00607     QString str = QString::number( x );
00608     switch ( x % 10 ) {
00609         case 1:
00610             str += QWidget::tr( "st" );
00611             break;
00612         case 2:
00613             str += QWidget::tr( "nd" );
00614             break;
00615         case 3:
00616             str += QWidget::tr( "rd" );
00617             break;
00618         default:
00619             str += QWidget::tr( "th" );
00620             break;
00621     }
00622     return str;
00623 }

Generated on Sat Nov 5 16:15:49 2005 for OPIE by  doxygen 1.4.2