korganizer

koeditorrecurrence.cpp

00001 /*
00002     This file is part of KOrganizer.
00003     Copyright (c) 2000-2003 Cornelius Schumacher <schumacher@kde.org>
00004     Copyright (C) 2003-2004 Reinhold Kainhofer <reinhold@kainhofer.com>
00005 
00006     This program is free software; you can redistribute it and/or modify
00007     it under the terms of the GNU General Public License as published by
00008     the Free Software Foundation; either version 2 of the License, or
00009     (at your option) any later version.
00010 
00011     This program 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
00014     GNU General Public License for more details.
00015 
00016     You should have received a copy of the GNU General Public License
00017     along with this program; if not, write to the Free Software
00018     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00019 
00020     As a special exception, permission is given to link this program
00021     with any edition of Qt, and distribute the resulting executable,
00022     without including the source code for Qt in the source distribution.
00023 */
00024 
00025 #include <qtooltip.h>
00026 #include <qfiledialog.h>
00027 #include <qlayout.h>
00028 #include <qvbox.h>
00029 #include <qbuttongroup.h>
00030 #include <qvgroupbox.h>
00031 #include <qwidgetstack.h>
00032 #include <qdatetime.h>
00033 #include <qlistbox.h>
00034 #include <qspinbox.h>
00035 #include <qcheckbox.h>
00036 #include <qgroupbox.h>
00037 #include <qwidgetstack.h>
00038 #include <qradiobutton.h>
00039 #include <qlabel.h>
00040 #include <qpushbutton.h>
00041 #include <qwhatsthis.h>
00042 
00043 #include <kdialog.h>
00044 #include <kglobal.h>
00045 #include <klocale.h>
00046 #include <kiconloader.h>
00047 #include <kdebug.h>
00048 #include <knumvalidator.h>
00049 #include <kcalendarsystem.h>
00050 #include <kmessagebox.h>
00051 
00052 #include <libkdepim/kdateedit.h>
00053 #include <libkcal/todo.h>
00054 
00055 #include "koprefs.h"
00056 #include "koglobals.h"
00057 
00058 #include "koeditorrecurrence.h"
00059 #include "koeditorrecurrence.moc"
00060 
00062 
00063 RecurBase::RecurBase( QWidget *parent, const char *name ) :
00064   QWidget( parent, name )
00065 {
00066   mFrequencyEdit = new QSpinBox( 1, 9999, 1, this );
00067   mFrequencyEdit->setValue( 1 );
00068 }
00069 
00070 QWidget *RecurBase::frequencyEdit()
00071 {
00072   return mFrequencyEdit;
00073 }
00074 
00075 void RecurBase::setFrequency( int f )
00076 {
00077   if ( f < 1 ) f = 1;
00078 
00079   mFrequencyEdit->setValue( f );
00080 }
00081 
00082 int RecurBase::frequency()
00083 {
00084   return mFrequencyEdit->value();
00085 }
00086 
00087 QComboBox *RecurBase::createWeekCountCombo( QWidget *parent, const char *name )
00088 {
00089   QComboBox *combo = new QComboBox( parent, name );
00090   QWhatsThis::add( combo,
00091                    i18n("The number of the week from the beginning "
00092                         "of the month on which this event or to-do "
00093                         "should recur.") );
00094   if ( !combo ) return 0;
00095   combo->insertItem( i18n("1st") );
00096   combo->insertItem( i18n("2nd") );
00097   combo->insertItem( i18n("3rd") );
00098   combo->insertItem( i18n("4th") );
00099   combo->insertItem( i18n("5th") );
00100   combo->insertItem( i18n("Last") );
00101   combo->insertItem( i18n("2nd Last") );
00102   combo->insertItem( i18n("3rd Last") );
00103   combo->insertItem( i18n("4th Last") );
00104   combo->insertItem( i18n("5th Last") );
00105   return combo;
00106 }
00107 
00108 QComboBox *RecurBase::createWeekdayCombo( QWidget *parent, const char *name )
00109 {
00110   QComboBox *combo = new QComboBox( parent, name );
00111   QWhatsThis::add( combo,
00112                    i18n("The weekday on which this event or to-do "
00113                         "should recur.") );
00114   if ( !combo ) return 0;
00115   const KCalendarSystem *calSys = KOGlobals::self()->calendarSystem();
00116   for( int i = 1; i <= 7; ++i ) {
00117     combo->insertItem( calSys->weekDayName( i ) );
00118   }
00119   return combo;
00120 }
00121 
00122 QComboBox *RecurBase::createMonthNameCombo( QWidget *parent, const char *name )
00123 {
00124   QComboBox *combo = new QComboBox( parent, name );
00125   QWhatsThis::add( combo,
00126                    i18n("The month during which this event or to-do "
00127                         "should recur.") );
00128   if ( !combo ) return 0;
00129   const KCalendarSystem *calSys = KOGlobals::self()->calendarSystem();
00130   for( int i = 1; i <= 12; ++i ) {
00131     // use an arbitrary year, we just need the month name...
00132     QDate dt( 2005, i, 1 );
00133     combo->insertItem( calSys->monthName( dt ) );
00134   }
00135   return combo;
00136 }
00137 
00138 QBoxLayout *RecurBase::createFrequencySpinBar( QWidget *parent, QLayout *layout,
00139     QString everyText, QString unitText )
00140 {
00141   QBoxLayout *freqLayout = new QHBoxLayout( layout );
00142 
00143   QString whatsThis = i18n("Sets how often this event or to-do should recur.");
00144   QLabel *preLabel = new QLabel( everyText, parent );
00145   QWhatsThis::add( preLabel, whatsThis );
00146   freqLayout->addWidget( preLabel );
00147 
00148   freqLayout->addWidget( frequencyEdit() );
00149   preLabel->setBuddy( frequencyEdit() );
00150   QWhatsThis::add( preLabel->buddy(), whatsThis );
00151 
00152   QLabel *postLabel = new QLabel( unitText, parent );
00153   QWhatsThis::add( postLabel, whatsThis );
00154   freqLayout->addWidget( postLabel );
00155   freqLayout->addStretch();
00156   return freqLayout;
00157 }
00158 
00160 
00161 RecurDaily::RecurDaily( QWidget *parent, const char *name ) :
00162   RecurBase( parent, name )
00163 {
00164   QBoxLayout *topLayout = new QVBoxLayout( this );
00165   topLayout->setSpacing( KDialog::spacingHint() );
00166 
00167   createFrequencySpinBar( this, topLayout, i18n("&Recur every"), i18n("day(s)") );
00168 }
00169 
00170 
00172 
00173 RecurWeekly::RecurWeekly( QWidget *parent, const char *name ) :
00174   RecurBase( parent, name )
00175 {
00176   QBoxLayout *topLayout = new QVBoxLayout( this );
00177   topLayout->setSpacing( KDialog::spacingHint() );
00178 
00179 //  topLayout->addStretch( 1 );
00180 
00181   createFrequencySpinBar( this, topLayout, i18n("&Recur every"), i18n("week(s) on:") );
00182 
00183   QHBox *dayBox = new QHBox( this );
00184   topLayout->addWidget( dayBox, 1, AlignVCenter );
00185   // Respect start of week setting
00186   int weekStart=KGlobal::locale()->weekStartDay();
00187   for ( int i = 0; i < 7; ++i ) {
00188     // i is the nr of the combobox, not the day of week!
00189     // label=(i+weekStart+6)%7 + 1;
00190     // index in CheckBox array(=day): label-1
00191     const KCalendarSystem *calSys = KOGlobals::self()->calendarSystem();
00192     QString weekDayName = calSys->weekDayName(
00193       (i + weekStart + 6)%7 + 1, true );
00194     if ( KOPrefs::instance()->mCompactDialogs ) {
00195       weekDayName = weekDayName.left( 1 );
00196     }
00197     mDayBoxes[ (i + weekStart + 6)%7 ] = new QCheckBox( weekDayName, dayBox );
00198     QWhatsThis::add( mDayBoxes[ (i + weekStart + 6)%7 ],
00199                      i18n("Day of the week on which this event or to-do "
00200                           "should recur.") );
00201   }
00202 
00203   topLayout->addStretch( 1 );
00204 }
00205 
00206 void RecurWeekly::setDays( const QBitArray &days )
00207 {
00208   for ( int i = 0; i < 7; ++i ) {
00209     mDayBoxes[ i ]->setChecked( days.testBit( i ) );
00210   }
00211 }
00212 
00213 QBitArray RecurWeekly::days()
00214 {
00215   QBitArray days( 7 );
00216 
00217   for ( int i = 0; i < 7; ++i ) {
00218     days.setBit( i, mDayBoxes[ i ]->isChecked() );
00219   }
00220 
00221   return days;
00222 }
00223 
00225 
00226 RecurMonthly::RecurMonthly( QWidget *parent, const char *name ) :
00227   RecurBase( parent, name )
00228 {
00229   QBoxLayout *topLayout = new QVBoxLayout( this );
00230   topLayout->setSpacing( KDialog::spacingHint() );
00231 
00232   createFrequencySpinBar( this, topLayout, i18n("&Recur every"), i18n("month(s)") );
00233 
00234   QButtonGroup *buttonGroup = new QButtonGroup( this );
00235   buttonGroup->setFrameStyle( QFrame::NoFrame );
00236   topLayout->addWidget( buttonGroup, 1, AlignVCenter );
00237 
00238   QGridLayout *buttonLayout = new QGridLayout( buttonGroup, 3, 2 );
00239   buttonLayout->setSpacing( KDialog::spacingHint() );
00240 
00241 
00242   QString recurOnText;
00243   if ( !KOPrefs::instance()->mCompactDialogs ) {
00244     recurOnText = i18n("&Recur on the");
00245   }
00246 
00247   mByDayRadio = new QRadioButton( recurOnText, buttonGroup );
00248   QWhatsThis::add( mByDayRadio,
00249                    i18n("Sets a specific day of the month on which "
00250                         "this event or to-do should recur.") );
00251   
00252   buttonLayout->addWidget( mByDayRadio, 0, 0 );
00253 
00254   QString whatsThis = i18n("The day of the month on which this event or to-do "
00255                            "should recur.");
00256   mByDayCombo = new QComboBox( buttonGroup );
00257   QWhatsThis::add( mByDayCombo, whatsThis );
00258   mByDayCombo->setSizeLimit( 7 );
00259   mByDayCombo->insertItem( i18n("1st") );
00260   mByDayCombo->insertItem( i18n("2nd") );
00261   mByDayCombo->insertItem( i18n("3rd") );
00262   mByDayCombo->insertItem( i18n("4th") );
00263   mByDayCombo->insertItem( i18n("5th") );
00264   mByDayCombo->insertItem( i18n("6th") );
00265   mByDayCombo->insertItem( i18n("7th") );
00266   mByDayCombo->insertItem( i18n("8th") );
00267   mByDayCombo->insertItem( i18n("9th") );
00268   mByDayCombo->insertItem( i18n("10th") );
00269   mByDayCombo->insertItem( i18n("11th") );
00270   mByDayCombo->insertItem( i18n("12th") );
00271   mByDayCombo->insertItem( i18n("13th") );
00272   mByDayCombo->insertItem( i18n("14th") );
00273   mByDayCombo->insertItem( i18n("15th") );
00274   mByDayCombo->insertItem( i18n("16th") );
00275   mByDayCombo->insertItem( i18n("17th") );
00276   mByDayCombo->insertItem( i18n("18th") );
00277   mByDayCombo->insertItem( i18n("19th") );
00278   mByDayCombo->insertItem( i18n("20th") );
00279   mByDayCombo->insertItem( i18n("21st") );
00280   mByDayCombo->insertItem( i18n("22nd") );
00281   mByDayCombo->insertItem( i18n("23rd") );
00282   mByDayCombo->insertItem( i18n("24th") );
00283   mByDayCombo->insertItem( i18n("25th") );
00284   mByDayCombo->insertItem( i18n("26th") );
00285   mByDayCombo->insertItem( i18n("27th") );
00286   mByDayCombo->insertItem( i18n("28th") );
00287   mByDayCombo->insertItem( i18n("29th") );
00288   mByDayCombo->insertItem( i18n("30th") );
00289   mByDayCombo->insertItem( i18n("31st") );
00290   mByDayCombo->insertItem( i18n("Last") );
00291   mByDayCombo->insertItem( i18n("2nd Last") );
00292   mByDayCombo->insertItem( i18n("3rd Last") );
00293   mByDayCombo->insertItem( i18n("4th Last") );
00294   mByDayCombo->insertItem( i18n("5th Last") );
00295   // FIXME: After the string freeze is over, insert all possible values, not
00296   //        just the ones we already have translated:
00297 /*  mByDayCombo->insertItem( i18n("6th Last") );
00298   mByDayCombo->insertItem( i18n("7th Last") );
00299   mByDayCombo->insertItem( i18n("8th Last") );
00300   mByDayCombo->insertItem( i18n("9th Last") );
00301   mByDayCombo->insertItem( i18n("10th Last") );
00302   mByDayCombo->insertItem( i18n("11th Last") );
00303   mByDayCombo->insertItem( i18n("12th Last") );
00304   mByDayCombo->insertItem( i18n("13th Last") );
00305   mByDayCombo->insertItem( i18n("14th Last") );
00306   mByDayCombo->insertItem( i18n("15th Last") );
00307   mByDayCombo->insertItem( i18n("16th Last") );
00308   mByDayCombo->insertItem( i18n("17th Last") );
00309   mByDayCombo->insertItem( i18n("18th Last") );
00310   mByDayCombo->insertItem( i18n("19th Last") );
00311   mByDayCombo->insertItem( i18n("20th Last") );
00312   mByDayCombo->insertItem( i18n("21st Last") );
00313   mByDayCombo->insertItem( i18n("22nd Last") );
00314   mByDayCombo->insertItem( i18n("23rd Last") );
00315   mByDayCombo->insertItem( i18n("24th Last") );
00316   mByDayCombo->insertItem( i18n("25th Last") );
00317   mByDayCombo->insertItem( i18n("26th Last") );
00318   mByDayCombo->insertItem( i18n("27th Last") );
00319   mByDayCombo->insertItem( i18n("28th Last") );
00320   mByDayCombo->insertItem( i18n("29th Last") );
00321   mByDayCombo->insertItem( i18n("30th Last") );
00322   mByDayCombo->insertItem( i18n("31st Last") );*/
00323   buttonLayout->addWidget( mByDayCombo, 0, 1 );
00324 
00325   QLabel *byDayLabel = new QLabel( i18n("day"), buttonGroup );
00326   QWhatsThis::add( byDayLabel, whatsThis );
00327   buttonLayout->addWidget( byDayLabel, 0, 2 );
00328 
00329 
00330   mByPosRadio = new QRadioButton( recurOnText, buttonGroup);
00331   QWhatsThis::add( mByPosRadio,
00332                    i18n("Sets a weekday and specific week in the month "
00333                         "on which this event or to-do should recur") );
00334   buttonLayout->addWidget( mByPosRadio, 1, 0 );
00335 
00336   mByPosCountCombo = createWeekCountCombo( buttonGroup );
00337   buttonLayout->addWidget( mByPosCountCombo, 1, 1 );
00338 
00339   mByPosWeekdayCombo = createWeekdayCombo( buttonGroup );
00340   buttonLayout->addWidget( mByPosWeekdayCombo, 1, 2 );
00341 }
00342 
00343 void RecurMonthly::setByDay( int day )
00344 {
00345   mByDayRadio->setChecked( true );
00346   // Days from the end are after the ones from the begin, so correct for the
00347   // negative sign and add 30 (index starting at 0)
00348   if ( day > 0 && day <= 31 )
00349     mByDayCombo->setCurrentItem( day-1 );
00350   else if ( day < 0 )
00351     mByDayCombo->setCurrentItem( 31 - 1 - day );
00352 }
00353 
00354 void RecurMonthly::setByPos( int count, int weekday )
00355 {
00356   mByPosRadio->setChecked( true );
00357   if (count>0)
00358     mByPosCountCombo->setCurrentItem( count - 1 );
00359   else
00360     // negative weeks means counted from the end of month
00361     mByPosCountCombo->setCurrentItem( -count + 4 );
00362   mByPosWeekdayCombo->setCurrentItem( weekday - 1 );
00363 }
00364 
00365 bool RecurMonthly::byDay()
00366 {
00367   return mByDayRadio->isChecked();
00368 }
00369 
00370 bool RecurMonthly::byPos()
00371 {
00372   return mByPosRadio->isChecked();
00373 }
00374 
00375 int RecurMonthly::day()
00376 {
00377   int day = mByDayCombo->currentItem();
00378   if ( day >= 31 ) day = 31-day-1;
00379   else ++day;
00380   return day;
00381 }
00382 
00383 int RecurMonthly::count()
00384 {
00385   int pos=mByPosCountCombo->currentItem();
00386   if (pos<=4) // positive  count
00387     return pos+1;
00388   else
00389     return -pos+4;
00390 }
00391 
00392 int RecurMonthly::weekday()
00393 {
00394   return mByPosWeekdayCombo->currentItem() + 1;
00395 }
00396 
00398 
00399 RecurYearly::RecurYearly( QWidget *parent, const char *name ) :
00400   RecurBase( parent, name )
00401 {
00402   QBoxLayout *topLayout = new QVBoxLayout( this );
00403   topLayout->setSpacing( KDialog::spacingHint() );
00404 
00405   createFrequencySpinBar( this, topLayout, i18n("&Recur every"), i18n("year(s)") );
00406 
00407 
00408   QButtonGroup *buttonGroup = new QButtonGroup( this );
00409   buttonGroup->setFrameStyle( QFrame::NoFrame );
00410   topLayout->addWidget( buttonGroup, 1, AlignVCenter );
00411 
00412   QBoxLayout *buttonLayout = new QVBoxLayout( buttonGroup );
00413 
00414 
00415   /* YearlyMonth (day n of Month Y) */
00416   QBoxLayout *monthLayout = new QHBoxLayout( buttonLayout );
00417   QString recurInMonthText(
00418       i18n("part before XXX of 'Recur on day XXX of month YYY'",
00419       "&Recur on day "));
00420   if ( KOPrefs::instance()->mCompactDialogs ) {
00421     recurInMonthText = i18n("&Day ");
00422   }
00423   mByMonthRadio = new QRadioButton( recurInMonthText, buttonGroup );
00424   QWhatsThis::add( mByMonthRadio,
00425        i18n("Sets a specific day in a specific month on which "
00426       "this event or to-do should recur.") );
00427   monthLayout->addWidget( mByMonthRadio );
00428   mByMonthSpin = new QSpinBox( 1, 31, 1, buttonGroup );
00429   QWhatsThis::add( mByMonthSpin,
00430        i18n("The day of the month on which this event or to-do "
00431       "should recur.") );
00432   monthLayout->addWidget( mByMonthSpin );
00433   QLabel *ofLabel = new QLabel(
00434       i18n("part between XXX and YYY of 'Recur on day XXX of month YYY'", " &of "),
00435       buttonGroup );
00436   //What do I do here? I'm not sure if this label should have What's This in it... - Antonio
00437   monthLayout->addWidget( ofLabel );
00438 
00439   mByMonthCombo = createMonthNameCombo( buttonGroup );
00440   monthLayout->addWidget( mByMonthCombo );
00441   ofLabel->setBuddy( mByMonthCombo );
00442 
00443   monthLayout->addStretch( 1 );
00444 
00445 
00446   /* YearlyPos (weekday X of week N of month Y) */
00447   QBoxLayout *posLayout = new QHBoxLayout( buttonLayout );
00448   QString recurOnPosText( i18n("Part before XXX in 'Recur on NNN. WEEKDAY of MONTH', short version", "&On" ) );
00449   if ( !KOPrefs::instance()->mCompactDialogs ) {
00450     recurOnPosText = i18n("Part before XXX in 'Recur on NNN. WEEKDAY of MONTH'", "&On the" );
00451   }
00452   mByPosRadio = new QRadioButton( recurOnPosText, buttonGroup );
00453   QWhatsThis::add( mByPosRadio,
00454        i18n("Sets a specific day in a specific week of a specific "
00455       "month on which this event or to-do should recur.") );
00456   posLayout->addWidget( mByPosRadio );
00457 
00458   mByPosDayCombo = createWeekCountCombo( buttonGroup );
00459   posLayout->addWidget( mByPosDayCombo );
00460 
00461   mByPosWeekdayCombo = createWeekdayCombo( buttonGroup );
00462   posLayout->addWidget( mByPosWeekdayCombo );
00463 
00464   ofLabel = new QLabel(
00465       i18n("part between WEEKDAY and MONTH in 'Recur on NNN. WEEKDAY of MONTH'", " o&f "),
00466       buttonGroup );
00467   posLayout->addWidget( ofLabel );
00468 
00469   mByPosMonthCombo  = createMonthNameCombo( buttonGroup );
00470   posLayout->addWidget( mByPosMonthCombo );
00471   ofLabel->setBuddy( mByPosMonthCombo );
00472 
00473   posLayout->addStretch( 1 );
00474 
00475 
00476   /* YearlyDay (day N of the year) */
00477   QBoxLayout *dayLayout = new QHBoxLayout( buttonLayout );
00478   QString recurOnDayText;
00479   if ( KOPrefs::instance()->mCompactDialogs ) {
00480     recurOnDayText = i18n("Day #");
00481   } else {
00482     recurOnDayText = i18n("Recur on &day #");
00483   }
00484   QString whatsThis = i18n("Sets a specific day within the year on which this "
00485          "event or to-do should recur.");
00486   mByDayRadio = new QRadioButton( recurOnDayText, buttonGroup );
00487   QWhatsThis::add( mByDayRadio, whatsThis );
00488   dayLayout->addWidget( mByDayRadio );
00489 
00490   mByDaySpin = new QSpinBox( 1, 366, 1, buttonGroup );
00491   QWhatsThis::add( mByDaySpin, whatsThis );
00492   
00493   dayLayout->addWidget( mByDaySpin );
00494 
00495   QString ofTheYear( i18n("part after NNN of 'Recur on day #NNN of the year'", " of the &year"));
00496   if ( KOPrefs::instance()->mCompactDialogs ) {
00497     ofTheYear = i18n("part after NNN of 'Recur on day #NNN of the year', short version",
00498         " of the year");
00499   }
00500   ofLabel = new QLabel( ofTheYear, buttonGroup );
00501   QWhatsThis::add( ofLabel, whatsThis );
00502   dayLayout->addWidget( ofLabel );
00503   ofLabel->setBuddy( mByDaySpin );
00504 
00505   dayLayout->addStretch( 1 );
00506 }
00507 
00508 void RecurYearly::setByDay( int day )
00509 {
00510   mByDayRadio->setChecked( true );
00511   mByDaySpin->setValue( day );
00512 }
00513 
00514 void RecurYearly::setByPos( int count, int weekday, int month )
00515 {
00516   mByPosRadio->setChecked( true );
00517   if ( count > 0 )
00518     mByPosDayCombo->setCurrentItem( count - 1 );
00519   else
00520     mByPosDayCombo->setCurrentItem( -count + 4 );
00521   mByPosWeekdayCombo->setCurrentItem( weekday - 1 );
00522   mByPosMonthCombo->setCurrentItem( month-1 );
00523 }
00524 
00525 void RecurYearly::setByMonth( int day, int month )
00526 {
00527   mByMonthRadio->setChecked( true );
00528   mByMonthSpin->setValue( day );
00529   mByMonthCombo->setCurrentItem( month - 1 );
00530 }
00531 
00532 RecurYearly::YearlyType RecurYearly::getType()
00533 {
00534   if ( mByMonthRadio->isChecked() ) return byMonth;
00535   if ( mByPosRadio->isChecked() ) return byPos;
00536   if ( mByDayRadio->isChecked() ) return byDay;
00537   return byMonth;
00538 }
00539 
00540 int RecurYearly::monthDay()
00541 {
00542   return mByMonthSpin->value();
00543 }
00544 
00545 int RecurYearly::month()
00546 {
00547   return mByMonthCombo->currentItem() + 1;
00548 }
00549 
00550 int RecurYearly::posCount()
00551 {
00552   int pos = mByPosDayCombo->currentItem();
00553   if ( pos <= 4 ) // positive  count
00554     return pos + 1;
00555   else
00556     return -pos + 4;
00557 }
00558 
00559 int RecurYearly::posWeekday()
00560 {
00561   return mByPosWeekdayCombo->currentItem() + 1;
00562 }
00563 
00564 int RecurYearly::posMonth()
00565 {
00566   return mByPosMonthCombo->currentItem() + 1;
00567 }
00568 
00569 int RecurYearly::day()
00570 {
00571   return mByDaySpin->value();
00572 }
00573 
00575 
00576 ExceptionsWidget::ExceptionsWidget( QWidget *parent, const char *name ) :
00577   QWidget( parent, name )
00578 {
00579   QBoxLayout *topLayout = new QVBoxLayout( this );
00580 
00581   QGroupBox *groupBox = new QGroupBox( 1, Horizontal, i18n("E&xceptions"),
00582                                        this );
00583   topLayout->addWidget( groupBox );
00584 
00585   QWidget *box = new QWidget( groupBox );
00586 
00587   QGridLayout *boxLayout = new QGridLayout( box );
00588 
00589   mExceptionDateEdit = new KDateEdit( box );
00590   QWhatsThis::add( mExceptionDateEdit,
00591        i18n("A date that should be considered an exception "
00592       "to the recurrence rules for this event or to-do.") );
00593   mExceptionDateEdit->setDate( QDate::currentDate() );
00594   boxLayout->addWidget( mExceptionDateEdit, 0, 0 );
00595 
00596   QPushButton *addExceptionButton = new QPushButton( i18n("&Add"), box );
00597   QWhatsThis::add( addExceptionButton,
00598        i18n("Add this date as an exception "
00599       "to the recurrence rules for this event or to-do.") );
00600   boxLayout->addWidget( addExceptionButton, 1, 0 );
00601   QPushButton *changeExceptionButton = new QPushButton( i18n("&Change"), box );
00602   QWhatsThis::add( changeExceptionButton,
00603        i18n("Replace the currently selected date with this date.") );
00604   boxLayout->addWidget( changeExceptionButton, 2, 0 );
00605   QPushButton *deleteExceptionButton = new QPushButton( i18n("&Delete"), box );
00606   QWhatsThis::add( deleteExceptionButton,
00607        i18n("Delete the currently selected date from the list of dates "
00608             "that should be considered exceptions to the recurrence rules "
00609             "for this event or to-do.") );
00610   boxLayout->addWidget( deleteExceptionButton, 3, 0 );
00611 
00612   mExceptionList = new QListBox( box );
00613   QWhatsThis::add( mExceptionList,
00614        i18n("Displays current dates that are being considered "
00615       "exceptions to the recurrence rules for this event "
00616       "or to-do.") );
00617   boxLayout->addMultiCellWidget( mExceptionList, 0, 3, 1, 1 );
00618 
00619   boxLayout->setRowStretch( 4, 1 );
00620   boxLayout->setColStretch( 1, 3 );
00621 
00622   connect( addExceptionButton, SIGNAL( clicked() ),
00623            SLOT( addException() ) );
00624   connect( changeExceptionButton, SIGNAL( clicked() ),
00625            SLOT( changeException() ) );
00626   connect( deleteExceptionButton, SIGNAL( clicked() ),
00627            SLOT( deleteException() ) );
00628 }
00629 
00630 void ExceptionsWidget::addException()
00631 {
00632   QDate date = mExceptionDateEdit->date();
00633   QString dateStr = KGlobal::locale()->formatDate( date );
00634   if( !mExceptionList->findItem( dateStr ) ) {
00635     mExceptionDates.append( date );
00636     mExceptionList->insertItem( dateStr );
00637   }
00638 }
00639 
00640 void ExceptionsWidget::changeException()
00641 {
00642   int pos = mExceptionList->currentItem();
00643   if ( pos < 0 ) return;
00644 
00645   QDate date = mExceptionDateEdit->date();
00646   mExceptionDates[ pos ] = date;
00647   mExceptionList->changeItem( KGlobal::locale()->formatDate( date ), pos );
00648 }
00649 
00650 void ExceptionsWidget::deleteException()
00651 {
00652   int pos = mExceptionList->currentItem();
00653   if ( pos < 0 ) return;
00654 
00655   mExceptionDates.remove( mExceptionDates.at( pos ) );
00656   mExceptionList->removeItem( pos );
00657 }
00658 
00659 void ExceptionsWidget::setDates( const DateList &dates )
00660 {
00661   mExceptionList->clear();
00662   mExceptionDates.clear();
00663   DateList::ConstIterator dit;
00664   for ( dit = dates.begin(); dit != dates.end(); ++dit ) {
00665     mExceptionList->insertItem( KGlobal::locale()->formatDate(* dit ) );
00666     mExceptionDates.append( *dit );
00667   }
00668 }
00669 
00670 DateList ExceptionsWidget::dates()
00671 {
00672   return mExceptionDates;
00673 }
00674 
00676 
00677 ExceptionsDialog::ExceptionsDialog( QWidget *parent, const char *name ) :
00678   KDialogBase( parent, name, true, i18n("Edit Exceptions"), Ok|Cancel )
00679 {
00680   mExceptions = new ExceptionsWidget( this );
00681   setMainWidget( mExceptions );
00682 }
00683 
00684 void ExceptionsDialog::setDates( const DateList &dates )
00685 {
00686   mExceptions->setDates( dates );
00687 }
00688 
00689 DateList ExceptionsDialog::dates()
00690 {
00691   return mExceptions->dates();
00692 }
00693 
00695 
00696 RecurrenceRangeWidget::RecurrenceRangeWidget( QWidget *parent,
00697                                               const char *name )
00698   : QWidget( parent, name )
00699 {
00700   QBoxLayout *topLayout = new QVBoxLayout( this );
00701 
00702   mRangeGroupBox = new QGroupBox( 1, Horizontal, i18n("Recurrence Range"),
00703                                   this );
00704   QWhatsThis::add( mRangeGroupBox,
00705        i18n("Sets a range for which these recurrence rules will "
00706       "apply to this event or to-do.") );
00707   topLayout->addWidget( mRangeGroupBox );
00708 
00709   QWidget *rangeBox = new QWidget( mRangeGroupBox );
00710   QVBoxLayout *rangeLayout = new QVBoxLayout( rangeBox );
00711   rangeLayout->setSpacing( KDialog::spacingHint() );
00712 
00713   mStartDateLabel = new QLabel( i18n("Begin on:"), rangeBox );
00714   QWhatsThis::add( mStartDateLabel,
00715        i18n("The date on which the recurrences for this event or to-do "
00716       "should begin.") );
00717   rangeLayout->addWidget( mStartDateLabel );
00718 
00719   QButtonGroup *rangeButtonGroup = new QButtonGroup( this );
00720   rangeButtonGroup->hide();
00721 
00722   mNoEndDateButton = new QRadioButton( i18n("&No ending date"), rangeBox );
00723   QWhatsThis::add( mNoEndDateButton,
00724        i18n("Sets the event or to-do to recur forever.") );
00725   rangeButtonGroup->insert( mNoEndDateButton );
00726   rangeLayout->addWidget( mNoEndDateButton );
00727 
00728   QBoxLayout *durationLayout = new QHBoxLayout( rangeLayout );
00729   durationLayout->setSpacing( KDialog::spacingHint() );
00730 
00731   mEndDurationButton = new QRadioButton( i18n("End &after"), rangeBox );
00732   QWhatsThis::add( mEndDurationButton,
00733        i18n("Sets the event or to-do to stop recurring after a "
00734       "certain number of occurrences.") );
00735   rangeButtonGroup->insert( mEndDurationButton );
00736   durationLayout->addWidget( mEndDurationButton );
00737 
00738   QString whatsThis = i18n("Number of times the event or to-do should recur "
00739            "before stopping.");
00740   mEndDurationEdit = new QSpinBox( 1, 9999, 1, rangeBox );
00741   QWhatsThis::add( mEndDurationEdit, whatsThis );
00742   durationLayout->addWidget( mEndDurationEdit );
00743 
00744   QLabel *endDurationLabel = new QLabel( i18n("&occurrence(s)"), rangeBox );
00745   QWhatsThis::add( endDurationLabel, whatsThis );
00746   durationLayout ->addWidget( endDurationLabel );
00747   endDurationLabel->setBuddy( mEndDurationEdit );
00748 
00749   QBoxLayout *endDateLayout = new QHBoxLayout( rangeLayout );
00750   endDateLayout->setSpacing( KDialog::spacingHint() );
00751 
00752   mEndDateButton = new QRadioButton( i18n("End &on:"), rangeBox );
00753   QWhatsThis::add( mEndDateButton,
00754                    i18n("Sets the event or to-do to stop recurring on "
00755                         "a certain date.") );
00756   rangeButtonGroup->insert( mEndDateButton );
00757   endDateLayout->addWidget( mEndDateButton );
00758 
00759   mEndDateEdit = new KDateEdit( rangeBox );
00760   QWhatsThis::add( mEndDateEdit,
00761                    i18n("Date after which the event or to-do should stop "
00762                         "recurring") );
00763   endDateLayout->addWidget( mEndDateEdit );
00764 
00765   endDateLayout->addStretch( 1 );
00766 
00767   connect( mNoEndDateButton, SIGNAL( toggled( bool ) ),
00768            SLOT( showCurrentRange() ) );
00769   connect( mEndDurationButton, SIGNAL( toggled( bool ) ),
00770            SLOT( showCurrentRange() ) );
00771   connect( mEndDateButton, SIGNAL( toggled( bool ) ),
00772            SLOT( showCurrentRange() ) );
00773 }
00774 
00775 void RecurrenceRangeWidget::setDefaults( const QDateTime &from  )
00776 {
00777   mNoEndDateButton->setChecked( true );
00778 
00779   setDateTimes( from );
00780   setEndDate( from.date() );
00781 }
00782 
00783 void RecurrenceRangeWidget::setDuration( int duration )
00784 {
00785   if ( duration == -1 ) {
00786     mNoEndDateButton->setChecked( true );
00787   } else if ( duration == 0 ) {
00788     mEndDateButton->setChecked( true );
00789   } else {
00790     mEndDurationButton->setChecked( true );
00791     mEndDurationEdit->setValue( duration );
00792   }
00793 }
00794 
00795 int RecurrenceRangeWidget::duration()
00796 {
00797   if ( mNoEndDateButton->isChecked() ) {
00798     return -1;
00799   } else if ( mEndDurationButton->isChecked() ) {
00800     return mEndDurationEdit->value();
00801   } else {
00802     return 0;
00803   }
00804 }
00805 
00806 void RecurrenceRangeWidget::setEndDate( const QDate &date )
00807 {
00808   mEndDateEdit->setDate( date );
00809 }
00810 
00811 QDate RecurrenceRangeWidget::endDate()
00812 {
00813   return mEndDateEdit->date();
00814 }
00815 
00816 void RecurrenceRangeWidget::showCurrentRange()
00817 {
00818   mEndDurationEdit->setEnabled( mEndDurationButton->isChecked() );
00819   mEndDateEdit->setEnabled( mEndDateButton->isChecked() );
00820 }
00821 
00822 void RecurrenceRangeWidget::setDateTimes( const QDateTime &start,
00823                                           const QDateTime & )
00824 {
00825   mStartDateLabel->setText( i18n("Begins on: %1")
00826       .arg( KGlobal::locale()->formatDate( start.date() ) ) );
00827 }
00828 
00830 
00831 RecurrenceRangeDialog::RecurrenceRangeDialog( QWidget *parent,
00832                                               const char *name ) :
00833   KDialogBase( parent, name, true, i18n("Edit Recurrence Range"), Ok|Cancel )
00834 {
00835   mRecurrenceRangeWidget = new RecurrenceRangeWidget( this );
00836   setMainWidget( mRecurrenceRangeWidget );
00837 }
00838 
00839 void RecurrenceRangeDialog::setDefaults( const QDateTime &from )
00840 {
00841   mRecurrenceRangeWidget->setDefaults( from );
00842 }
00843 
00844 void RecurrenceRangeDialog::setDuration( int duration )
00845 {
00846   mRecurrenceRangeWidget->setDuration( duration );
00847 }
00848 
00849 int RecurrenceRangeDialog::duration()
00850 {
00851   return mRecurrenceRangeWidget->duration();
00852 }
00853 
00854 void RecurrenceRangeDialog::setEndDate( const QDate &date )
00855 {
00856   mRecurrenceRangeWidget->setEndDate( date );
00857 }
00858 
00859 QDate RecurrenceRangeDialog::endDate()
00860 {
00861   return mRecurrenceRangeWidget->endDate();
00862 }
00863 
00864 void RecurrenceRangeDialog::setDateTimes( const QDateTime &start,
00865                                           const QDateTime &end )
00866 {
00867   mRecurrenceRangeWidget->setDateTimes( start, end );
00868 }
00869 
00871 
00872 RecurrenceChooser::RecurrenceChooser( QWidget *parent, const char *name ) :
00873   QWidget( parent, name )
00874 {
00875   QBoxLayout *topLayout = new QVBoxLayout( this );
00876 
00877   if ( KOPrefs::instance()->mCompactDialogs ) {
00878     mTypeCombo = new QComboBox( this );
00879     QWhatsThis::add( mTypeCombo,
00880                      i18n("Sets the type of recurrence this event or to-do "
00881                           "should have.") );
00882     mTypeCombo->insertItem( i18n("Daily") );
00883     mTypeCombo->insertItem( i18n("Weekly") );
00884     mTypeCombo->insertItem( i18n("Monthly") );
00885     mTypeCombo->insertItem( i18n("Yearly") );
00886 
00887     topLayout->addWidget( mTypeCombo );
00888 
00889     connect( mTypeCombo, SIGNAL( activated( int ) ), SLOT( emitChoice() ) );
00890   } else {
00891     mTypeCombo = 0;
00892 
00893     QButtonGroup *ruleButtonGroup = new QButtonGroup( 1, Horizontal, this );
00894     ruleButtonGroup->setFrameStyle( QFrame::NoFrame );
00895     topLayout->addWidget( ruleButtonGroup );
00896 
00897     mDailyButton = new QRadioButton( i18n("&Daily"), ruleButtonGroup );
00898     QWhatsThis::add( mDailyButton,
00899                      i18n("Sets the event or to-do to recur daily according "
00900                           "to the specified rules.") );
00901     mWeeklyButton = new QRadioButton( i18n("&Weekly"), ruleButtonGroup );
00902     QWhatsThis::add( mWeeklyButton,
00903                      i18n("Sets the event or to-do to recur weekly according "
00904                           "to the specified rules.") );
00905     mMonthlyButton = new QRadioButton( i18n("&Monthly"), ruleButtonGroup );
00906     QWhatsThis::add( mMonthlyButton,
00907                      i18n("Sets the event or to-do to recur monthly according "
00908                           "to the specified rules.") );
00909     mYearlyButton = new QRadioButton( i18n("&Yearly"), ruleButtonGroup );
00910     QWhatsThis::add( mYearlyButton,
00911                      i18n("Sets the event or to-do to recur yearly according "
00912                           "to the specified rules.") );
00913 
00914     connect( mDailyButton, SIGNAL( toggled( bool ) ),
00915              SLOT( emitChoice() ) );
00916     connect( mWeeklyButton, SIGNAL( toggled( bool ) ),
00917              SLOT( emitChoice() ) );
00918     connect( mMonthlyButton, SIGNAL( toggled( bool ) ),
00919              SLOT( emitChoice() ) );
00920     connect( mYearlyButton, SIGNAL( toggled( bool ) ),
00921              SLOT( emitChoice() ) );
00922   }
00923 }
00924 
00925 int RecurrenceChooser::type()
00926 {
00927   if ( mTypeCombo ) {
00928     return mTypeCombo->currentItem();
00929   } else {
00930     if ( mDailyButton->isChecked() ) return Daily;
00931     else if ( mWeeklyButton->isChecked() ) return Weekly;
00932     else if ( mMonthlyButton->isChecked() ) return Monthly;
00933     else return Yearly;
00934   }
00935 }
00936 
00937 void RecurrenceChooser::setType( int type )
00938 {
00939   if ( mTypeCombo ) {
00940     mTypeCombo->setCurrentItem( type );
00941   } else {
00942     switch ( type ) {
00943       case Daily:
00944         mDailyButton->setChecked( true );
00945         break;
00946       case Weekly:
00947         mWeeklyButton->setChecked( true );
00948         break;
00949       case Monthly:
00950         mMonthlyButton->setChecked( true );
00951         break;
00952       case Yearly:
00953       default:
00954         mYearlyButton->setChecked( true );
00955         break;
00956     }
00957   }
00958 }
00959 
00960 void RecurrenceChooser::emitChoice()
00961 {
00962   emit chosen ( type() );
00963 }
00964 
00966 
00967 KOEditorRecurrence::KOEditorRecurrence( QWidget* parent, const char *name ) :
00968   QWidget( parent, name )
00969 {
00970   QGridLayout *topLayout = new QGridLayout( this );
00971   topLayout->setSpacing( KDialog::spacingHint() );
00972 
00973   mEnabledCheck = new QCheckBox( i18n("&Enable recurrence"), this );
00974   QWhatsThis::add( mEnabledCheck,
00975                    i18n("Enables recurrence for this event or to-do according "
00976                         "to the specified rules.") );
00977   connect( mEnabledCheck, SIGNAL( toggled( bool ) ),
00978            SLOT( setRecurrenceEnabled( bool ) ) );
00979   topLayout->addMultiCellWidget( mEnabledCheck, 0, 0, 0, 1 );
00980 
00981 
00982   mTimeGroupBox = new QGroupBox( 1, Horizontal, i18n("Appointment Time "),
00983                                  this );
00984   QWhatsThis::add( mTimeGroupBox,
00985                    i18n("Displays appointment time information.") );
00986   topLayout->addMultiCellWidget( mTimeGroupBox, 1, 1 , 0 , 1 );
00987 
00988   if ( KOPrefs::instance()->mCompactDialogs ) {
00989     mTimeGroupBox->hide();
00990   }
00991 
00992 //  QFrame *timeFrame = new QFrame( mTimeGroupBox );
00993 //  QBoxLayout *layoutTimeFrame = new QHBoxLayout( timeFrame );
00994 //  layoutTimeFrame->setSpacing( KDialog::spacingHint() );
00995 
00996   mDateTimeLabel = new QLabel( mTimeGroupBox );
00997 //  mDateTimeLabel = new QLabel( timeFrame );
00998 //  layoutTimeFrame->addWidget( mDateTimeLabel );
00999 
01000   Qt::Orientation orientation;
01001   if ( KOPrefs::instance()->mCompactDialogs ) orientation = Horizontal;
01002   else orientation = Vertical;
01003 
01004   mRuleBox = new QGroupBox( 1, orientation, i18n("Recurrence Rule"), this );
01005   QWhatsThis::add( mRuleBox,
01006                    i18n("Options concerning the type of recurrence this event "
01007                         "or to-do should have.") );
01008   if ( KOPrefs::instance()->mCompactDialogs ) {
01009     topLayout->addWidget( mRuleBox, 2, 0 );
01010   } else {
01011     topLayout->addMultiCellWidget( mRuleBox, 2, 2, 0, 1 );
01012   }
01013 
01014   mRecurrenceChooser = new RecurrenceChooser( mRuleBox );
01015   connect( mRecurrenceChooser, SIGNAL( chosen( int ) ),
01016            SLOT( showCurrentRule( int ) ) );
01017 
01018   if ( !KOPrefs::instance()->mCompactDialogs ) {
01019     QFrame *ruleSepFrame = new QFrame( mRuleBox );
01020     ruleSepFrame->setFrameStyle( QFrame::VLine | QFrame::Sunken );
01021   }
01022 
01023   mRuleStack = new QWidgetStack( mRuleBox );
01024 
01025   mDaily = new RecurDaily( mRuleStack );
01026   mRuleStack->addWidget( mDaily, 0 );
01027 
01028   mWeekly = new RecurWeekly( mRuleStack );
01029   mRuleStack->addWidget( mWeekly, 0 );
01030 
01031   mMonthly = new RecurMonthly( mRuleStack );
01032   mRuleStack->addWidget( mMonthly, 0 );
01033 
01034   mYearly = new RecurYearly( mRuleStack );
01035   mRuleStack->addWidget( mYearly, 0 );
01036 
01037   showCurrentRule( mRecurrenceChooser->type() );
01038 
01039   if ( KOPrefs::instance()->mCompactDialogs ) {
01040     mRecurrenceRangeWidget = 0;
01041     mRecurrenceRangeDialog = new RecurrenceRangeDialog( this );
01042     mRecurrenceRange = mRecurrenceRangeDialog;
01043     mRecurrenceRangeButton = new QPushButton( i18n("Recurrence Range..."),
01044                                               this );
01045     QWhatsThis::add( mRecurrenceRangeButton,
01046                      i18n("Options concerning the time range during which "
01047                           "this event or to-do should recur.") );
01048     topLayout->addWidget( mRecurrenceRangeButton, 3, 0 );
01049     connect( mRecurrenceRangeButton, SIGNAL( clicked() ),
01050              SLOT( showRecurrenceRangeDialog() ) );
01051 
01052     mExceptionsWidget = 0;
01053     mExceptionsDialog = new ExceptionsDialog( this );
01054     mExceptions = mExceptionsDialog;
01055     mExceptionsButton = new QPushButton( i18n("Exceptions..."), this );
01056     topLayout->addWidget( mExceptionsButton, 4, 0 );
01057     connect( mExceptionsButton, SIGNAL( clicked() ),
01058              SLOT( showExceptionsDialog() ) );
01059 
01060   } else {
01061     mRecurrenceRangeWidget = new RecurrenceRangeWidget( this );
01062     QWhatsThis::add( mRecurrenceRangeWidget,
01063                      i18n("Options concerning the time range during which "
01064                           "this event or to-do should recur.") );
01065     mRecurrenceRangeDialog = 0;
01066     mRecurrenceRange = mRecurrenceRangeWidget;
01067     mRecurrenceRangeButton = 0;
01068     topLayout->addWidget( mRecurrenceRangeWidget, 3, 0 );
01069 
01070     mExceptionsWidget = new ExceptionsWidget( this );
01071     mExceptionsDialog = 0;
01072     mExceptions = mExceptionsWidget;
01073     mExceptionsButton = 0;
01074     topLayout->addWidget( mExceptionsWidget, 3, 1 );
01075   }
01076 }
01077 
01078 KOEditorRecurrence::~KOEditorRecurrence()
01079 {
01080 }
01081 
01082 void KOEditorRecurrence::setRecurrenceEnabled( bool enabled )
01083 {
01084 //  kdDebug(5850) << "KOEditorRecurrence::setRecurrenceEnabled(): " << (enabled ? "on" : "off") << endl;
01085 
01086   mTimeGroupBox->setEnabled( enabled );
01087   mRuleBox->setEnabled( enabled );
01088   if ( mRecurrenceRangeWidget ) mRecurrenceRangeWidget->setEnabled( enabled );
01089   if ( mRecurrenceRangeButton ) mRecurrenceRangeButton->setEnabled( enabled );
01090   if ( mExceptionsWidget ) mExceptionsWidget->setEnabled( enabled );
01091   if ( mExceptionsButton ) mExceptionsButton->setEnabled( enabled );
01092 }
01093 
01094 void KOEditorRecurrence::showCurrentRule( int current )
01095 {
01096   switch ( current ) {
01097     case Daily:
01098       mRuleStack->raiseWidget( mDaily );
01099       break;
01100     case Weekly:
01101       mRuleStack->raiseWidget( mWeekly );
01102       break;
01103     case Monthly:
01104       mRuleStack->raiseWidget( mMonthly );
01105       break;
01106     default:
01107     case Yearly:
01108       mRuleStack->raiseWidget( mYearly );
01109       break;
01110   }
01111 }
01112 
01113 void KOEditorRecurrence::setDateTimes( const QDateTime &start, const QDateTime &end )
01114 {
01115 //  kdDebug(5850) << "KOEditorRecurrence::setDateTimes" << endl;
01116 
01117   mEventStartDt = start;
01118   mRecurrenceRange->setDateTimes( start, end );
01119   mDaily->setDateTimes( start, end );
01120   mWeekly->setDateTimes( start, end );
01121   mMonthly->setDateTimes( start, end );
01122   mYearly->setDateTimes( start, end );
01123   
01124   // Now set the defaults for all unused types, use the start time for it
01125   bool enabled = mEnabledCheck->isChecked();
01126   int type = mRecurrenceChooser->type();
01127   
01128   if ( !enabled || type != RecurrenceChooser::Weekly ) {
01129     QBitArray days( 7 );
01130     days.fill( 0 );
01131     days.setBit( (start.date().dayOfWeek()+6) % 7 );
01132     mWeekly->setDays( days );
01133   } 
01134   if ( !enabled || type != RecurrenceChooser::Monthly ) {
01135     mMonthly->setByPos( ( start.date().day() - 1 ) / 7 + 1, start.date().dayOfWeek() - 1 );
01136     mMonthly->setByDay( start.date().day() );
01137   }
01138   if ( !enabled || type != RecurrenceChooser::Yearly ) {
01139     mYearly->setByDay( start.date().dayOfYear() );
01140     mYearly->setByPos( ( start.date().day() - 1 ) / 7 + 1,
01141         start.date().dayOfWeek() - 1, start.date().month() );
01142     mYearly->setByMonth( start.date().day(), start.date().month() );
01143   }
01144 }
01145 
01146 void KOEditorRecurrence::setDefaults( const QDateTime &from, const QDateTime &to, bool )
01147 {
01148   setDateTimes( from, to );
01149 
01150   bool enabled = false;
01151   mEnabledCheck->setChecked( enabled );
01152   setRecurrenceEnabled( enabled );
01153 
01154   mRecurrenceRange->setDefaults( from );
01155 
01156   mRecurrenceChooser->setType( RecurrenceChooser::Weekly );
01157   showCurrentRule( mRecurrenceChooser->type() );
01158 
01159   mDaily->setFrequency( 1 );
01160 
01161   mWeekly->setFrequency( 1 );
01162   QBitArray days( 7 );
01163   days.fill( 0 );
01164   days.setBit( (from.date().dayOfWeek()+6) % 7 );
01165   mWeekly->setDays( days );
01166 
01167   mMonthly->setFrequency( 1 );
01168   mMonthly->setByPos( ( from.date().day() - 1 ) / 7 + 1, from.date().dayOfWeek() );
01169   mMonthly->setByDay( from.date().day() );
01170 
01171   mYearly->setFrequency( 1 );
01172   mYearly->setByDay( from.date().dayOfYear() );
01173   mYearly->setByPos( ( from.date().day() - 1 ) / 7 + 1,
01174       from.date().dayOfWeek(), from.date().month() );
01175   mYearly->setByMonth( from.date().day(), from.date().month() );
01176 }
01177 
01178 void KOEditorRecurrence::readIncidence(Incidence *incidence)
01179 {
01180   if (!incidence) return;
01181 
01182   QBitArray rDays( 7 );
01183   int day = 0;
01184   int count = 0;
01185   int month = 0;
01186 
01187   if ( incidence->type() == "Todo" ) {
01188     Todo *todo = static_cast<Todo *>(incidence);
01189     setDefaults( todo->dtStart(true), todo->dtDue(), todo->doesFloat() );
01190   } else {
01191     setDefaults( incidence->dtStart(), incidence->dtEnd(), incidence->doesFloat() );
01192   }
01193 
01194   uint recurs = incidence->recurrenceType();
01195   int f = 0;
01196   Recurrence *r = 0;
01197 
01198   if ( recurs ) {
01199     r = incidence->recurrence();
01200     f = r->frequency();
01201   }
01202 
01203 
01204   mEnabledCheck->setChecked( recurs );
01205   setRecurrenceEnabled( recurs );
01206 
01207   int recurrenceType = RecurrenceChooser::Weekly;
01208 
01209   switch ( recurs ) {
01210     case Recurrence::rNone:
01211       break;
01212     case Recurrence::rDaily:
01213       recurrenceType = RecurrenceChooser::Daily;
01214       mDaily->setFrequency( f );
01215       break;
01216     case Recurrence::rWeekly:
01217       recurrenceType = RecurrenceChooser::Weekly;
01218       mWeekly->setFrequency( f );
01219       mWeekly->setDays( r->days() );
01220       break;
01221     case Recurrence::rMonthlyPos: {
01222       // TODO: we only handle one possibility in the list right now,
01223       // so I have hardcoded calls with first().  If we make the GUI
01224       // more extended, this can be changed.
01225       recurrenceType = RecurrenceChooser::Monthly;
01226 
01227       QValueList<RecurrenceRule::WDayPos> rmp = r->monthPositions();
01228       if ( !rmp.isEmpty() ) {
01229         mMonthly->setByPos( rmp.first().pos(), rmp.first().day() );
01230       }
01231 
01232       mMonthly->setFrequency( f );
01233 
01234       break; }
01235     case Recurrence::rMonthlyDay: {
01236       recurrenceType = RecurrenceChooser::Monthly;
01237 
01238       QValueList<int> rmd = r->monthDays();
01239       // check if we have any setting for which day (vcs import is broken and
01240       // does not set any day, thus we need to check)
01241       if ( rmd.isEmpty() ) {
01242         day = incidence->dtStart().date().day();
01243       } else {
01244         day = rmd.first();
01245       }
01246       mMonthly->setByDay( day );
01247 
01248       mMonthly->setFrequency( f );
01249 
01250       break; }
01251     case Recurrence::rYearlyMonth: {
01252       recurrenceType = RecurrenceChooser::Yearly;
01253       QValueList<int> rmd = r->yearDates();
01254       if ( rmd.isEmpty() ) {
01255         day = incidence->dtStart().date().day();
01256       } else {
01257         day = rmd.first();
01258       }
01259       int month = incidence->dtStart().date().month();
01260       rmd = r->yearMonths();
01261       if ( !rmd.isEmpty() )
01262         month = rmd.first();
01263       mYearly->setByMonth( day, month );
01264       mYearly->setFrequency( f );
01265       break; }
01266     case Recurrence::rYearlyPos: {
01267       recurrenceType = RecurrenceChooser::Yearly;
01268 
01269       QValueList<int> months = r->yearMonths();
01270       if ( months.isEmpty() ) {
01271         month = incidence->dtStart().date().month();
01272       } else {
01273         month = months.first();
01274       }
01275 
01276       QValueList<RecurrenceRule::WDayPos> pos = r->yearPositions();
01277 
01278       if ( pos.isEmpty() ) {
01279         // Use dtStart if nothing is given (shouldn't happen!)
01280         count = ( incidence->dtStart().date().day() - 1 ) / 7;
01281         day = incidence->dtStart().date().dayOfWeek();
01282       } else {
01283         count = pos.first().pos();
01284         day = pos.first().day();
01285       }
01286       mYearly->setByPos( count, day, month );
01287       mYearly->setFrequency( f );
01288       break; }
01289     case Recurrence::rYearlyDay: {
01290       recurrenceType = RecurrenceChooser::Yearly;
01291       QValueList<int> days = r->yearDays();
01292       if ( days.isEmpty() ) {
01293         day = incidence->dtStart().date().dayOfYear();
01294       } else {
01295         day = days.first();
01296       }
01297       mYearly->setByDay( day );
01298 
01299       mYearly->setFrequency( f );
01300       break; }
01301     default:
01302       break;
01303   }
01304 
01305   mRecurrenceChooser->setType( recurrenceType );
01306   showCurrentRule( recurrenceType );
01307 
01308   mRecurrenceRange->setDateTimes( incidence->recurrence()->startDateTime() );
01309 
01310   if ( incidence->doesRecur() ) {
01311     mRecurrenceRange->setDuration( r->duration() );
01312     if ( r->duration() == 0 ) mRecurrenceRange->setEndDate( r->endDate() );
01313   }
01314 
01315   mExceptions->setDates( incidence->recurrence()->exDates() );
01316 }
01317 
01318 void KOEditorRecurrence::writeIncidence( Incidence *incidence )
01319 {
01320   if ( !mEnabledCheck->isChecked() || !isEnabled() )
01321   {
01322     if ( incidence->doesRecur() )
01323       incidence->recurrence()->unsetRecurs();
01324     return;
01325   }
01326 
01327   Recurrence *r = incidence->recurrence();
01328 
01329   // clear out any old settings;
01330   r->unsetRecurs();
01331 
01332   int duration = mRecurrenceRange->duration();
01333   QDate endDate;
01334   if ( duration == 0 ) endDate = mRecurrenceRange->endDate();
01335 
01336   int recurrenceType = mRecurrenceChooser->type();
01337   if ( recurrenceType == RecurrenceChooser::Daily ) {
01338     r->setDaily( mDaily->frequency() );
01339   } else if ( recurrenceType == RecurrenceChooser::Weekly ) {
01340     r->setWeekly( mWeekly->frequency(), mWeekly->days() );
01341   } else if ( recurrenceType == RecurrenceChooser::Monthly ) {
01342     r->setMonthly( mMonthly->frequency() );
01343     
01344     if ( mMonthly->byPos() ) {
01345       int pos = mMonthly->count();
01346 
01347       QBitArray days( 7 );
01348       days.fill( false );
01349       days.setBit( mMonthly->weekday() - 1 );
01350       r->addMonthlyPos( pos, days );
01351     } else {
01352       // it's by day
01353       r->addMonthlyDate( mMonthly->day() );
01354     }
01355   } else if ( recurrenceType == RecurrenceChooser::Yearly ) {
01356     r->setYearly( mYearly->frequency() );
01357 
01358     switch ( mYearly->getType() ) {
01359       case RecurYearly::byMonth:
01360         r->addYearlyDate( mYearly->monthDay() );
01361         r->addYearlyMonth( mYearly->month() );
01362         break;
01363       case RecurYearly::byPos:  {
01364         r->addYearlyMonth( mYearly->posMonth() );
01365         QBitArray days( 7 );
01366         days.fill( false );
01367         days.setBit( mYearly->posWeekday() - 1 );
01368         r->addYearlyPos( mYearly->posCount(), days );
01369         break; }
01370       case RecurYearly::byDay:
01371         r->addYearlyDay( mYearly->day() );
01372         break;
01373     }
01374   } // end "Yearly"
01375 
01376   if ( duration > 0 ) 
01377     r->setDuration( duration );
01378   else if ( duration == 0 )
01379     r->setEndDate( endDate );
01380   incidence->recurrence()->setExDates( mExceptions->dates() );
01381 }
01382 
01383 void KOEditorRecurrence::setDateTimeStr( const QString &str )
01384 {
01385   mDateTimeLabel->setText( str );
01386 }
01387 
01388 bool KOEditorRecurrence::validateInput()
01389 {
01390   // Check input here.
01391   // Check if the recurrence (if set to end at a date) is scheduled to end before the event starts.
01392   if ( mEnabledCheck->isChecked() && (mRecurrenceRange->duration()==0) &&
01393        mEventStartDt.isValid() && ((mRecurrenceRange->endDate())<mEventStartDt.date()) ) {
01394     KMessageBox::sorry( 0,
01395       i18n("The end date '%1' of the recurrence must be after the start date '%2' of the event.")
01396       .arg( KGlobal::locale()->formatDate( mRecurrenceRange->endDate() ) )
01397       .arg( KGlobal::locale()->formatDate( mEventStartDt.date() ) ) );
01398     return false;
01399   }
01400   int recurrenceType = mRecurrenceChooser->type();
01401   // Check if a weekly recurrence has at least one day selected
01402   // TODO: Get rid of this, it's not really needed (by default the day should be taken from dtStart)
01403   if( mEnabledCheck->isChecked() && recurrenceType == RecurrenceChooser::Weekly ) {
01404     const QBitArray &days = mWeekly->days();
01405     bool valid = false;
01406     for ( int i=0; i<7; ++i ) valid = valid || days.testBit( i );
01407     if ( !valid ) {
01408       KMessageBox::sorry( 0,
01409         i18n("A weekly recurring event or task has to have at least one weekday "
01410              "associated with it.") );
01411       return false;
01412     }
01413   }
01414   return true;
01415 }
01416 
01417 void KOEditorRecurrence::showExceptionsDialog()
01418 {
01419   DateList dates = mExceptions->dates();
01420   int result = mExceptionsDialog->exec();
01421   if ( result == QDialog::Rejected ) mExceptions->setDates( dates );
01422 }
01423 
01424 void KOEditorRecurrence::showRecurrenceRangeDialog()
01425 {
01426   int duration = mRecurrenceRange->duration();
01427   QDate endDate = mRecurrenceRange->endDate();
01428 
01429   int result = mRecurrenceRangeDialog->exec();
01430   if ( result == QDialog::Rejected ) {
01431     mRecurrenceRange->setDuration( duration );
01432     mRecurrenceRange->setEndDate( endDate );
01433   }
01434 }
01435 
01436 bool KOEditorRecurrence::doesRecur()
01437 {
01438   return mEnabledCheck->isChecked();
01439 }
KDE Home | KDE Accessibility Home | Description of Access Keys