00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
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
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
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
00186 int weekStart=KGlobal::locale()->weekStartDay();
00187 for ( int i = 0; i < 7; ++i ) {
00188
00189
00190
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
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322
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
00347
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
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)
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
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
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
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
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 )
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(
00597 i18n( "Add a new recurrence to the recurrence list", "&Add" ), box );
00598 QWhatsThis::add( addExceptionButton,
00599 i18n("Add this date as an exception "
00600 "to the recurrence rules for this event or to-do.") );
00601 boxLayout->addWidget( addExceptionButton, 1, 0 );
00602 QPushButton *changeExceptionButton = new QPushButton( i18n("&Change"), box );
00603 QWhatsThis::add( changeExceptionButton,
00604 i18n("Replace the currently selected date with this date.") );
00605 boxLayout->addWidget( changeExceptionButton, 2, 0 );
00606 QPushButton *deleteExceptionButton = new QPushButton( i18n("&Delete"), box );
00607 QWhatsThis::add( deleteExceptionButton,
00608 i18n("Delete the currently selected date from the list of dates "
00609 "that should be considered exceptions to the recurrence rules "
00610 "for this event or to-do.") );
00611 boxLayout->addWidget( deleteExceptionButton, 3, 0 );
00612
00613 mExceptionList = new QListBox( box );
00614 QWhatsThis::add( mExceptionList,
00615 i18n("Displays current dates that are being considered "
00616 "exceptions to the recurrence rules for this event "
00617 "or to-do.") );
00618 boxLayout->addMultiCellWidget( mExceptionList, 0, 3, 1, 1 );
00619
00620 boxLayout->setRowStretch( 4, 1 );
00621 boxLayout->setColStretch( 1, 3 );
00622
00623 connect( addExceptionButton, SIGNAL( clicked() ),
00624 SLOT( addException() ) );
00625 connect( changeExceptionButton, SIGNAL( clicked() ),
00626 SLOT( changeException() ) );
00627 connect( deleteExceptionButton, SIGNAL( clicked() ),
00628 SLOT( deleteException() ) );
00629 }
00630
00631 void ExceptionsWidget::addException()
00632 {
00633 QDate date = mExceptionDateEdit->date();
00634 QString dateStr = KGlobal::locale()->formatDate( date );
00635 if( !mExceptionList->findItem( dateStr ) ) {
00636 mExceptionDates.append( date );
00637 mExceptionList->insertItem( dateStr );
00638 }
00639 }
00640
00641 void ExceptionsWidget::changeException()
00642 {
00643 int pos = mExceptionList->currentItem();
00644 if ( pos < 0 ) return;
00645
00646 QDate date = mExceptionDateEdit->date();
00647 mExceptionDates[ pos ] = date;
00648 mExceptionList->changeItem( KGlobal::locale()->formatDate( date ), pos );
00649 }
00650
00651 void ExceptionsWidget::deleteException()
00652 {
00653 int pos = mExceptionList->currentItem();
00654 if ( pos < 0 ) return;
00655
00656 mExceptionDates.remove( mExceptionDates.at( pos ) );
00657 mExceptionList->removeItem( pos );
00658 }
00659
00660 void ExceptionsWidget::setDates( const DateList &dates )
00661 {
00662 mExceptionList->clear();
00663 mExceptionDates.clear();
00664 DateList::ConstIterator dit;
00665 for ( dit = dates.begin(); dit != dates.end(); ++dit ) {
00666 mExceptionList->insertItem( KGlobal::locale()->formatDate(* dit ) );
00667 mExceptionDates.append( *dit );
00668 }
00669 }
00670
00671 DateList ExceptionsWidget::dates()
00672 {
00673 return mExceptionDates;
00674 }
00675
00677
00678 ExceptionsDialog::ExceptionsDialog( QWidget *parent, const char *name ) :
00679 KDialogBase( parent, name, true, i18n("Edit Exceptions"), Ok|Cancel )
00680 {
00681 mExceptions = new ExceptionsWidget( this );
00682 setMainWidget( mExceptions );
00683 }
00684
00685 void ExceptionsDialog::setDates( const DateList &dates )
00686 {
00687 mExceptions->setDates( dates );
00688 }
00689
00690 DateList ExceptionsDialog::dates()
00691 {
00692 return mExceptions->dates();
00693 }
00694
00696
00697 RecurrenceRangeWidget::RecurrenceRangeWidget( QWidget *parent,
00698 const char *name )
00699 : QWidget( parent, name )
00700 {
00701 QBoxLayout *topLayout = new QVBoxLayout( this );
00702
00703 mRangeGroupBox = new QGroupBox( 1, Horizontal, i18n("Recurrence Range"),
00704 this );
00705 QWhatsThis::add( mRangeGroupBox,
00706 i18n("Sets a range for which these recurrence rules will "
00707 "apply to this event or to-do.") );
00708 topLayout->addWidget( mRangeGroupBox );
00709
00710 QWidget *rangeBox = new QWidget( mRangeGroupBox );
00711 QVBoxLayout *rangeLayout = new QVBoxLayout( rangeBox );
00712 rangeLayout->setSpacing( KDialog::spacingHint() );
00713
00714 mStartDateLabel = new QLabel( i18n("Begin on:"), rangeBox );
00715 QWhatsThis::add( mStartDateLabel,
00716 i18n("The date on which the recurrences for this event or to-do "
00717 "should begin.") );
00718 rangeLayout->addWidget( mStartDateLabel );
00719
00720 QButtonGroup *rangeButtonGroup = new QButtonGroup( this );
00721 rangeButtonGroup->hide();
00722
00723 mNoEndDateButton = new QRadioButton( i18n("&No ending date"), rangeBox );
00724 QWhatsThis::add( mNoEndDateButton,
00725 i18n("Sets the event or to-do to recur forever.") );
00726 rangeButtonGroup->insert( mNoEndDateButton );
00727 rangeLayout->addWidget( mNoEndDateButton );
00728
00729 QBoxLayout *durationLayout = new QHBoxLayout( rangeLayout );
00730 durationLayout->setSpacing( KDialog::spacingHint() );
00731
00732 mEndDurationButton = new QRadioButton( i18n("End &after"), rangeBox );
00733 QWhatsThis::add( mEndDurationButton,
00734 i18n("Sets the event or to-do to stop recurring after a "
00735 "certain number of occurrences.") );
00736 rangeButtonGroup->insert( mEndDurationButton );
00737 durationLayout->addWidget( mEndDurationButton );
00738
00739 QString whatsThis = i18n("Number of times the event or to-do should recur "
00740 "before stopping.");
00741 mEndDurationEdit = new QSpinBox( 1, 9999, 1, rangeBox );
00742 QWhatsThis::add( mEndDurationEdit, whatsThis );
00743 durationLayout->addWidget( mEndDurationEdit );
00744
00745 QLabel *endDurationLabel = new QLabel( i18n("&occurrence(s)"), rangeBox );
00746 QWhatsThis::add( endDurationLabel, whatsThis );
00747 durationLayout ->addWidget( endDurationLabel );
00748 endDurationLabel->setBuddy( mEndDurationEdit );
00749
00750 QBoxLayout *endDateLayout = new QHBoxLayout( rangeLayout );
00751 endDateLayout->setSpacing( KDialog::spacingHint() );
00752
00753 mEndDateButton = new QRadioButton( i18n("End &on:"), rangeBox );
00754 QWhatsThis::add( mEndDateButton,
00755 i18n("Sets the event or to-do to stop recurring on "
00756 "a certain date.") );
00757 rangeButtonGroup->insert( mEndDateButton );
00758 endDateLayout->addWidget( mEndDateButton );
00759
00760 mEndDateEdit = new KDateEdit( rangeBox );
00761 QWhatsThis::add( mEndDateEdit,
00762 i18n("Date after which the event or to-do should stop "
00763 "recurring") );
00764 endDateLayout->addWidget( mEndDateEdit );
00765
00766 endDateLayout->addStretch( 1 );
00767
00768 connect( mNoEndDateButton, SIGNAL( toggled( bool ) ),
00769 SLOT( showCurrentRange() ) );
00770 connect( mEndDurationButton, SIGNAL( toggled( bool ) ),
00771 SLOT( showCurrentRange() ) );
00772 connect( mEndDateButton, SIGNAL( toggled( bool ) ),
00773 SLOT( showCurrentRange() ) );
00774 }
00775
00776 void RecurrenceRangeWidget::setDefaults( const QDateTime &from )
00777 {
00778 mNoEndDateButton->setChecked( true );
00779
00780 setDateTimes( from );
00781 setEndDate( from.date() );
00782 }
00783
00784 void RecurrenceRangeWidget::setDuration( int duration )
00785 {
00786 if ( duration == -1 ) {
00787 mNoEndDateButton->setChecked( true );
00788 } else if ( duration == 0 ) {
00789 mEndDateButton->setChecked( true );
00790 } else {
00791 mEndDurationButton->setChecked( true );
00792 mEndDurationEdit->setValue( duration );
00793 }
00794 }
00795
00796 int RecurrenceRangeWidget::duration()
00797 {
00798 if ( mNoEndDateButton->isChecked() ) {
00799 return -1;
00800 } else if ( mEndDurationButton->isChecked() ) {
00801 return mEndDurationEdit->value();
00802 } else {
00803 return 0;
00804 }
00805 }
00806
00807 void RecurrenceRangeWidget::setEndDate( const QDate &date )
00808 {
00809 mEndDateEdit->setDate( date );
00810 }
00811
00812 QDate RecurrenceRangeWidget::endDate()
00813 {
00814 return mEndDateEdit->date();
00815 }
00816
00817 void RecurrenceRangeWidget::showCurrentRange()
00818 {
00819 mEndDurationEdit->setEnabled( mEndDurationButton->isChecked() );
00820 mEndDateEdit->setEnabled( mEndDateButton->isChecked() );
00821 }
00822
00823 void RecurrenceRangeWidget::setDateTimes( const QDateTime &start,
00824 const QDateTime & )
00825 {
00826 mStartDateLabel->setText( i18n("Begins on: %1")
00827 .arg( KGlobal::locale()->formatDate( start.date() ) ) );
00828 }
00829
00831
00832 RecurrenceRangeDialog::RecurrenceRangeDialog( QWidget *parent,
00833 const char *name ) :
00834 KDialogBase( parent, name, true, i18n("Edit Recurrence Range"), Ok|Cancel )
00835 {
00836 mRecurrenceRangeWidget = new RecurrenceRangeWidget( this );
00837 setMainWidget( mRecurrenceRangeWidget );
00838 }
00839
00840 void RecurrenceRangeDialog::setDefaults( const QDateTime &from )
00841 {
00842 mRecurrenceRangeWidget->setDefaults( from );
00843 }
00844
00845 void RecurrenceRangeDialog::setDuration( int duration )
00846 {
00847 mRecurrenceRangeWidget->setDuration( duration );
00848 }
00849
00850 int RecurrenceRangeDialog::duration()
00851 {
00852 return mRecurrenceRangeWidget->duration();
00853 }
00854
00855 void RecurrenceRangeDialog::setEndDate( const QDate &date )
00856 {
00857 mRecurrenceRangeWidget->setEndDate( date );
00858 }
00859
00860 QDate RecurrenceRangeDialog::endDate()
00861 {
00862 return mRecurrenceRangeWidget->endDate();
00863 }
00864
00865 void RecurrenceRangeDialog::setDateTimes( const QDateTime &start,
00866 const QDateTime &end )
00867 {
00868 mRecurrenceRangeWidget->setDateTimes( start, end );
00869 }
00870
00872
00873 RecurrenceChooser::RecurrenceChooser( QWidget *parent, const char *name ) :
00874 QWidget( parent, name )
00875 {
00876 QBoxLayout *topLayout = new QVBoxLayout( this );
00877
00878 if ( KOPrefs::instance()->mCompactDialogs ) {
00879 mTypeCombo = new QComboBox( this );
00880 QWhatsThis::add( mTypeCombo,
00881 i18n("Sets the type of recurrence this event or to-do "
00882 "should have.") );
00883 mTypeCombo->insertItem( i18n("Daily") );
00884 mTypeCombo->insertItem( i18n("Weekly") );
00885 mTypeCombo->insertItem( i18n("Monthly") );
00886 mTypeCombo->insertItem( i18n("Yearly") );
00887
00888 topLayout->addWidget( mTypeCombo );
00889
00890 connect( mTypeCombo, SIGNAL( activated( int ) ), SLOT( emitChoice() ) );
00891 } else {
00892 mTypeCombo = 0;
00893
00894 QButtonGroup *ruleButtonGroup = new QButtonGroup( 1, Horizontal, this );
00895 ruleButtonGroup->setFrameStyle( QFrame::NoFrame );
00896 topLayout->addWidget( ruleButtonGroup );
00897
00898 mDailyButton = new QRadioButton( i18n("&Daily"), ruleButtonGroup );
00899 QWhatsThis::add( mDailyButton,
00900 i18n("Sets the event or to-do to recur daily according "
00901 "to the specified rules.") );
00902 mWeeklyButton = new QRadioButton( i18n("&Weekly"), ruleButtonGroup );
00903 QWhatsThis::add( mWeeklyButton,
00904 i18n("Sets the event or to-do to recur weekly according "
00905 "to the specified rules.") );
00906 mMonthlyButton = new QRadioButton( i18n("&Monthly"), ruleButtonGroup );
00907 QWhatsThis::add( mMonthlyButton,
00908 i18n("Sets the event or to-do to recur monthly according "
00909 "to the specified rules.") );
00910 mYearlyButton = new QRadioButton( i18n("&Yearly"), ruleButtonGroup );
00911 QWhatsThis::add( mYearlyButton,
00912 i18n("Sets the event or to-do to recur yearly according "
00913 "to the specified rules.") );
00914
00915 connect( mDailyButton, SIGNAL( toggled( bool ) ),
00916 SLOT( emitChoice() ) );
00917 connect( mWeeklyButton, SIGNAL( toggled( bool ) ),
00918 SLOT( emitChoice() ) );
00919 connect( mMonthlyButton, SIGNAL( toggled( bool ) ),
00920 SLOT( emitChoice() ) );
00921 connect( mYearlyButton, SIGNAL( toggled( bool ) ),
00922 SLOT( emitChoice() ) );
00923 }
00924 }
00925
00926 int RecurrenceChooser::type()
00927 {
00928 if ( mTypeCombo ) {
00929 return mTypeCombo->currentItem();
00930 } else {
00931 if ( mDailyButton->isChecked() ) return Daily;
00932 else if ( mWeeklyButton->isChecked() ) return Weekly;
00933 else if ( mMonthlyButton->isChecked() ) return Monthly;
00934 else return Yearly;
00935 }
00936 }
00937
00938 void RecurrenceChooser::setType( int type )
00939 {
00940 if ( mTypeCombo ) {
00941 mTypeCombo->setCurrentItem( type );
00942 } else {
00943 switch ( type ) {
00944 case Daily:
00945 mDailyButton->setChecked( true );
00946 break;
00947 case Weekly:
00948 mWeeklyButton->setChecked( true );
00949 break;
00950 case Monthly:
00951 mMonthlyButton->setChecked( true );
00952 break;
00953 case Yearly:
00954 default:
00955 mYearlyButton->setChecked( true );
00956 break;
00957 }
00958 }
00959 }
00960
00961 void RecurrenceChooser::emitChoice()
00962 {
00963 emit chosen ( type() );
00964 }
00965
00967
00968 KOEditorRecurrence::KOEditorRecurrence( QWidget* parent, const char *name ) :
00969 QWidget( parent, name )
00970 {
00971 QGridLayout *topLayout = new QGridLayout( this );
00972 topLayout->setSpacing( KDialog::spacingHint() );
00973
00974 mEnabledCheck = new QCheckBox( i18n("&Enable recurrence"), this );
00975 QWhatsThis::add( mEnabledCheck,
00976 i18n("Enables recurrence for this event or to-do according "
00977 "to the specified rules.") );
00978 connect( mEnabledCheck, SIGNAL( toggled( bool ) ),
00979 SLOT( setRecurrenceEnabled( bool ) ) );
00980 topLayout->addMultiCellWidget( mEnabledCheck, 0, 0, 0, 1 );
00981
00982
00983 mTimeGroupBox = new QGroupBox( 1, Horizontal, i18n("Appointment Time "),
00984 this );
00985 QWhatsThis::add( mTimeGroupBox,
00986 i18n("Displays appointment time information.") );
00987 topLayout->addMultiCellWidget( mTimeGroupBox, 1, 1 , 0 , 1 );
00988
00989 if ( KOPrefs::instance()->mCompactDialogs ) {
00990 mTimeGroupBox->hide();
00991 }
00992
00993
00994
00995
00996
00997 mDateTimeLabel = new QLabel( mTimeGroupBox );
00998
00999
01000
01001 Qt::Orientation orientation;
01002 if ( KOPrefs::instance()->mCompactDialogs ) orientation = Horizontal;
01003 else orientation = Vertical;
01004
01005 mRuleBox = new QGroupBox( 1, orientation, i18n("Recurrence Rule"), this );
01006 QWhatsThis::add( mRuleBox,
01007 i18n("Options concerning the type of recurrence this event "
01008 "or to-do should have.") );
01009 if ( KOPrefs::instance()->mCompactDialogs ) {
01010 topLayout->addWidget( mRuleBox, 2, 0 );
01011 } else {
01012 topLayout->addMultiCellWidget( mRuleBox, 2, 2, 0, 1 );
01013 }
01014
01015 mRecurrenceChooser = new RecurrenceChooser( mRuleBox );
01016 connect( mRecurrenceChooser, SIGNAL( chosen( int ) ),
01017 SLOT( showCurrentRule( int ) ) );
01018
01019 if ( !KOPrefs::instance()->mCompactDialogs ) {
01020 QFrame *ruleSepFrame = new QFrame( mRuleBox );
01021 ruleSepFrame->setFrameStyle( QFrame::VLine | QFrame::Sunken );
01022 }
01023
01024 mRuleStack = new QWidgetStack( mRuleBox );
01025
01026 mDaily = new RecurDaily( mRuleStack );
01027 mRuleStack->addWidget( mDaily, 0 );
01028
01029 mWeekly = new RecurWeekly( mRuleStack );
01030 mRuleStack->addWidget( mWeekly, 0 );
01031
01032 mMonthly = new RecurMonthly( mRuleStack );
01033 mRuleStack->addWidget( mMonthly, 0 );
01034
01035 mYearly = new RecurYearly( mRuleStack );
01036 mRuleStack->addWidget( mYearly, 0 );
01037
01038 showCurrentRule( mRecurrenceChooser->type() );
01039
01040 if ( KOPrefs::instance()->mCompactDialogs ) {
01041 mRecurrenceRangeWidget = 0;
01042 mRecurrenceRangeDialog = new RecurrenceRangeDialog( this );
01043 mRecurrenceRange = mRecurrenceRangeDialog;
01044 mRecurrenceRangeButton = new QPushButton( i18n("Recurrence Range..."),
01045 this );
01046 QWhatsThis::add( mRecurrenceRangeButton,
01047 i18n("Options concerning the time range during which "
01048 "this event or to-do should recur.") );
01049 topLayout->addWidget( mRecurrenceRangeButton, 3, 0 );
01050 connect( mRecurrenceRangeButton, SIGNAL( clicked() ),
01051 SLOT( showRecurrenceRangeDialog() ) );
01052
01053 mExceptionsWidget = 0;
01054 mExceptionsDialog = new ExceptionsDialog( this );
01055 mExceptions = mExceptionsDialog;
01056 mExceptionsButton = new QPushButton( i18n("Exceptions..."), this );
01057 topLayout->addWidget( mExceptionsButton, 4, 0 );
01058 connect( mExceptionsButton, SIGNAL( clicked() ),
01059 SLOT( showExceptionsDialog() ) );
01060
01061 } else {
01062 mRecurrenceRangeWidget = new RecurrenceRangeWidget( this );
01063 QWhatsThis::add( mRecurrenceRangeWidget,
01064 i18n("Options concerning the time range during which "
01065 "this event or to-do should recur.") );
01066 mRecurrenceRangeDialog = 0;
01067 mRecurrenceRange = mRecurrenceRangeWidget;
01068 mRecurrenceRangeButton = 0;
01069 topLayout->addWidget( mRecurrenceRangeWidget, 3, 0 );
01070
01071 mExceptionsWidget = new ExceptionsWidget( this );
01072 mExceptionsDialog = 0;
01073 mExceptions = mExceptionsWidget;
01074 mExceptionsButton = 0;
01075 topLayout->addWidget( mExceptionsWidget, 3, 1 );
01076 }
01077
01078
01079 mSaveRec.setDuration( -1 );
01080 }
01081
01082 KOEditorRecurrence::~KOEditorRecurrence()
01083 {
01084 }
01085
01086 void KOEditorRecurrence::setRecurrenceEnabled( bool enabled )
01087 {
01088
01089
01090 mEnabledCheck->setChecked( enabled );
01091 mTimeGroupBox->setEnabled( enabled );
01092 mRuleBox->setEnabled( enabled );
01093 if ( mRecurrenceRangeWidget ) mRecurrenceRangeWidget->setEnabled( enabled );
01094 if ( mRecurrenceRangeButton ) mRecurrenceRangeButton->setEnabled( enabled );
01095 if ( mExceptionsWidget ) mExceptionsWidget->setEnabled( enabled );
01096 if ( mExceptionsButton ) mExceptionsButton->setEnabled( enabled );
01097 }
01098
01099 void KOEditorRecurrence::showCurrentRule( int current )
01100 {
01101 switch ( current ) {
01102 case Daily:
01103 mRuleStack->raiseWidget( mDaily );
01104 break;
01105 case Weekly:
01106 mRuleStack->raiseWidget( mWeekly );
01107 break;
01108 case Monthly:
01109 mRuleStack->raiseWidget( mMonthly );
01110 break;
01111 default:
01112 case Yearly:
01113 mRuleStack->raiseWidget( mYearly );
01114 break;
01115 }
01116 }
01117
01118 void KOEditorRecurrence::setDateTimes( const QDateTime &start, const QDateTime &end )
01119 {
01120
01121
01122 mEventStartDt = start;
01123 mRecurrenceRange->setDateTimes( start, end );
01124 mDaily->setDateTimes( start, end );
01125 mWeekly->setDateTimes( start, end );
01126 mMonthly->setDateTimes( start, end );
01127 mYearly->setDateTimes( start, end );
01128
01129
01130 bool enabled = mEnabledCheck->isChecked();
01131 int type = mRecurrenceChooser->type();
01132
01133 if ( !enabled || type != RecurrenceChooser::Weekly ) {
01134 QBitArray days( 7 );
01135 days.fill( 0 );
01136 days.setBit( (start.date().dayOfWeek()+6) % 7 );
01137 mWeekly->setDays( days );
01138 }
01139 if ( !enabled || type != RecurrenceChooser::Monthly ) {
01140 mMonthly->setByPos( ( start.date().day() - 1 ) / 7 + 1, start.date().dayOfWeek() - 1 );
01141 mMonthly->setByDay( start.date().day() );
01142 }
01143 if ( !enabled || type != RecurrenceChooser::Yearly ) {
01144 mYearly->setByDay( start.date().dayOfYear() );
01145 mYearly->setByPos( ( start.date().day() - 1 ) / 7 + 1,
01146 start.date().dayOfWeek() - 1, start.date().month() );
01147 mYearly->setByMonth( start.date().day(), start.date().month() );
01148 }
01149 }
01150
01151 void KOEditorRecurrence::setDefaults( const QDateTime &from, const QDateTime &to, bool )
01152 {
01153 setDateTimes( from, to );
01154
01155 setRecurrenceEnabled( false );
01156
01157 mRecurrenceRange->setDefaults( from );
01158
01159 mRecurrenceChooser->setType( RecurrenceChooser::Weekly );
01160 showCurrentRule( mRecurrenceChooser->type() );
01161
01162 mDaily->setFrequency( 1 );
01163
01164 mWeekly->setFrequency( 1 );
01165 QBitArray days( 7 );
01166 days.fill( 0 );
01167 days.setBit( (from.date().dayOfWeek()+6) % 7 );
01168 mWeekly->setDays( days );
01169
01170 mMonthly->setFrequency( 1 );
01171 mMonthly->setByPos( ( from.date().day() - 1 ) / 7 + 1, from.date().dayOfWeek() );
01172 mMonthly->setByDay( from.date().day() );
01173
01174 mYearly->setFrequency( 1 );
01175 mYearly->setByDay( from.date().dayOfYear() );
01176 mYearly->setByPos( ( from.date().day() - 1 ) / 7 + 1,
01177 from.date().dayOfWeek(), from.date().month() );
01178 mYearly->setByMonth( from.date().day(), from.date().month() );
01179 }
01180
01181 void KOEditorRecurrence::readIncidence(Incidence *incidence)
01182 {
01183 if (!incidence) return;
01184
01185 QBitArray rDays( 7 );
01186 int day = 0;
01187 int count = 0;
01188 int month = 0;
01189
01190 if ( incidence->type() == "Todo" ) {
01191 Todo *todo = static_cast<Todo *>(incidence);
01192 setDefaults( todo->dtStart(true), todo->dtDue(), todo->doesFloat() );
01193 } else {
01194 setDefaults( incidence->dtStart(), incidence->dtEnd(), incidence->doesFloat() );
01195 }
01196
01197 uint recurs = incidence->recurrenceType();
01198 int f = 0;
01199 Recurrence *r = 0;
01200
01201 if ( recurs ) {
01202 r = incidence->recurrence();
01203 f = r->frequency();
01204 }
01205
01206 setRecurrenceEnabled( recurs );
01207
01208 int recurrenceType = RecurrenceChooser::Weekly;
01209
01210 switch ( recurs ) {
01211 case Recurrence::rNone:
01212 break;
01213 case Recurrence::rDaily:
01214 recurrenceType = RecurrenceChooser::Daily;
01215 mDaily->setFrequency( f );
01216 break;
01217 case Recurrence::rWeekly:
01218 recurrenceType = RecurrenceChooser::Weekly;
01219 mWeekly->setFrequency( f );
01220 mWeekly->setDays( r->days() );
01221 break;
01222 case Recurrence::rMonthlyPos: {
01223
01224
01225
01226 recurrenceType = RecurrenceChooser::Monthly;
01227
01228 QValueList<RecurrenceRule::WDayPos> rmp = r->monthPositions();
01229 if ( !rmp.isEmpty() ) {
01230 mMonthly->setByPos( rmp.first().pos(), rmp.first().day() );
01231 }
01232
01233 mMonthly->setFrequency( f );
01234
01235 break; }
01236 case Recurrence::rMonthlyDay: {
01237 recurrenceType = RecurrenceChooser::Monthly;
01238
01239 QValueList<int> rmd = r->monthDays();
01240
01241
01242 if ( rmd.isEmpty() ) {
01243 day = incidence->dtStart().date().day();
01244 } else {
01245 day = rmd.first();
01246 }
01247 mMonthly->setByDay( day );
01248
01249 mMonthly->setFrequency( f );
01250
01251 break; }
01252 case Recurrence::rYearlyMonth: {
01253 recurrenceType = RecurrenceChooser::Yearly;
01254 QValueList<int> rmd = r->yearDates();
01255 if ( rmd.isEmpty() ) {
01256 day = incidence->dtStart().date().day();
01257 } else {
01258 day = rmd.first();
01259 }
01260 int month = incidence->dtStart().date().month();
01261 rmd = r->yearMonths();
01262 if ( !rmd.isEmpty() )
01263 month = rmd.first();
01264 mYearly->setByMonth( day, month );
01265 mYearly->setFrequency( f );
01266 break; }
01267 case Recurrence::rYearlyPos: {
01268 recurrenceType = RecurrenceChooser::Yearly;
01269
01270 QValueList<int> months = r->yearMonths();
01271 if ( months.isEmpty() ) {
01272 month = incidence->dtStart().date().month();
01273 } else {
01274 month = months.first();
01275 }
01276
01277 QValueList<RecurrenceRule::WDayPos> pos = r->yearPositions();
01278
01279 if ( pos.isEmpty() ) {
01280
01281 count = ( incidence->dtStart().date().day() - 1 ) / 7;
01282 day = incidence->dtStart().date().dayOfWeek();
01283 } else {
01284 count = pos.first().pos();
01285 day = pos.first().day();
01286 }
01287 mYearly->setByPos( count, day, month );
01288 mYearly->setFrequency( f );
01289 break; }
01290 case Recurrence::rYearlyDay: {
01291 recurrenceType = RecurrenceChooser::Yearly;
01292 QValueList<int> days = r->yearDays();
01293 if ( days.isEmpty() ) {
01294 day = incidence->dtStart().date().dayOfYear();
01295 } else {
01296 day = days.first();
01297 }
01298 mYearly->setByDay( day );
01299
01300 mYearly->setFrequency( f );
01301 break; }
01302 default:
01303 break;
01304 }
01305
01306 mRecurrenceChooser->setType( recurrenceType );
01307 showCurrentRule( recurrenceType );
01308
01309 mRecurrenceRange->setDateTimes( incidence->recurrence()->startDateTime() );
01310
01311 if ( incidence->doesRecur() ) {
01312 mRecurrenceRange->setDuration( r->duration() );
01313 if ( r->duration() == 0 ) mRecurrenceRange->setEndDate( r->endDate() );
01314 }
01315
01316 mExceptions->setDates( incidence->recurrence()->exDates() );
01317 }
01318
01319 void KOEditorRecurrence::writeIncidence( Incidence *incidence )
01320 {
01321 if ( !mEnabledCheck->isChecked() || !isEnabled() )
01322 {
01323 if ( incidence->doesRecur() )
01324 incidence->recurrence()->unsetRecurs();
01325 return;
01326 }
01327
01328 Recurrence *r = incidence->recurrence();
01329
01330
01331 r->unsetRecurs();
01332
01333 int duration = mRecurrenceRange->duration();
01334 QDate endDate;
01335 if ( duration == 0 ) endDate = mRecurrenceRange->endDate();
01336
01337 int recurrenceType = mRecurrenceChooser->type();
01338 if ( recurrenceType == RecurrenceChooser::Daily ) {
01339 r->setDaily( mDaily->frequency() );
01340 } else if ( recurrenceType == RecurrenceChooser::Weekly ) {
01341 r->setWeekly( mWeekly->frequency(), mWeekly->days() );
01342 } else if ( recurrenceType == RecurrenceChooser::Monthly ) {
01343 r->setMonthly( mMonthly->frequency() );
01344
01345 if ( mMonthly->byPos() ) {
01346 int pos = mMonthly->count();
01347
01348 QBitArray days( 7 );
01349 days.fill( false );
01350 days.setBit( mMonthly->weekday() - 1 );
01351 r->addMonthlyPos( pos, days );
01352 } else {
01353
01354 r->addMonthlyDate( mMonthly->day() );
01355 }
01356 } else if ( recurrenceType == RecurrenceChooser::Yearly ) {
01357 r->setYearly( mYearly->frequency() );
01358
01359 switch ( mYearly->getType() ) {
01360 case RecurYearly::byMonth:
01361 r->addYearlyDate( mYearly->monthDay() );
01362 r->addYearlyMonth( mYearly->month() );
01363 break;
01364 case RecurYearly::byPos: {
01365 r->addYearlyMonth( mYearly->posMonth() );
01366 QBitArray days( 7 );
01367 days.fill( false );
01368 days.setBit( mYearly->posWeekday() - 1 );
01369 r->addYearlyPos( mYearly->posCount(), days );
01370 break; }
01371 case RecurYearly::byDay:
01372 r->addYearlyDay( mYearly->day() );
01373 break;
01374 }
01375 }
01376
01377 if ( duration > 0 )
01378 r->setDuration( duration );
01379 else if ( duration == 0 )
01380 r->setEndDate( endDate );
01381 incidence->recurrence()->setExDates( mExceptions->dates() );
01382 }
01383
01384 void KOEditorRecurrence::setDateTimeStr( const QString &str )
01385 {
01386 mDateTimeLabel->setText( str );
01387 }
01388
01389 bool KOEditorRecurrence::validateInput()
01390 {
01391
01392
01393 if ( mEnabledCheck->isChecked() && (mRecurrenceRange->duration()==0) &&
01394 mEventStartDt.isValid() && ((mRecurrenceRange->endDate())<mEventStartDt.date()) ) {
01395 KMessageBox::sorry( 0,
01396 i18n("The end date '%1' of the recurrence must be after the start date '%2' of the event.")
01397 .arg( KGlobal::locale()->formatDate( mRecurrenceRange->endDate() ) )
01398 .arg( KGlobal::locale()->formatDate( mEventStartDt.date() ) ) );
01399 return false;
01400 }
01401 int recurrenceType = mRecurrenceChooser->type();
01402
01403
01404 if( mEnabledCheck->isChecked() && recurrenceType == RecurrenceChooser::Weekly ) {
01405 const QBitArray &days = mWeekly->days();
01406 bool valid = false;
01407 for ( int i=0; i<7; ++i ) valid = valid || days.testBit( i );
01408 if ( !valid ) {
01409 KMessageBox::sorry( 0,
01410 i18n("A weekly recurring event or task has to have at least one weekday "
01411 "associated with it.") );
01412 return false;
01413 }
01414 }
01415 return true;
01416 }
01417
01418 void KOEditorRecurrence::showExceptionsDialog()
01419 {
01420 DateList dates = mExceptions->dates();
01421 int result = mExceptionsDialog->exec();
01422 if ( result == QDialog::Rejected ) mExceptions->setDates( dates );
01423 }
01424
01425 void KOEditorRecurrence::showRecurrenceRangeDialog()
01426 {
01427 int duration = mRecurrenceRange->duration();
01428 QDate endDate = mRecurrenceRange->endDate();
01429
01430 int result = mRecurrenceRangeDialog->exec();
01431 if ( result == QDialog::Rejected ) {
01432 mRecurrenceRange->setDuration( duration );
01433 mRecurrenceRange->setEndDate( endDate );
01434 }
01435 }
01436
01437 bool KOEditorRecurrence::doesRecur()
01438 {
01439 return mEnabledCheck->isChecked();
01440 }
01441
01442 void KOEditorRecurrence::saveValues()
01443 {
01444 int duration = mRecurrenceRange->duration();
01445 QDate endDate;
01446 if ( duration == 0 ) {
01447 endDate = mRecurrenceRange->endDate();
01448 }
01449
01450 int recurrenceType = mRecurrenceChooser->type();
01451 if ( recurrenceType == RecurrenceChooser::Daily ) {
01452 mSaveRec.setDaily( mDaily->frequency() );
01453 } else if ( recurrenceType == RecurrenceChooser::Weekly ) {
01454 mSaveRec.setWeekly( mWeekly->frequency(), mWeekly->days() );
01455 } else if ( recurrenceType == RecurrenceChooser::Monthly ) {
01456 mSaveRec.setMonthly( mMonthly->frequency() );
01457
01458 if ( mMonthly->byPos() ) {
01459 int pos = mMonthly->count();
01460
01461 QBitArray days( 7 );
01462 days.fill( false );
01463 days.setBit( mMonthly->weekday() - 1 );
01464 mSaveRec.addMonthlyPos( pos, days );
01465 } else {
01466
01467 mSaveRec.addMonthlyDate( mMonthly->day() );
01468 }
01469 } else if ( recurrenceType == RecurrenceChooser::Yearly ) {
01470 mSaveRec.setYearly( mYearly->frequency() );
01471
01472 switch ( mYearly->getType() ) {
01473 case RecurYearly::byMonth:
01474 mSaveRec.addYearlyDate( mYearly->monthDay() );
01475 mSaveRec.addYearlyMonth( mYearly->month() );
01476 break;
01477
01478 case RecurYearly::byPos:
01479 {
01480 mSaveRec.addYearlyMonth( mYearly->posMonth() );
01481 QBitArray days( 7 );
01482 days.fill( false );
01483 days.setBit( mYearly->posWeekday() - 1 );
01484 mSaveRec.addYearlyPos( mYearly->posCount(), days );
01485 break;
01486 }
01487
01488 case RecurYearly::byDay:
01489 mSaveRec.addYearlyDay( mYearly->day() );
01490 break;
01491 }
01492 }
01493
01494 if ( duration > 0 ) {
01495 mSaveRec.setDuration( duration );
01496 } else if ( duration == 0 ) {
01497 mSaveRec.setEndDate( endDate );
01498 }
01499
01500 mSaveRec.setExDates( mExceptions->dates() );
01501 }
01502
01503 void KOEditorRecurrence::restoreValues()
01504 {
01505 QBitArray rDays( 7 );
01506 int day = 0;
01507 int count = 0;
01508 int month = 0;
01509
01510 if ( mSaveRec.startDateTime().isValid() && mSaveRec.endDateTime().isValid() ) {
01511 setDefaults( mSaveRec.startDateTime(), mSaveRec.endDateTime(), mSaveRec.doesFloat() );
01512 }
01513
01514 int recurrenceType;
01515 switch ( mSaveRec.recurrenceType() ) {
01516 case Recurrence::rNone:
01517 recurrenceType = RecurrenceChooser::Weekly;
01518 break;
01519
01520 case Recurrence::rDaily:
01521 recurrenceType = RecurrenceChooser::Daily;
01522 mDaily->setFrequency( mSaveRec.frequency() );
01523 break;
01524
01525 case Recurrence::rWeekly:
01526 recurrenceType = RecurrenceChooser::Weekly;
01527
01528 mWeekly->setFrequency( mSaveRec.frequency() );
01529 mWeekly->setDays( mSaveRec.days() );
01530 break;
01531
01532 case Recurrence::rMonthlyPos:
01533 {
01534
01535
01536
01537 recurrenceType = RecurrenceChooser::Monthly;
01538
01539 QValueList<RecurrenceRule::WDayPos> rmp = mSaveRec.monthPositions();
01540 if ( !rmp.isEmpty() ) {
01541 mMonthly->setByPos( rmp.first().pos(), rmp.first().day() );
01542 }
01543 mMonthly->setFrequency( mSaveRec.frequency() );
01544 break;
01545 }
01546
01547 case Recurrence::rMonthlyDay:
01548 {
01549 recurrenceType = RecurrenceChooser::Monthly;
01550
01551 QValueList<int> rmd = mSaveRec.monthDays();
01552
01553
01554 if ( !rmd.isEmpty() ) {
01555 day = rmd.first();
01556 }
01557 if ( day > 0 ) {
01558 mMonthly->setByDay( day );
01559 mMonthly->setFrequency( mSaveRec.frequency() );
01560 }
01561 break;
01562 }
01563
01564 case Recurrence::rYearlyMonth:
01565 {
01566 recurrenceType = RecurrenceChooser::Yearly;
01567
01568 QValueList<int> rmd = mSaveRec.yearDates();
01569 if ( !rmd.isEmpty() ) {
01570 day = rmd.first();
01571 }
01572 rmd = mSaveRec.yearMonths();
01573 if ( !rmd.isEmpty() ) {
01574 month = rmd.first();
01575 }
01576 if ( day > 0 && month > 0 ) {
01577 mYearly->setByMonth( day, month );
01578 mYearly->setFrequency( mSaveRec.frequency() );
01579 }
01580 break;
01581 }
01582
01583 case Recurrence::rYearlyPos:
01584 {
01585 recurrenceType = RecurrenceChooser::Yearly;
01586
01587 QValueList<int> months = mSaveRec.yearMonths();
01588 if ( !months.isEmpty() ) {
01589 month = months.first();
01590 }
01591 QValueList<RecurrenceRule::WDayPos> pos = mSaveRec.yearPositions();
01592 if ( !pos.isEmpty() ) {
01593 count = pos.first().pos();
01594 day = pos.first().day();
01595 }
01596 if ( count > 0 && day > 0 && month > 0 ) {
01597 mYearly->setByPos( count, day, month );
01598 mYearly->setFrequency( mSaveRec.frequency() );
01599 }
01600 break;
01601 }
01602
01603 case Recurrence::rYearlyDay:
01604 {
01605 recurrenceType = RecurrenceChooser::Yearly;
01606
01607 QValueList<int> days = mSaveRec.yearDays();
01608 if ( !days.isEmpty() ) {
01609 day = days.first();
01610 }
01611 if ( day > 0 ) {
01612 mYearly->setByDay( day );
01613 mYearly->setFrequency( mSaveRec.frequency() );
01614 }
01615 break;
01616 }
01617 default:
01618 break;
01619 }
01620
01621 mRecurrenceChooser->setType( recurrenceType );
01622 showCurrentRule( recurrenceType );
01623
01624 if ( mSaveRec.startDateTime().isValid() ) {
01625 mRecurrenceRange->setDateTimes( mSaveRec.startDateTime() );
01626 }
01627
01628 mRecurrenceRange->setDuration( mSaveRec.duration() );
01629 if ( mSaveRec.duration() == 0 && mSaveRec.endDate().isValid() ) {
01630 mRecurrenceRange->setEndDate( mSaveRec.endDate() );
01631 }
01632
01633 mExceptions->setDates( mSaveRec.exDates() );
01634 }
01635
01636 KOEditorRecurrenceDialog::KOEditorRecurrenceDialog(QWidget * parent)
01637 : KDialogBase( parent, 0, false, i18n("Recurrence"), Ok|Cancel ), mRecurEnabled( false )
01638 {
01639 mRecurrence = new KOEditorRecurrence( this );
01640 setMainWidget( mRecurrence );
01641 }
01642
01643 void KOEditorRecurrenceDialog::slotOk()
01644 {
01645 mRecurEnabled = mRecurrence->doesRecur();
01646 mRecurrence->saveValues();
01647 emit okClicked();
01648 accept();
01649 }
01650
01651 void KOEditorRecurrenceDialog::slotCancel()
01652 {
01653 mRecurrence->setRecurrenceEnabled( mRecurEnabled );
01654 mRecurrence->restoreValues();
01655 reject();
01656 }