00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include <qtooltip.h>
00025 #include <qfiledialog.h>
00026 #include <qlayout.h>
00027 #include <qvbox.h>
00028 #include <qbuttongroup.h>
00029 #include <qvgroupbox.h>
00030 #include <qwidgetstack.h>
00031 #include <qdatetime.h>
00032 #include <qlistbox.h>
00033 #include <qspinbox.h>
00034 #include <qcheckbox.h>
00035 #include <qgroupbox.h>
00036 #include <qwidgetstack.h>
00037 #include <qradiobutton.h>
00038 #include <qlabel.h>
00039 #include <qpushbutton.h>
00040
00041 #include <kdialog.h>
00042 #include <kglobal.h>
00043 #include <klocale.h>
00044 #include <kiconloader.h>
00045 #include <kdebug.h>
00046 #include <knumvalidator.h>
00047 #include <kcalendarsystem.h>
00048 #include <kmessagebox.h>
00049
00050 #include <libkdepim/kdateedit.h>
00051 #include <libkcal/todo.h>
00052
00053 #include "koprefs.h"
00054 #include "koglobals.h"
00055
00056 #include "koeditorrecurrence.h"
00057 #include "koeditorrecurrence.moc"
00058
00060
00061 RecurBase::RecurBase( QWidget *parent, const char *name ) :
00062 QWidget( parent, name )
00063 {
00064 mFrequencyEdit = new QSpinBox( 1, 9999, 1, this );
00065 mFrequencyEdit->setValue( 1 );
00066 }
00067
00068 QWidget *RecurBase::frequencyEdit()
00069 {
00070 return mFrequencyEdit;
00071 }
00072
00073 void RecurBase::setFrequency( int f )
00074 {
00075 if ( f < 1 ) f = 1;
00076
00077 mFrequencyEdit->setValue( f );
00078 }
00079
00080 int RecurBase::frequency()
00081 {
00082 return mFrequencyEdit->value();
00083 }
00084
00085 QComboBox *RecurBase::createWeekCountCombo( QWidget *parent, const char *name )
00086 {
00087 QComboBox *combo = new QComboBox( parent, name );
00088 if ( !combo ) return 0;
00089 combo->insertItem( i18n("1st") );
00090 combo->insertItem( i18n("2nd") );
00091 combo->insertItem( i18n("3rd") );
00092 combo->insertItem( i18n("4th") );
00093 combo->insertItem( i18n("5th") );
00094 combo->insertItem( i18n("Last") );
00095 combo->insertItem( i18n("2nd Last") );
00096 combo->insertItem( i18n("3rd Last") );
00097 combo->insertItem( i18n("4th Last") );
00098 combo->insertItem( i18n("5th Last") );
00099 return combo;
00100 }
00101
00102 QComboBox *RecurBase::createWeekdayCombo( QWidget *parent, const char *name )
00103 {
00104 QComboBox *combo = new QComboBox( parent, name );
00105 if ( !combo ) return 0;
00106 const KCalendarSystem *calSys = KOGlobals::self()->calendarSystem();
00107 for( int i = 1; i <= 7; ++i ) {
00108 combo->insertItem( calSys->weekDayName( i ) );
00109 }
00110 return combo;
00111 }
00112
00113 QComboBox *RecurBase::createMonthNameCombo( QWidget *parent, const char *name )
00114 {
00115 QComboBox *combo = new QComboBox( parent, name );
00116 if ( !combo ) return 0;
00117 const KCalendarSystem *calSys = KOGlobals::self()->calendarSystem();
00118 for( int i = 1; i <= 12; ++i ) {
00119
00120 QDate dt( 2005, i, 1 );
00121 combo->insertItem( calSys->monthName( dt ) );
00122 }
00123 return combo;
00124 }
00125
00126 QBoxLayout *RecurBase::createFrequencySpinBar( QWidget *parent, QLayout *layout,
00127 QString everyText, QString unitText )
00128 {
00129 QBoxLayout *freqLayout = new QHBoxLayout( layout );
00130
00131 QLabel *preLabel = new QLabel( everyText, parent );
00132 freqLayout->addWidget( preLabel );
00133
00134 freqLayout->addWidget( frequencyEdit() );
00135 preLabel->setBuddy( frequencyEdit() );
00136
00137 QLabel *postLabel = new QLabel( unitText, parent );
00138 freqLayout->addWidget( postLabel );
00139 freqLayout->addStretch();
00140 return freqLayout;
00141 }
00142
00144
00145 RecurDaily::RecurDaily( QWidget *parent, const char *name ) :
00146 RecurBase( parent, name )
00147 {
00148 QBoxLayout *topLayout = new QVBoxLayout( this );
00149 topLayout->setSpacing( KDialog::spacingHint() );
00150
00151 createFrequencySpinBar( this, topLayout, i18n("&Recur every"), i18n("day(s)") );
00152 }
00153
00154
00156
00157 RecurWeekly::RecurWeekly( QWidget *parent, const char *name ) :
00158 RecurBase( parent, name )
00159 {
00160 QBoxLayout *topLayout = new QVBoxLayout( this );
00161 topLayout->setSpacing( KDialog::spacingHint() );
00162
00163
00164
00165 createFrequencySpinBar( this, topLayout, i18n("&Recur every"), i18n("week(s) on:") );
00166
00167 QHBox *dayBox = new QHBox( this );
00168 topLayout->addWidget( dayBox, 1, AlignVCenter );
00169
00170 int weekStart=KGlobal::locale()->weekStartDay();
00171 for ( int i = 0; i < 7; ++i ) {
00172
00173
00174
00175 const KCalendarSystem *calSys = KOGlobals::self()->calendarSystem();
00176 QString weekDayName = calSys->weekDayName(
00177 (i + weekStart + 6)%7 + 1, true );
00178 if ( KOPrefs::instance()->mCompactDialogs ) {
00179 weekDayName = weekDayName.left( 1 );
00180 }
00181 mDayBoxes[ (i + weekStart + 6)%7 ] = new QCheckBox( weekDayName, dayBox );
00182 }
00183
00184 topLayout->addStretch( 1 );
00185 }
00186
00187 void RecurWeekly::setDays( const QBitArray &days )
00188 {
00189 for ( int i = 0; i < 7; ++i ) {
00190 mDayBoxes[ i ]->setChecked( days.testBit( i ) );
00191 }
00192 }
00193
00194 QBitArray RecurWeekly::days()
00195 {
00196 QBitArray days( 7 );
00197
00198 for ( int i = 0; i < 7; ++i ) {
00199 days.setBit( i, mDayBoxes[ i ]->isChecked() );
00200 }
00201
00202 return days;
00203 }
00204
00206
00207 RecurMonthly::RecurMonthly( QWidget *parent, const char *name ) :
00208 RecurBase( parent, name )
00209 {
00210 QBoxLayout *topLayout = new QVBoxLayout( this );
00211 topLayout->setSpacing( KDialog::spacingHint() );
00212
00213 createFrequencySpinBar( this, topLayout, i18n("&Recur every"), i18n("month(s)") );
00214
00215 QButtonGroup *buttonGroup = new QButtonGroup( this );
00216 buttonGroup->setFrameStyle( QFrame::NoFrame );
00217 topLayout->addWidget( buttonGroup, 1, AlignVCenter );
00218
00219 QGridLayout *buttonLayout = new QGridLayout( buttonGroup, 3, 2 );
00220 buttonLayout->setSpacing( KDialog::spacingHint() );
00221
00222
00223 QString recurOnText;
00224 if ( !KOPrefs::instance()->mCompactDialogs ) {
00225 recurOnText = i18n("&Recur on the");
00226 }
00227
00228 mByDayRadio = new QRadioButton( recurOnText, buttonGroup );
00229 buttonLayout->addWidget( mByDayRadio, 0, 0 );
00230
00231 mByDayCombo = new QComboBox( buttonGroup );
00232 mByDayCombo->setSizeLimit( 7 );
00233 mByDayCombo->insertItem( i18n("1st") );
00234 mByDayCombo->insertItem( i18n("2nd") );
00235 mByDayCombo->insertItem( i18n("3rd") );
00236 mByDayCombo->insertItem( i18n("4th") );
00237 mByDayCombo->insertItem( i18n("5th") );
00238 mByDayCombo->insertItem( i18n("6th") );
00239 mByDayCombo->insertItem( i18n("7th") );
00240 mByDayCombo->insertItem( i18n("8th") );
00241 mByDayCombo->insertItem( i18n("9th") );
00242 mByDayCombo->insertItem( i18n("10th") );
00243 mByDayCombo->insertItem( i18n("11th") );
00244 mByDayCombo->insertItem( i18n("12th") );
00245 mByDayCombo->insertItem( i18n("13th") );
00246 mByDayCombo->insertItem( i18n("14th") );
00247 mByDayCombo->insertItem( i18n("15th") );
00248 mByDayCombo->insertItem( i18n("16th") );
00249 mByDayCombo->insertItem( i18n("17th") );
00250 mByDayCombo->insertItem( i18n("18th") );
00251 mByDayCombo->insertItem( i18n("19th") );
00252 mByDayCombo->insertItem( i18n("20th") );
00253 mByDayCombo->insertItem( i18n("21st") );
00254 mByDayCombo->insertItem( i18n("22nd") );
00255 mByDayCombo->insertItem( i18n("23rd") );
00256 mByDayCombo->insertItem( i18n("24th") );
00257 mByDayCombo->insertItem( i18n("25th") );
00258 mByDayCombo->insertItem( i18n("26th") );
00259 mByDayCombo->insertItem( i18n("27th") );
00260 mByDayCombo->insertItem( i18n("28th") );
00261 mByDayCombo->insertItem( i18n("29th") );
00262 mByDayCombo->insertItem( i18n("30th") );
00263 mByDayCombo->insertItem( i18n("31st") );
00264 buttonLayout->addWidget( mByDayCombo, 0, 1 );
00265
00266 QLabel *byDayLabel = new QLabel( i18n("day"), buttonGroup );
00267 buttonLayout->addWidget( byDayLabel, 0, 2 );
00268
00269
00270 mByPosRadio = new QRadioButton( recurOnText, buttonGroup);
00271 buttonLayout->addWidget( mByPosRadio, 1, 0 );
00272
00273 mByPosCountCombo = createWeekCountCombo( buttonGroup );
00274 buttonLayout->addWidget( mByPosCountCombo, 1, 1 );
00275
00276 mByPosWeekdayCombo = createWeekdayCombo( buttonGroup );
00277 buttonLayout->addWidget( mByPosWeekdayCombo, 1, 2 );
00278 }
00279
00280 void RecurMonthly::setByDay( int day )
00281 {
00282 mByDayRadio->setChecked( true );
00283 mByDayCombo->setCurrentItem( day-1 );
00284 }
00285
00286 void RecurMonthly::setByPos( int count, int weekday )
00287 {
00288 mByPosRadio->setChecked( true );
00289 if (count>0)
00290 mByPosCountCombo->setCurrentItem( count - 1 );
00291 else
00292
00293 mByPosCountCombo->setCurrentItem( -count + 4 );
00294 mByPosWeekdayCombo->setCurrentItem( weekday );
00295 }
00296
00297 bool RecurMonthly::byDay()
00298 {
00299 return mByDayRadio->isChecked();
00300 }
00301
00302 bool RecurMonthly::byPos()
00303 {
00304 return mByPosRadio->isChecked();
00305 }
00306
00307 int RecurMonthly::day()
00308 {
00309 return mByDayCombo->currentItem() + 1;
00310 }
00311
00312 int RecurMonthly::count()
00313 {
00314 int pos=mByPosCountCombo->currentItem();
00315 if (pos<=4)
00316 return pos+1;
00317 else
00318 return -pos+4;
00319 }
00320
00321 int RecurMonthly::weekday()
00322 {
00323 return mByPosWeekdayCombo->currentItem();
00324 }
00325
00327
00328 RecurYearly::RecurYearly( QWidget *parent, const char *name ) :
00329 RecurBase( parent, name )
00330 {
00331 QBoxLayout *topLayout = new QVBoxLayout( this );
00332 topLayout->setSpacing( KDialog::spacingHint() );
00333
00334 createFrequencySpinBar( this, topLayout, i18n("&Recur every"), i18n("year(s)") );
00335
00336
00337 QButtonGroup *buttonGroup = new QButtonGroup( this );
00338 buttonGroup->setFrameStyle( QFrame::NoFrame );
00339 topLayout->addWidget( buttonGroup, 1, AlignVCenter );
00340
00341 QBoxLayout *buttonLayout = new QVBoxLayout( buttonGroup );
00342
00343
00344
00345 QBoxLayout *monthLayout = new QHBoxLayout( buttonLayout );
00346 QString recurInMonthText(
00347 i18n("part before XXX of 'Recur on day XXX of month YYY'",
00348 "&Recur on day "));
00349 if ( KOPrefs::instance()->mCompactDialogs ) {
00350 recurInMonthText = i18n("&Day ");
00351 }
00352 mByMonthRadio = new QRadioButton( recurInMonthText, buttonGroup );
00353 monthLayout->addWidget( mByMonthRadio );
00354 mByMonthSpin = new QSpinBox( 1, 31, 1, buttonGroup );
00355 monthLayout->addWidget( mByMonthSpin );
00356 QLabel *ofLabel = new QLabel(
00357 i18n("part between XXX and YYY of 'Recur on day XXX of month YYY'", " &of "),
00358 buttonGroup );
00359 monthLayout->addWidget( ofLabel );
00360
00361 mByMonthCombo = createMonthNameCombo( buttonGroup );
00362 monthLayout->addWidget( mByMonthCombo );
00363 ofLabel->setBuddy( mByMonthCombo );
00364
00365 monthLayout->addStretch( 1 );
00366
00367
00368
00369 QBoxLayout *posLayout = new QHBoxLayout( buttonLayout );
00370 QString recurOnPosText( i18n("Part before XXX in 'Recur on NNN. WEEKDAY of MONTH', short version", "&On" ) );
00371 if ( !KOPrefs::instance()->mCompactDialogs ) {
00372 recurOnPosText = i18n("Part before XXX in 'Recur on NNN. WEEKDAY of MONTH'", "&On the" );
00373 }
00374 mByPosRadio = new QRadioButton( recurOnPosText, buttonGroup );
00375 posLayout->addWidget( mByPosRadio );
00376
00377 mByPosDayCombo = createWeekCountCombo( buttonGroup );
00378 posLayout->addWidget( mByPosDayCombo );
00379
00380 mByPosWeekdayCombo = createWeekdayCombo( buttonGroup );
00381 posLayout->addWidget( mByPosWeekdayCombo );
00382
00383 ofLabel = new QLabel(
00384 i18n("part between WEEKDAY and MONTH in 'Recur on NNN. WEEKDAY of MONTH'", " o&f "),
00385 buttonGroup );
00386 posLayout->addWidget( ofLabel );
00387
00388 mByPosMonthCombo = createMonthNameCombo( buttonGroup );
00389 posLayout->addWidget( mByPosMonthCombo );
00390 ofLabel->setBuddy( mByPosMonthCombo );
00391
00392 posLayout->addStretch( 1 );
00393
00394
00395
00396 QBoxLayout *dayLayout = new QHBoxLayout( buttonLayout );
00397 QString recurOnDayText;
00398 if ( KOPrefs::instance()->mCompactDialogs ) {
00399 recurOnDayText = i18n("Day #");
00400 } else {
00401 recurOnDayText = i18n("Recur on &day #");
00402 }
00403 mByDayRadio = new QRadioButton( recurOnDayText, buttonGroup );
00404 dayLayout->addWidget( mByDayRadio );
00405
00406 mByDaySpin = new QSpinBox( 1, 366, 1, buttonGroup );
00407 dayLayout->addWidget( mByDaySpin );
00408
00409 QString ofTheYear( i18n("part after NNN of 'Recur on day #NNN of the year'", " of the &year"));
00410 if ( KOPrefs::instance()->mCompactDialogs ) {
00411 ofTheYear = i18n("part after NNN of 'Recur on day #NNN of the year', short version",
00412 " of the year");
00413 }
00414 ofLabel = new QLabel( ofTheYear, buttonGroup );
00415 dayLayout->addWidget( ofLabel );
00416 ofLabel->setBuddy( mByDaySpin );
00417
00418 dayLayout->addStretch( 1 );
00419 }
00420
00421 void RecurYearly::setByDay( int day )
00422 {
00423 mByDayRadio->setChecked( true );
00424 mByDaySpin->setValue( day );
00425 }
00426
00427 void RecurYearly::setByPos( int count, int weekday, int month )
00428 {
00429 mByPosRadio->setChecked( true );
00430 if ( count > 0 )
00431 mByPosDayCombo->setCurrentItem( count - 1 );
00432 else
00433 mByPosDayCombo->setCurrentItem( -count + 4 );
00434 mByPosWeekdayCombo->setCurrentItem( weekday );
00435 mByPosMonthCombo->setCurrentItem( month-1 );
00436 }
00437
00438 void RecurYearly::setByMonth( int day, int month )
00439 {
00440 mByMonthRadio->setChecked( true );
00441 mByMonthSpin->setValue( day );
00442 mByMonthCombo->setCurrentItem( month - 1 );
00443 }
00444
00445 RecurYearly::YearlyType RecurYearly::getType()
00446 {
00447 if ( mByMonthRadio->isChecked() ) return byMonth;
00448 if ( mByPosRadio->isChecked() ) return byPos;
00449 if ( mByDayRadio->isChecked() ) return byDay;
00450 return byMonth;
00451 }
00452
00453 int RecurYearly::monthDay()
00454 {
00455 return mByMonthSpin->value();
00456 }
00457
00458 int RecurYearly::month()
00459 {
00460 return mByMonthCombo->currentItem() + 1;
00461 }
00462
00463 int RecurYearly::posCount()
00464 {
00465 int pos = mByPosDayCombo->currentItem();
00466 if ( pos <= 4 )
00467 return pos + 1;
00468 else
00469 return -pos + 4;
00470 }
00471
00472 int RecurYearly::posWeekday()
00473 {
00474 return mByPosWeekdayCombo->currentItem();
00475 }
00476
00477 int RecurYearly::posMonth()
00478 {
00479 return mByPosMonthCombo->currentItem() + 1;
00480 }
00481
00482 int RecurYearly::day()
00483 {
00484 return mByDaySpin->value();
00485 }
00486
00488
00489 ExceptionsWidget::ExceptionsWidget( QWidget *parent, const char *name ) :
00490 QWidget( parent, name )
00491 {
00492 QBoxLayout *topLayout = new QVBoxLayout( this );
00493
00494 QGroupBox *groupBox = new QGroupBox( 1, Horizontal, i18n("E&xceptions"),
00495 this );
00496 topLayout->addWidget( groupBox );
00497
00498 QWidget *box = new QWidget( groupBox );
00499
00500 QGridLayout *boxLayout = new QGridLayout( box );
00501
00502 mExceptionDateEdit = new KDateEdit( box );
00503 mExceptionDateEdit->setDate( QDate::currentDate() );
00504 boxLayout->addWidget( mExceptionDateEdit, 0, 0 );
00505
00506 QPushButton *addExceptionButton = new QPushButton( i18n("&Add"), box );
00507 boxLayout->addWidget( addExceptionButton, 1, 0 );
00508 QPushButton *changeExceptionButton = new QPushButton( i18n("&Change"), box );
00509 boxLayout->addWidget( changeExceptionButton, 2, 0 );
00510 QPushButton *deleteExceptionButton = new QPushButton( i18n("&Delete"), box );
00511 boxLayout->addWidget( deleteExceptionButton, 3, 0 );
00512
00513 mExceptionList = new QListBox( box );
00514 boxLayout->addMultiCellWidget( mExceptionList, 0, 3, 1, 1 );
00515
00516 boxLayout->setRowStretch( 4, 1 );
00517 boxLayout->setColStretch( 1, 3 );
00518
00519 connect( addExceptionButton, SIGNAL( clicked() ),
00520 SLOT( addException() ) );
00521 connect( changeExceptionButton, SIGNAL( clicked() ),
00522 SLOT( changeException() ) );
00523 connect( deleteExceptionButton, SIGNAL( clicked() ),
00524 SLOT( deleteException() ) );
00525 }
00526
00527 void ExceptionsWidget::addException()
00528 {
00529 QDate date = mExceptionDateEdit->date();
00530 QString dateStr = KGlobal::locale()->formatDate( date );
00531 if( !mExceptionList->findItem( dateStr ) ) {
00532 mExceptionDates.append( date );
00533 mExceptionList->insertItem( dateStr );
00534 }
00535 }
00536
00537 void ExceptionsWidget::changeException()
00538 {
00539 int pos = mExceptionList->currentItem();
00540 if ( pos < 0 ) return;
00541
00542 QDate date = mExceptionDateEdit->date();
00543 mExceptionDates[ pos ] = date;
00544 mExceptionList->changeItem( KGlobal::locale()->formatDate( date ), pos );
00545 }
00546
00547 void ExceptionsWidget::deleteException()
00548 {
00549 int pos = mExceptionList->currentItem();
00550 if ( pos < 0 ) return;
00551
00552 mExceptionDates.remove( mExceptionDates.at( pos ) );
00553 mExceptionList->removeItem( pos );
00554 }
00555
00556 void ExceptionsWidget::setDates( const DateList &dates )
00557 {
00558 mExceptionList->clear();
00559 mExceptionDates.clear();
00560 DateList::ConstIterator dit;
00561 for ( dit = dates.begin(); dit != dates.end(); ++dit ) {
00562 mExceptionList->insertItem( KGlobal::locale()->formatDate(* dit ) );
00563 mExceptionDates.append( *dit );
00564 }
00565 }
00566
00567 DateList ExceptionsWidget::dates()
00568 {
00569 return mExceptionDates;
00570 }
00571
00573
00574 ExceptionsDialog::ExceptionsDialog( QWidget *parent, const char *name ) :
00575 KDialogBase( parent, name, true, i18n("Edit Exceptions"), Ok|Cancel )
00576 {
00577 mExceptions = new ExceptionsWidget( this );
00578 setMainWidget( mExceptions );
00579 }
00580
00581 void ExceptionsDialog::setDates( const DateList &dates )
00582 {
00583 mExceptions->setDates( dates );
00584 }
00585
00586 DateList ExceptionsDialog::dates()
00587 {
00588 return mExceptions->dates();
00589 }
00590
00592
00593 RecurrenceRangeWidget::RecurrenceRangeWidget( QWidget *parent,
00594 const char *name )
00595 : QWidget( parent, name )
00596 {
00597 QBoxLayout *topLayout = new QVBoxLayout( this );
00598
00599 mRangeGroupBox = new QGroupBox( 1, Horizontal, i18n("Recurrence Range"),
00600 this );
00601 topLayout->addWidget( mRangeGroupBox );
00602
00603 QWidget *rangeBox = new QWidget( mRangeGroupBox );
00604 QVBoxLayout *rangeLayout = new QVBoxLayout( rangeBox );
00605 rangeLayout->setSpacing( KDialog::spacingHint() );
00606
00607 mStartDateLabel = new QLabel( i18n("Begin on:"), rangeBox );
00608 rangeLayout->addWidget( mStartDateLabel );
00609
00610 QButtonGroup *rangeButtonGroup = new QButtonGroup( this );
00611 rangeButtonGroup->hide();
00612
00613 mNoEndDateButton = new QRadioButton( i18n("&No ending date"), rangeBox );
00614 rangeButtonGroup->insert( mNoEndDateButton );
00615 rangeLayout->addWidget( mNoEndDateButton );
00616
00617 QBoxLayout *durationLayout = new QHBoxLayout( rangeLayout );
00618 durationLayout->setSpacing( KDialog::spacingHint() );
00619
00620 mEndDurationButton = new QRadioButton( i18n("End &after"), rangeBox );
00621 rangeButtonGroup->insert( mEndDurationButton );
00622 durationLayout->addWidget( mEndDurationButton );
00623
00624 mEndDurationEdit = new QSpinBox( 1, 9999, 1, rangeBox );
00625 durationLayout->addWidget( mEndDurationEdit );
00626
00627 QLabel *endDurationLabel = new QLabel( i18n("&occurrence(s)"), rangeBox );
00628 durationLayout ->addWidget( endDurationLabel );
00629 endDurationLabel->setBuddy( mEndDurationEdit );
00630
00631 QBoxLayout *endDateLayout = new QHBoxLayout( rangeLayout );
00632 endDateLayout->setSpacing( KDialog::spacingHint() );
00633
00634 mEndDateButton = new QRadioButton( i18n("End &by:"), rangeBox );
00635 rangeButtonGroup->insert( mEndDateButton );
00636 endDateLayout->addWidget( mEndDateButton );
00637
00638 mEndDateEdit = new KDateEdit( rangeBox );
00639 endDateLayout->addWidget( mEndDateEdit );
00640
00641 endDateLayout->addStretch( 1 );
00642
00643 connect( mNoEndDateButton, SIGNAL( toggled( bool ) ),
00644 SLOT( showCurrentRange() ) );
00645 connect( mEndDurationButton, SIGNAL( toggled( bool ) ),
00646 SLOT( showCurrentRange() ) );
00647 connect( mEndDateButton, SIGNAL( toggled( bool ) ),
00648 SLOT( showCurrentRange() ) );
00649 }
00650
00651 void RecurrenceRangeWidget::setDefaults( const QDateTime &from )
00652 {
00653 mNoEndDateButton->setChecked( true );
00654
00655 setDateTimes( from );
00656 setEndDate( from.date() );
00657 }
00658
00659 void RecurrenceRangeWidget::setDuration( int duration )
00660 {
00661 if ( duration == -1 ) {
00662 mNoEndDateButton->setChecked( true );
00663 } else if ( duration == 0 ) {
00664 mEndDateButton->setChecked( true );
00665 } else {
00666 mEndDurationButton->setChecked( true );
00667 mEndDurationEdit->setValue( duration );
00668 }
00669 }
00670
00671 int RecurrenceRangeWidget::duration()
00672 {
00673 if ( mNoEndDateButton->isChecked() ) {
00674 return -1;
00675 } else if ( mEndDurationButton->isChecked() ) {
00676 return mEndDurationEdit->value();
00677 } else {
00678 return 0;
00679 }
00680 }
00681
00682 void RecurrenceRangeWidget::setEndDate( const QDate &date )
00683 {
00684 mEndDateEdit->setDate( date );
00685 }
00686
00687 QDate RecurrenceRangeWidget::endDate()
00688 {
00689 return mEndDateEdit->date();
00690 }
00691
00692 void RecurrenceRangeWidget::showCurrentRange()
00693 {
00694 mEndDurationEdit->setEnabled( mEndDurationButton->isChecked() );
00695 mEndDateEdit->setEnabled( mEndDateButton->isChecked() );
00696 }
00697
00698 void RecurrenceRangeWidget::setDateTimes( const QDateTime &start,
00699 const QDateTime & )
00700 {
00701 mStartDateLabel->setText( i18n("Begins on: %1")
00702 .arg( KGlobal::locale()->formatDate( start.date() ) ) );
00703 }
00704
00706
00707 RecurrenceRangeDialog::RecurrenceRangeDialog( QWidget *parent,
00708 const char *name ) :
00709 KDialogBase( parent, name, true, i18n("Edit Recurrence Range"), Ok|Cancel )
00710 {
00711 mRecurrenceRangeWidget = new RecurrenceRangeWidget( this );
00712 setMainWidget( mRecurrenceRangeWidget );
00713 }
00714
00715 void RecurrenceRangeDialog::setDefaults( const QDateTime &from )
00716 {
00717 mRecurrenceRangeWidget->setDefaults( from );
00718 }
00719
00720 void RecurrenceRangeDialog::setDuration( int duration )
00721 {
00722 mRecurrenceRangeWidget->setDuration( duration );
00723 }
00724
00725 int RecurrenceRangeDialog::duration()
00726 {
00727 return mRecurrenceRangeWidget->duration();
00728 }
00729
00730 void RecurrenceRangeDialog::setEndDate( const QDate &date )
00731 {
00732 mRecurrenceRangeWidget->setEndDate( date );
00733 }
00734
00735 QDate RecurrenceRangeDialog::endDate()
00736 {
00737 return mRecurrenceRangeWidget->endDate();
00738 }
00739
00740 void RecurrenceRangeDialog::setDateTimes( const QDateTime &start,
00741 const QDateTime &end )
00742 {
00743 mRecurrenceRangeWidget->setDateTimes( start, end );
00744 }
00745
00747
00748 RecurrenceChooser::RecurrenceChooser( QWidget *parent, const char *name ) :
00749 QWidget( parent, name )
00750 {
00751 QBoxLayout *topLayout = new QVBoxLayout( this );
00752
00753 if ( KOPrefs::instance()->mCompactDialogs ) {
00754 mTypeCombo = new QComboBox( this );
00755 mTypeCombo->insertItem( i18n("Daily") );
00756 mTypeCombo->insertItem( i18n("Weekly") );
00757 mTypeCombo->insertItem( i18n("Monthly") );
00758 mTypeCombo->insertItem( i18n("Yearly") );
00759
00760 topLayout->addWidget( mTypeCombo );
00761
00762 connect( mTypeCombo, SIGNAL( activated( int ) ), SLOT( emitChoice() ) );
00763 } else {
00764 mTypeCombo = 0;
00765
00766 QButtonGroup *ruleButtonGroup = new QButtonGroup( 1, Horizontal, this );
00767 ruleButtonGroup->setFrameStyle( QFrame::NoFrame );
00768 topLayout->addWidget( ruleButtonGroup );
00769
00770 mDailyButton = new QRadioButton( i18n("&Daily"), ruleButtonGroup );
00771 mWeeklyButton = new QRadioButton( i18n("&Weekly"), ruleButtonGroup );
00772 mMonthlyButton = new QRadioButton( i18n("&Monthly"), ruleButtonGroup );
00773 mYearlyButton = new QRadioButton( i18n("&Yearly"), ruleButtonGroup );
00774
00775 connect( mDailyButton, SIGNAL( toggled( bool ) ),
00776 SLOT( emitChoice() ) );
00777 connect( mWeeklyButton, SIGNAL( toggled( bool ) ),
00778 SLOT( emitChoice() ) );
00779 connect( mMonthlyButton, SIGNAL( toggled( bool ) ),
00780 SLOT( emitChoice() ) );
00781 connect( mYearlyButton, SIGNAL( toggled( bool ) ),
00782 SLOT( emitChoice() ) );
00783 }
00784 }
00785
00786 int RecurrenceChooser::type()
00787 {
00788 if ( mTypeCombo ) {
00789 return mTypeCombo->currentItem();
00790 } else {
00791 if ( mDailyButton->isChecked() ) return Daily;
00792 else if ( mWeeklyButton->isChecked() ) return Weekly;
00793 else if ( mMonthlyButton->isChecked() ) return Monthly;
00794 else return Yearly;
00795 }
00796 }
00797
00798 void RecurrenceChooser::setType( int type )
00799 {
00800 if ( mTypeCombo ) {
00801 mTypeCombo->setCurrentItem( type );
00802 } else {
00803 switch ( type ) {
00804 case Daily:
00805 mDailyButton->setChecked( true );
00806 break;
00807 case Weekly:
00808 mWeeklyButton->setChecked( true );
00809 break;
00810 case Monthly:
00811 mMonthlyButton->setChecked( true );
00812 break;
00813 case Yearly:
00814 default:
00815 mYearlyButton->setChecked( true );
00816 break;
00817 }
00818 }
00819 }
00820
00821 void RecurrenceChooser::emitChoice()
00822 {
00823 emit chosen ( type() );
00824 }
00825
00827
00828 KOEditorRecurrence::KOEditorRecurrence( QWidget* parent, const char *name ) :
00829 QWidget( parent, name )
00830 {
00831 QGridLayout *topLayout = new QGridLayout( this );
00832 topLayout->setSpacing( KDialog::spacingHint() );
00833
00834 mEnabledCheck = new QCheckBox( i18n("&Enable recurrence"), this );
00835 connect( mEnabledCheck, SIGNAL( toggled( bool ) ),
00836 SLOT( setRecurrenceEnabled( bool ) ) );
00837 topLayout->addMultiCellWidget( mEnabledCheck, 0, 0, 0, 1 );
00838
00839
00840 mTimeGroupBox = new QGroupBox( 1, Horizontal, i18n("Appointment Time "),
00841 this );
00842 topLayout->addMultiCellWidget( mTimeGroupBox, 1, 1 , 0 , 1 );
00843
00844 if ( KOPrefs::instance()->mCompactDialogs ) {
00845 mTimeGroupBox->hide();
00846 }
00847
00848
00849
00850
00851
00852 mDateTimeLabel = new QLabel( mTimeGroupBox );
00853
00854
00855
00856 Qt::Orientation orientation;
00857 if ( KOPrefs::instance()->mCompactDialogs ) orientation = Horizontal;
00858 else orientation = Vertical;
00859
00860 mRuleBox = new QGroupBox( 1, orientation, i18n("Recurrence Rule"), this );
00861 if ( KOPrefs::instance()->mCompactDialogs ) {
00862 topLayout->addWidget( mRuleBox, 2, 0 );
00863 } else {
00864 topLayout->addMultiCellWidget( mRuleBox, 2, 2, 0, 1 );
00865 }
00866
00867 mRecurrenceChooser = new RecurrenceChooser( mRuleBox );
00868 connect( mRecurrenceChooser, SIGNAL( chosen( int ) ),
00869 SLOT( showCurrentRule( int ) ) );
00870
00871 if ( !KOPrefs::instance()->mCompactDialogs ) {
00872 QFrame *ruleSepFrame = new QFrame( mRuleBox );
00873 ruleSepFrame->setFrameStyle( QFrame::VLine | QFrame::Sunken );
00874 }
00875
00876 mRuleStack = new QWidgetStack( mRuleBox );
00877
00878 mDaily = new RecurDaily( mRuleStack );
00879 mRuleStack->addWidget( mDaily, 0 );
00880
00881 mWeekly = new RecurWeekly( mRuleStack );
00882 mRuleStack->addWidget( mWeekly, 0 );
00883
00884 mMonthly = new RecurMonthly( mRuleStack );
00885 mRuleStack->addWidget( mMonthly, 0 );
00886
00887 mYearly = new RecurYearly( mRuleStack );
00888 mRuleStack->addWidget( mYearly, 0 );
00889
00890 showCurrentRule( mRecurrenceChooser->type() );
00891
00892 if ( KOPrefs::instance()->mCompactDialogs ) {
00893 mRecurrenceRangeWidget = 0;
00894 mRecurrenceRangeDialog = new RecurrenceRangeDialog( this );
00895 mRecurrenceRange = mRecurrenceRangeDialog;
00896 mRecurrenceRangeButton = new QPushButton( i18n("Recurrence Range..."),
00897 this );
00898 topLayout->addWidget( mRecurrenceRangeButton, 3, 0 );
00899 connect( mRecurrenceRangeButton, SIGNAL( clicked() ),
00900 SLOT( showRecurrenceRangeDialog() ) );
00901
00902 mExceptionsWidget = 0;
00903 mExceptionsDialog = new ExceptionsDialog( this );
00904 mExceptions = mExceptionsDialog;
00905 mExceptionsButton = new QPushButton( i18n("Exceptions..."), this );
00906 topLayout->addWidget( mExceptionsButton, 4, 0 );
00907 connect( mExceptionsButton, SIGNAL( clicked() ),
00908 SLOT( showExceptionsDialog() ) );
00909
00910 } else {
00911 mRecurrenceRangeWidget = new RecurrenceRangeWidget( this );
00912 mRecurrenceRangeDialog = 0;
00913 mRecurrenceRange = mRecurrenceRangeWidget;
00914 mRecurrenceRangeButton = 0;
00915 topLayout->addWidget( mRecurrenceRangeWidget, 3, 0 );
00916
00917 mExceptionsWidget = new ExceptionsWidget( this );
00918 mExceptionsDialog = 0;
00919 mExceptions = mExceptionsWidget;
00920 mExceptionsButton = 0;
00921 topLayout->addWidget( mExceptionsWidget, 3, 1 );
00922 }
00923 }
00924
00925 KOEditorRecurrence::~KOEditorRecurrence()
00926 {
00927 }
00928
00929 void KOEditorRecurrence::setRecurrenceEnabled( bool enabled )
00930 {
00931
00932
00933 mTimeGroupBox->setEnabled( enabled );
00934 mRuleBox->setEnabled( enabled );
00935 if ( mRecurrenceRangeWidget ) mRecurrenceRangeWidget->setEnabled( enabled );
00936 if ( mRecurrenceRangeButton ) mRecurrenceRangeButton->setEnabled( enabled );
00937 if ( mExceptionsWidget ) mExceptionsWidget->setEnabled( enabled );
00938 if ( mExceptionsButton ) mExceptionsButton->setEnabled( enabled );
00939 }
00940
00941 void KOEditorRecurrence::showCurrentRule( int current )
00942 {
00943 switch ( current ) {
00944 case Daily:
00945 mRuleStack->raiseWidget( mDaily );
00946 break;
00947 case Weekly:
00948 mRuleStack->raiseWidget( mWeekly );
00949 break;
00950 case Monthly:
00951 mRuleStack->raiseWidget( mMonthly );
00952 break;
00953 default:
00954 case Yearly:
00955 mRuleStack->raiseWidget( mYearly );
00956 break;
00957 }
00958 }
00959
00960 void KOEditorRecurrence::setDateTimes( QDateTime start, QDateTime end )
00961 {
00962
00963
00964 mEventStartDt = start;
00965 mRecurrenceRange->setDateTimes( start, end );
00966 mDaily->setDateTimes( start, end );
00967 mWeekly->setDateTimes( start, end );
00968 mMonthly->setDateTimes( start, end );
00969 mYearly->setDateTimes( start, end );
00970 }
00971
00972 void KOEditorRecurrence::setDefaults( QDateTime from, QDateTime to, bool )
00973 {
00974 setDateTimes( from, to );
00975
00976 bool enabled = false;
00977 mEnabledCheck->setChecked( enabled );
00978 setRecurrenceEnabled( enabled );
00979
00980 mRecurrenceRange->setDefaults( from );
00981
00982 mRecurrenceChooser->setType( RecurrenceChooser::Weekly );
00983 showCurrentRule( mRecurrenceChooser->type() );
00984
00985 mDaily->setFrequency( 1 );
00986
00987 mWeekly->setFrequency( 1 );
00988 QBitArray days( 7 );
00989 days.fill( 0 );
00990 days.setBit( (from.date().dayOfWeek()+6) % 7 );
00991 mWeekly->setDays( days );
00992
00993 mMonthly->setFrequency( 1 );
00994 mMonthly->setByPos( ( from.date().day() - 1 ) / 7 + 1, from.date().dayOfWeek() - 1 );
00995 mMonthly->setByDay( from.date().day() );
00996
00997 mYearly->setFrequency( 1 );
00998 mYearly->setByDay( from.date().dayOfYear() );
00999 mYearly->setByPos( ( from.date().day() - 1 ) / 7 + 1,
01000 from.date().dayOfWeek() - 1, from.date().month() );
01001 mYearly->setByMonth( from.date().day(), from.date().month() );
01002 }
01003
01004 void KOEditorRecurrence::readIncidence(Incidence *incidence)
01005 {
01006 if (!incidence) return;
01007
01008 QBitArray rDays( 7 );
01009 QPtrList<Recurrence::rMonthPos> rmp;
01010 QPtrList<int> rmd;
01011 int day = 0;
01012 int count = 0;
01013 int month = 0;
01014
01015 if ( incidence->type() == "Todo" ) {
01016 Todo *todo = static_cast<Todo *>(incidence);
01017 setDefaults( todo->dtStart(true), todo->dtDue(), todo->doesFloat() );
01018 } else {
01019 setDefaults( incidence->dtStart(), incidence->dtEnd(), incidence->doesFloat() );
01020 }
01021
01022 int recurs = incidence->doesRecur();
01023 int f = 0;
01024 Recurrence *r = 0;
01025
01026 if ( recurs )
01027 {
01028 r = incidence->recurrence();
01029 f = r->frequency();
01030 }
01031
01032
01033 mEnabledCheck->setChecked( recurs );
01034 setRecurrenceEnabled( recurs );
01035
01036 int recurrenceType = RecurrenceChooser::Weekly;
01037
01038 switch ( recurs ) {
01039 case Recurrence::rNone:
01040 break;
01041 case Recurrence::rDaily:
01042 recurrenceType = RecurrenceChooser::Daily;
01043 mDaily->setFrequency( f );
01044 break;
01045 case Recurrence::rWeekly:
01046 recurrenceType = RecurrenceChooser::Weekly;
01047 mWeekly->setFrequency( f );
01048 mWeekly->setDays( r->days() );
01049 break;
01050 case Recurrence::rMonthlyPos:
01051
01052
01053
01054 recurrenceType = RecurrenceChooser::Monthly;
01055
01056 rmp = r->monthPositions();
01057 if ( rmp.first()->negative )
01058 count=-rmp.first()->rPos;
01059 else
01060
01061 count = rmp.first()->rPos;
01062 day = 0;
01063 while ( !rmp.first()->rDays.testBit( day ) ) ++day;
01064 mMonthly->setByPos( count, day );
01065
01066 mMonthly->setFrequency( f );
01067
01068 break;
01069 case Recurrence::rMonthlyDay:
01070 recurrenceType = RecurrenceChooser::Monthly;
01071
01072 rmd = r->monthDays();
01073
01074
01075 if ( rmd.first() ) {
01076 day = *rmd.first();
01077 } else {
01078 day = incidence->dtStart().date().day();
01079 }
01080 mMonthly->setByDay( day );
01081
01082 mMonthly->setFrequency( f );
01083
01084 break;
01085 case Recurrence::rYearlyMonth: {
01086 recurrenceType = RecurrenceChooser::Yearly;
01087 rmd = r->monthDays();
01088 if ( rmd.first() ) {
01089 day = *rmd.first();
01090 } else {
01091 day = incidence->dtStart().date().day();
01092 }
01093 QValueList<int> monthlist;
01094 QValueList<int> leaplist;
01095 r->getYearlyMonthMonths( day, monthlist, leaplist );
01096 if ( !monthlist.isEmpty() ) {
01097 mYearly->setByMonth( day, monthlist.first() );
01098 }
01099 mYearly->setFrequency( f );
01100 break; }
01101 case Recurrence::rYearlyPos: {
01102 recurrenceType = RecurrenceChooser::Yearly;
01103 rmd = r->yearNums();
01104 if ( rmd.first() ) {
01105 month = *rmd.first();
01106 } else {
01107 month = incidence->dtStart().date().month();
01108 }
01109
01110 QPtrList<Recurrence::rMonthPos> monthPos( r->yearMonthPositions() );
01111 if ( monthPos.first() ) {
01112 Recurrence::rMonthPos *mp = monthPos.first();
01113 count = mp->rPos;
01114 if ( mp->negative ) count = -count;
01115 QBitArray days( mp->rDays );
01116 day = -1;
01117 for ( int i=6; i>=0; i-- ) {
01118 if ( days.testBit(i) ) day = i;
01119 }
01120 if ( day == -1 )
01121 day = incidence->dtStart().date().dayOfWeek();
01122 } else {
01123 count = ( incidence->dtStart().date().day() - 1 ) / 7;
01124 day = incidence->dtStart().date().dayOfWeek();
01125 }
01126 mYearly->setByPos( count, day, month );
01127 mYearly->setFrequency( f );
01128 break; }
01129 case Recurrence::rYearlyDay:
01130 recurrenceType = RecurrenceChooser::Yearly;
01131 rmd = r->yearNums();
01132 day = *rmd.first();
01133 mYearly->setByDay( day );
01134
01135 mYearly->setFrequency( f );
01136 break;
01137 default:
01138 break;
01139 }
01140
01141 mRecurrenceChooser->setType( recurrenceType );
01142 showCurrentRule( recurrenceType );
01143
01144 mRecurrenceRange->setDateTimes( incidence->recurrence()->recurStart() );
01145
01146 if ( incidence->doesRecur() ) {
01147 mRecurrenceRange->setDuration( r->duration() );
01148 if ( r->duration() == 0 ) mRecurrenceRange->setEndDate( r->endDate() );
01149 }
01150
01151 mExceptions->setDates( incidence->exDates() );
01152 }
01153
01154 void KOEditorRecurrence::writeIncidence( Incidence *incidence )
01155 {
01156 if ( !mEnabledCheck->isChecked() || !isEnabled() )
01157 {
01158 if ( incidence->doesRecur() )
01159 incidence->recurrence()->unsetRecurs();
01160 return;
01161 }
01162
01163 Recurrence *r = incidence->recurrence();
01164
01165
01166 r->unsetRecurs();
01167
01168 int duration = mRecurrenceRange->duration();
01169 QDate endDate;
01170 if ( duration == 0 ) endDate = mRecurrenceRange->endDate();
01171
01172 int recurrenceType = mRecurrenceChooser->type();
01173 if ( recurrenceType == RecurrenceChooser::Daily ) {
01174 int freq = mDaily->frequency();
01175 if ( duration != 0 ) r->setDaily( freq, duration );
01176 else r->setDaily( freq, endDate );
01177 } else if ( recurrenceType == RecurrenceChooser::Weekly ) {
01178 int freq = mWeekly->frequency();
01179 QBitArray days = mWeekly->days();
01180 if ( duration != 0 ) r->setWeekly( freq, days, duration );
01181 else r->setWeekly( freq, days, endDate );
01182 } else if ( recurrenceType == RecurrenceChooser::Monthly ) {
01183 int freq = mMonthly->frequency();
01184 if ( mMonthly->byPos() ) {
01185 int pos = mMonthly->count();
01186
01187 QBitArray days( 7 );
01188 days.fill( false );
01189
01190 days.setBit( mMonthly->weekday() );
01191 if ( duration != 0 )
01192 r->setMonthly( Recurrence::rMonthlyPos, freq, duration );
01193 else
01194 r->setMonthly( Recurrence::rMonthlyPos, freq, endDate );
01195 r->addMonthlyPos( pos, days );
01196 } else {
01197
01198 if ( duration != 0 ) {
01199 r->setMonthly( Recurrence::rMonthlyDay, freq, duration );
01200 } else {
01201 r->setMonthly( Recurrence::rMonthlyDay, freq, endDate );
01202 }
01203 r->addMonthlyDay( mMonthly->day() );
01204 }
01205 } else if ( recurrenceType == RecurrenceChooser::Yearly ) {
01206 int freq = mYearly->frequency();
01207
01208 switch ( mYearly->getType() ) {
01209 case RecurYearly::byMonth:
01210 if ( duration != 0 ) {
01211 r->setYearlyByDate( mYearly->monthDay(), r->feb29YearlyType(), freq, duration );
01212 } else {
01213 r->setYearlyByDate( mYearly->monthDay(), r->feb29YearlyType(), freq, endDate );
01214 }
01215 r->addYearlyNum( mYearly->month() );
01216 break;
01217 case RecurYearly::byPos: {
01218 if ( duration != 0 ) {
01219 r->setYearly( Recurrence::rYearlyPos, freq, duration );
01220 } else {
01221 r->setYearly( Recurrence::rYearlyPos, freq, endDate );
01222 }
01223 r->addYearlyNum( mYearly->posMonth() );
01224 QBitArray days( 7 );
01225 days.fill( false );
01226 days.setBit( mYearly->posWeekday() );
01227 r->addYearlyMonthPos( mYearly->posCount(), days );
01228 break; }
01229 case RecurYearly::byDay:
01230 if ( duration != 0 ) {
01231 r->setYearly( Recurrence::rYearlyDay, freq, duration );
01232 } else {
01233 r->setYearly( Recurrence::rYearlyDay, freq, endDate );
01234 }
01235 r->addYearlyNum( mYearly->day() );
01236 break;
01237 }
01238 }
01239
01240 incidence->setExDates( mExceptions->dates() );
01241 }
01242
01243 void KOEditorRecurrence::setDateTimeStr( const QString &str )
01244 {
01245 mDateTimeLabel->setText( str );
01246 }
01247
01248 bool KOEditorRecurrence::validateInput()
01249 {
01250
01251
01252 if ( mEnabledCheck->isChecked() && (mRecurrenceRange->duration()==0) &&
01253 mEventStartDt.isValid() && ((mRecurrenceRange->endDate())<mEventStartDt.date()) ) {
01254 KMessageBox::sorry( 0,
01255 i18n("The end date '%1' of the recurrence must be after the start date '%2' of the event.")
01256 .arg( KGlobal::locale()->formatDate( mRecurrenceRange->endDate() ) )
01257 .arg( KGlobal::locale()->formatDate( mEventStartDt.date() ) ) );
01258 return false;
01259 }
01260
01261 return true;
01262 }
01263
01264 void KOEditorRecurrence::showExceptionsDialog()
01265 {
01266 DateList dates = mExceptions->dates();
01267 int result = mExceptionsDialog->exec();
01268 if ( result == QDialog::Rejected ) mExceptions->setDates( dates );
01269 }
01270
01271 void KOEditorRecurrence::showRecurrenceRangeDialog()
01272 {
01273 int duration = mRecurrenceRange->duration();
01274 QDate endDate = mRecurrenceRange->endDate();
01275
01276 int result = mRecurrenceRangeDialog->exec();
01277 if ( result == QDialog::Rejected ) {
01278 mRecurrenceRange->setDuration( duration );
01279 mRecurrenceRange->setEndDate( endDate );
01280 }
01281 }