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 TQt, and distribute the resulting executable, 00022 without including the source code for TQt in the source distribution. 00023 */ 00024 00025 #include <tqtooltip.h> 00026 #include <tqfiledialog.h> 00027 #include <tqlayout.h> 00028 #include <tqvbox.h> 00029 #include <tqbuttongroup.h> 00030 #include <tqvgroupbox.h> 00031 #include <tqwidgetstack.h> 00032 #include <tqdatetime.h> 00033 #include <tqlistbox.h> 00034 #include <tqspinbox.h> 00035 #include <tqcheckbox.h> 00036 #include <tqgroupbox.h> 00037 #include <tqwidgetstack.h> 00038 #include <tqradiobutton.h> 00039 #include <tqlabel.h> 00040 #include <tqpushbutton.h> 00041 #include <tqwhatsthis.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( TQWidget *parent, const char *name ) : 00064 TQWidget( parent, name ) 00065 { 00066 mFrequencyEdit = new TQSpinBox( 1, 9999, 1, this ); 00067 mFrequencyEdit->setValue( 1 ); 00068 } 00069 00070 TQWidget *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 TQComboBox *RecurBase::createWeekCountCombo( TQWidget *parent, const char *name ) 00088 { 00089 TQComboBox *combo = new TQComboBox( parent, name ); 00090 TQWhatsThis::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 TQComboBox *RecurBase::createWeekdayCombo( TQWidget *parent, const char *name ) 00109 { 00110 TQComboBox *combo = new TQComboBox( parent, name ); 00111 TQWhatsThis::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 TQComboBox *RecurBase::createMonthNameCombo( TQWidget *parent, const char *name ) 00123 { 00124 TQComboBox *combo = new TQComboBox( parent, name ); 00125 TQWhatsThis::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 TQDate dt( 2005, i, 1 ); 00133 combo->insertItem( calSys->monthName( dt ) ); 00134 } 00135 return combo; 00136 } 00137 00138 TQBoxLayout *RecurBase::createFrequencySpinBar( TQWidget *parent, TQLayout *layout, 00139 TQString everyText, TQString unitText ) 00140 { 00141 TQBoxLayout *freqLayout = new TQHBoxLayout( layout ); 00142 00143 TQString whatsThis = i18n("Sets how often this event or to-do should recur."); 00144 TQLabel *preLabel = new TQLabel( everyText, parent ); 00145 TQWhatsThis::add( preLabel, whatsThis ); 00146 freqLayout->addWidget( preLabel ); 00147 00148 freqLayout->addWidget( frequencyEdit() ); 00149 preLabel->setBuddy( frequencyEdit() ); 00150 TQWhatsThis::add( preLabel->buddy(), whatsThis ); 00151 00152 TQLabel *postLabel = new TQLabel( unitText, parent ); 00153 TQWhatsThis::add( postLabel, whatsThis ); 00154 freqLayout->addWidget( postLabel ); 00155 freqLayout->addStretch(); 00156 return freqLayout; 00157 } 00158 00160 00161 RecurDaily::RecurDaily( TQWidget *parent, const char *name ) : 00162 RecurBase( parent, name ) 00163 { 00164 TQBoxLayout *topLayout = new TQVBoxLayout( this ); 00165 topLayout->setSpacing( KDialog::spacingHint() ); 00166 00167 createFrequencySpinBar( this, topLayout, i18n("&Recur every"), i18n("day(s)") ); 00168 } 00169 00170 00172 00173 RecurWeekly::RecurWeekly( TQWidget *parent, const char *name ) : 00174 RecurBase( parent, name ) 00175 { 00176 TQBoxLayout *topLayout = new TQVBoxLayout( 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 TQHBox *dayBox = new TQHBox( 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 TQString 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 TQCheckBox( weekDayName, dayBox ); 00198 TQWhatsThis::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 TQBitArray &days ) 00207 { 00208 for ( int i = 0; i < 7; ++i ) { 00209 mDayBoxes[ i ]->setChecked( days.testBit( i ) ); 00210 } 00211 } 00212 00213 TQBitArray RecurWeekly::days() 00214 { 00215 TQBitArray 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( TQWidget *parent, const char *name ) : 00227 RecurBase( parent, name ) 00228 { 00229 TQBoxLayout *topLayout = new TQVBoxLayout( this ); 00230 topLayout->setSpacing( KDialog::spacingHint() ); 00231 00232 createFrequencySpinBar( this, topLayout, i18n("&Recur every"), i18n("month(s)") ); 00233 00234 TQButtonGroup *buttonGroup = new TQButtonGroup( this ); 00235 buttonGroup->setFrameStyle( TQFrame::NoFrame ); 00236 topLayout->addWidget( buttonGroup, 1, AlignVCenter ); 00237 00238 TQGridLayout *buttonLayout = new TQGridLayout( buttonGroup, 3, 2 ); 00239 buttonLayout->setSpacing( KDialog::spacingHint() ); 00240 00241 00242 TQString recurOnText; 00243 if ( !KOPrefs::instance()->mCompactDialogs ) { 00244 recurOnText = i18n("&Recur on the"); 00245 } 00246 00247 mByDayRadio = new TQRadioButton( recurOnText, buttonGroup ); 00248 TQWhatsThis::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 TQString whatsThis = i18n("The day of the month on which this event or to-do " 00255 "should recur."); 00256 mByDayCombo = new TQComboBox( buttonGroup ); 00257 TQWhatsThis::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 TQLabel *byDayLabel = new TQLabel( i18n("day"), buttonGroup ); 00326 TQWhatsThis::add( byDayLabel, whatsThis ); 00327 buttonLayout->addWidget( byDayLabel, 0, 2 ); 00328 00329 00330 mByPosRadio = new TQRadioButton( recurOnText, buttonGroup); 00331 TQWhatsThis::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( TQWidget *parent, const char *name ) : 00400 RecurBase( parent, name ) 00401 { 00402 TQBoxLayout *topLayout = new TQVBoxLayout( this ); 00403 topLayout->setSpacing( KDialog::spacingHint() ); 00404 00405 createFrequencySpinBar( this, topLayout, i18n("&Recur every"), i18n("year(s)") ); 00406 00407 00408 TQButtonGroup *buttonGroup = new TQButtonGroup( this ); 00409 buttonGroup->setFrameStyle( TQFrame::NoFrame ); 00410 topLayout->addWidget( buttonGroup, 1, AlignVCenter ); 00411 00412 TQBoxLayout *buttonLayout = new TQVBoxLayout( buttonGroup ); 00413 00414 00415 /* YearlyMonth (day n of Month Y) */ 00416 TQBoxLayout *monthLayout = new TQHBoxLayout( buttonLayout ); 00417 TQString 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 TQRadioButton( recurInMonthText, buttonGroup ); 00424 TQWhatsThis::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 TQSpinBox( 1, 31, 1, buttonGroup ); 00429 TQWhatsThis::add( mByMonthSpin, 00430 i18n("The day of the month on which this event or to-do " 00431 "should recur.") ); 00432 monthLayout->addWidget( mByMonthSpin ); 00433 TQLabel *ofLabel = new TQLabel( 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 TQBoxLayout *posLayout = new TQHBoxLayout( buttonLayout ); 00448 TQString 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 TQRadioButton( recurOnPosText, buttonGroup ); 00453 TQWhatsThis::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 TQLabel( 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 TQBoxLayout *dayLayout = new TQHBoxLayout( buttonLayout ); 00478 TQString recurOnDayText; 00479 if ( KOPrefs::instance()->mCompactDialogs ) { 00480 recurOnDayText = i18n("Day #"); 00481 } else { 00482 recurOnDayText = i18n("Recur on &day #"); 00483 } 00484 TQString whatsThis = i18n("Sets a specific day within the year on which this " 00485 "event or to-do should recur."); 00486 mByDayRadio = new TQRadioButton( recurOnDayText, buttonGroup ); 00487 TQWhatsThis::add( mByDayRadio, whatsThis ); 00488 dayLayout->addWidget( mByDayRadio ); 00489 00490 mByDaySpin = new TQSpinBox( 1, 366, 1, buttonGroup ); 00491 TQWhatsThis::add( mByDaySpin, whatsThis ); 00492 00493 dayLayout->addWidget( mByDaySpin ); 00494 00495 TQString 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 TQLabel( ofTheYear, buttonGroup ); 00501 TQWhatsThis::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( TQWidget *parent, const char *name ) : 00577 TQWidget( parent, name ) 00578 { 00579 TQBoxLayout *topLayout = new TQVBoxLayout( this ); 00580 00581 TQGroupBox *groupBox = new TQGroupBox( 1, Qt::Horizontal, i18n("E&xceptions"), 00582 this ); 00583 topLayout->addWidget( groupBox ); 00584 00585 TQWidget *box = new TQWidget( groupBox ); 00586 00587 TQGridLayout *boxLayout = new TQGridLayout( box ); 00588 00589 mExceptionDateEdit = new KDateEdit( box ); 00590 TQWhatsThis::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( TQDate::currentDate() ); 00594 boxLayout->addWidget( mExceptionDateEdit, 0, 0 ); 00595 00596 TQPushButton *addExceptionButton = new TQPushButton( 00597 i18n( "Add a new recurrence to the recurrence list", "&Add" ), box ); 00598 TQWhatsThis::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 TQPushButton *changeExceptionButton = new TQPushButton( i18n("&Change"), box ); 00603 TQWhatsThis::add( changeExceptionButton, 00604 i18n("Replace the currently selected date with this date.") ); 00605 boxLayout->addWidget( changeExceptionButton, 2, 0 ); 00606 TQPushButton *deleteExceptionButton = new TQPushButton( i18n("&Delete"), box ); 00607 TQWhatsThis::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 TQListBox( box ); 00614 TQWhatsThis::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, TQT_SIGNAL( clicked() ), 00624 TQT_SLOT( addException() ) ); 00625 connect( changeExceptionButton, TQT_SIGNAL( clicked() ), 00626 TQT_SLOT( changeException() ) ); 00627 connect( deleteExceptionButton, TQT_SIGNAL( clicked() ), 00628 TQT_SLOT( deleteException() ) ); 00629 } 00630 00631 void ExceptionsWidget::addException() 00632 { 00633 TQDate date = mExceptionDateEdit->date(); 00634 TQString 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 TQDate 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( TQWidget *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( TQWidget *parent, 00698 const char *name ) 00699 : TQWidget( parent, name ) 00700 { 00701 TQBoxLayout *topLayout = new TQVBoxLayout( this ); 00702 00703 mRangeGroupBox = new TQGroupBox( 1, Qt::Horizontal, i18n("Recurrence Range"), 00704 this ); 00705 TQWhatsThis::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 TQWidget *rangeBox = new TQWidget( mRangeGroupBox ); 00711 TQVBoxLayout *rangeLayout = new TQVBoxLayout( rangeBox ); 00712 rangeLayout->setSpacing( KDialog::spacingHint() ); 00713 00714 mStartDateLabel = new TQLabel( i18n("Begin on:"), rangeBox ); 00715 TQWhatsThis::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 TQButtonGroup *rangeButtonGroup = new TQButtonGroup( this ); 00721 rangeButtonGroup->hide(); 00722 00723 mNoEndDateButton = new TQRadioButton( i18n("&No ending date"), rangeBox ); 00724 TQWhatsThis::add( mNoEndDateButton, 00725 i18n("Sets the event or to-do to recur forever.") ); 00726 rangeButtonGroup->insert( mNoEndDateButton ); 00727 rangeLayout->addWidget( mNoEndDateButton ); 00728 00729 TQBoxLayout *durationLayout = new TQHBoxLayout( rangeLayout ); 00730 durationLayout->setSpacing( KDialog::spacingHint() ); 00731 00732 mEndDurationButton = new TQRadioButton( i18n("End &after"), rangeBox ); 00733 TQWhatsThis::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 TQString whatsThis = i18n("Number of times the event or to-do should recur " 00740 "before stopping."); 00741 mEndDurationEdit = new TQSpinBox( 1, 9999, 1, rangeBox ); 00742 TQWhatsThis::add( mEndDurationEdit, whatsThis ); 00743 durationLayout->addWidget( mEndDurationEdit ); 00744 00745 TQLabel *endDurationLabel = new TQLabel( i18n("&occurrence(s)"), rangeBox ); 00746 TQWhatsThis::add( endDurationLabel, whatsThis ); 00747 durationLayout ->addWidget( endDurationLabel ); 00748 endDurationLabel->setBuddy( mEndDurationEdit ); 00749 00750 TQBoxLayout *endDateLayout = new TQHBoxLayout( rangeLayout ); 00751 endDateLayout->setSpacing( KDialog::spacingHint() ); 00752 00753 mEndDateButton = new TQRadioButton( i18n("End &on:"), rangeBox ); 00754 TQWhatsThis::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 TQWhatsThis::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, TQT_SIGNAL( toggled( bool ) ), 00769 TQT_SLOT( showCurrentRange() ) ); 00770 connect( mEndDurationButton, TQT_SIGNAL( toggled( bool ) ), 00771 TQT_SLOT( showCurrentRange() ) ); 00772 connect( mEndDateButton, TQT_SIGNAL( toggled( bool ) ), 00773 TQT_SLOT( showCurrentRange() ) ); 00774 } 00775 00776 void RecurrenceRangeWidget::setDefaults( const TQDateTime &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 TQDate &date ) 00808 { 00809 mEndDateEdit->setDate( date ); 00810 } 00811 00812 TQDate 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 TQDateTime &start, 00824 const TQDateTime & ) 00825 { 00826 mStartDateLabel->setText( i18n("Begins on: %1") 00827 .arg( KGlobal::locale()->formatDate( start.date() ) ) ); 00828 } 00829 00831 00832 RecurrenceRangeDialog::RecurrenceRangeDialog( TQWidget *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 TQDateTime &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 TQDate &date ) 00856 { 00857 mRecurrenceRangeWidget->setEndDate( date ); 00858 } 00859 00860 TQDate RecurrenceRangeDialog::endDate() 00861 { 00862 return mRecurrenceRangeWidget->endDate(); 00863 } 00864 00865 void RecurrenceRangeDialog::setDateTimes( const TQDateTime &start, 00866 const TQDateTime &end ) 00867 { 00868 mRecurrenceRangeWidget->setDateTimes( start, end ); 00869 } 00870 00872 00873 RecurrenceChooser::RecurrenceChooser( TQWidget *parent, const char *name ) : 00874 TQWidget( parent, name ) 00875 { 00876 TQBoxLayout *topLayout = new TQVBoxLayout( this ); 00877 00878 if ( KOPrefs::instance()->mCompactDialogs ) { 00879 mTypeCombo = new TQComboBox( this ); 00880 TQWhatsThis::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, TQT_SIGNAL( activated( int ) ), TQT_SLOT( emitChoice() ) ); 00891 } else { 00892 mTypeCombo = 0; 00893 00894 TQButtonGroup *ruleButtonGroup = new TQButtonGroup( 1, Qt::Horizontal, this ); 00895 ruleButtonGroup->setFrameStyle( TQFrame::NoFrame ); 00896 topLayout->addWidget( ruleButtonGroup ); 00897 00898 mDailyButton = new TQRadioButton( i18n("&Daily"), ruleButtonGroup ); 00899 TQWhatsThis::add( mDailyButton, 00900 i18n("Sets the event or to-do to recur daily according " 00901 "to the specified rules.") ); 00902 mWeeklyButton = new TQRadioButton( i18n("&Weekly"), ruleButtonGroup ); 00903 TQWhatsThis::add( mWeeklyButton, 00904 i18n("Sets the event or to-do to recur weekly according " 00905 "to the specified rules.") ); 00906 mMonthlyButton = new TQRadioButton( i18n("&Monthly"), ruleButtonGroup ); 00907 TQWhatsThis::add( mMonthlyButton, 00908 i18n("Sets the event or to-do to recur monthly according " 00909 "to the specified rules.") ); 00910 mYearlyButton = new TQRadioButton( i18n("&Yearly"), ruleButtonGroup ); 00911 TQWhatsThis::add( mYearlyButton, 00912 i18n("Sets the event or to-do to recur yearly according " 00913 "to the specified rules.") ); 00914 00915 connect( mDailyButton, TQT_SIGNAL( toggled( bool ) ), 00916 TQT_SLOT( emitChoice() ) ); 00917 connect( mWeeklyButton, TQT_SIGNAL( toggled( bool ) ), 00918 TQT_SLOT( emitChoice() ) ); 00919 connect( mMonthlyButton, TQT_SIGNAL( toggled( bool ) ), 00920 TQT_SLOT( emitChoice() ) ); 00921 connect( mYearlyButton, TQT_SIGNAL( toggled( bool ) ), 00922 TQT_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( TQWidget* parent, const char *name ) : 00969 TQWidget( parent, name ) 00970 { 00971 TQGridLayout *topLayout = new TQGridLayout( this ); 00972 topLayout->setSpacing( KDialog::spacingHint() ); 00973 00974 mEnabledCheck = new TQCheckBox( i18n("&Enable recurrence"), this ); 00975 TQWhatsThis::add( mEnabledCheck, 00976 i18n("Enables recurrence for this event or to-do according " 00977 "to the specified rules.") ); 00978 connect( mEnabledCheck, TQT_SIGNAL( toggled( bool ) ), 00979 TQT_SLOT( setRecurrenceEnabled( bool ) ) ); 00980 topLayout->addMultiCellWidget( mEnabledCheck, 0, 0, 0, 1 ); 00981 00982 00983 mTimeGroupBox = new TQGroupBox( 1, Qt::Horizontal, i18n("Appointment Time "), 00984 this ); 00985 TQWhatsThis::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 // TQFrame *timeFrame = new TQFrame( mTimeGroupBox ); 00994 // TQBoxLayout *layoutTimeFrame = new TQHBoxLayout( timeFrame ); 00995 // layoutTimeFrame->setSpacing( KDialog::spacingHint() ); 00996 00997 mDateTimeLabel = new TQLabel( mTimeGroupBox ); 00998 // mDateTimeLabel = new TQLabel( timeFrame ); 00999 // layoutTimeFrame->addWidget( mDateTimeLabel ); 01000 01001 Qt::Orientation orientation; 01002 if ( KOPrefs::instance()->mCompactDialogs ) orientation = Qt::Horizontal; 01003 else orientation = Qt::Vertical; 01004 01005 mRuleBox = new TQGroupBox( 1, orientation, i18n("Recurrence Rule"), this ); 01006 TQWhatsThis::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, TQT_SIGNAL( chosen( int ) ), 01017 TQT_SLOT( showCurrentRule( int ) ) ); 01018 01019 if ( !KOPrefs::instance()->mCompactDialogs ) { 01020 TQFrame *ruleSepFrame = new TQFrame( mRuleBox ); 01021 ruleSepFrame->setFrameStyle( TQFrame::VLine | TQFrame::Sunken ); 01022 } 01023 01024 mRuleStack = new TQWidgetStack( 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 TQPushButton( i18n("Recurrence Range..."), 01045 this ); 01046 TQWhatsThis::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, TQT_SIGNAL( clicked() ), 01051 TQT_SLOT( showRecurrenceRangeDialog() ) ); 01052 01053 mExceptionsWidget = 0; 01054 mExceptionsDialog = new ExceptionsDialog( this ); 01055 mExceptions = mExceptionsDialog; 01056 mExceptionsButton = new TQPushButton( i18n("Exceptions..."), this ); 01057 topLayout->addWidget( mExceptionsButton, 4, 0 ); 01058 connect( mExceptionsButton, TQT_SIGNAL( clicked() ), 01059 TQT_SLOT( showExceptionsDialog() ) ); 01060 01061 } else { 01062 mRecurrenceRangeWidget = new RecurrenceRangeWidget( this ); 01063 TQWhatsThis::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 // set some initial defaults for the saved recurrence 01079 mSaveRec.setDuration( -1 ); // never ending 01080 } 01081 01082 KOEditorRecurrence::~KOEditorRecurrence() 01083 { 01084 } 01085 01086 void KOEditorRecurrence::setRecurrenceEnabled( bool enabled ) 01087 { 01088 // kdDebug(5850) << "KOEditorRecurrence::setRecurrenceEnabled(): " << (enabled ? "on" : "off") << endl; 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 TQDateTime &start, const TQDateTime &end ) 01119 { 01120 // kdDebug(5850) << "KOEditorRecurrence::setDateTimes" << endl; 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 // Now set the defaults for all unused types, use the start time for it 01130 bool enabled = mEnabledCheck->isChecked(); 01131 int type = mRecurrenceChooser->type(); 01132 01133 if ( !enabled || type != RecurrenceChooser::Weekly ) { 01134 TQBitArray 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 TQDateTime &from, const TQDateTime &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 TQBitArray 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 TQBitArray 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 // TODO: we only handle one possibility in the list right now, 01224 // so I have hardcoded calls with first(). If we make the GUI 01225 // more extended, this can be changed. 01226 recurrenceType = RecurrenceChooser::Monthly; 01227 01228 TQValueList<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 TQValueList<int> rmd = r->monthDays(); 01240 // check if we have any setting for which day (vcs import is broken and 01241 // does not set any day, thus we need to check) 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 TQValueList<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 TQValueList<int> months = r->yearMonths(); 01271 if ( months.isEmpty() ) { 01272 month = incidence->dtStart().date().month(); 01273 } else { 01274 month = months.first(); 01275 } 01276 01277 TQValueList<RecurrenceRule::WDayPos> pos = r->yearPositions(); 01278 01279 if ( pos.isEmpty() ) { 01280 // Use dtStart if nothing is given (shouldn't happen!) 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 TQValueList<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 // clear out any old settings; 01331 r->unsetRecurs(); 01332 01333 int duration = mRecurrenceRange->duration(); 01334 TQDate 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 TQBitArray days( 7 ); 01349 days.fill( false ); 01350 days.setBit( mMonthly->weekday() - 1 ); 01351 r->addMonthlyPos( pos, days ); 01352 } else { 01353 // it's by day 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 TQBitArray 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 } // end "Yearly" 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 TQString &str ) 01385 { 01386 mDateTimeLabel->setText( str ); 01387 } 01388 01389 bool KOEditorRecurrence::validateInput() 01390 { 01391 // Check input here. 01392 // Check if the recurrence (if set to end at a date) is scheduled to end before the event starts. 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 // Check if a weekly recurrence has at least one day selected 01403 // TODO: Get rid of this, it's not really needed (by default the day should be taken from dtStart) 01404 if( mEnabledCheck->isChecked() && recurrenceType == RecurrenceChooser::Weekly ) { 01405 const TQBitArray &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 == TQDialog::Rejected ) mExceptions->setDates( dates ); 01423 } 01424 01425 void KOEditorRecurrence::showRecurrenceRangeDialog() 01426 { 01427 int duration = mRecurrenceRange->duration(); 01428 TQDate endDate = mRecurrenceRange->endDate(); 01429 01430 int result = mRecurrenceRangeDialog->exec(); 01431 if ( result == TQDialog::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 TQDate 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 TQBitArray days( 7 ); 01462 days.fill( false ); 01463 days.setBit( mMonthly->weekday() - 1 ); 01464 mSaveRec.addMonthlyPos( pos, days ); 01465 } else { 01466 // it's by day 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 TQBitArray 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 TQBitArray 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 // TODO: we only handle one possibility in the list right now, 01535 // so I have hardcoded calls with first(). If we make the GUI 01536 // more extended, this can be changed. 01537 recurrenceType = RecurrenceChooser::Monthly; 01538 01539 TQValueList<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 TQValueList<int> rmd = mSaveRec.monthDays(); 01552 // check if we have any setting for which day (vcs import is broken and 01553 // does not set any day, thus we need to check) 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 TQValueList<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 TQValueList<int> months = mSaveRec.yearMonths(); 01588 if ( !months.isEmpty() ) { 01589 month = months.first(); 01590 } 01591 TQValueList<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 TQValueList<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(TQWidget * 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(); // tell the incidence editor to update the recurrenceString 01648 accept(); 01649 } 01650 01651 void KOEditorRecurrenceDialog::slotCancel() 01652 { 01653 mRecurrence->setRecurrenceEnabled( mRecurEnabled ); 01654 mRecurrence->restoreValues(); 01655 reject(); 01656 }