recurrenceedit.cpp
00001 /* 00002 * recurrenceedit.cpp - widget to edit the event's recurrence definition 00003 * Program: kalarm 00004 * Copyright © 2002-2008 by David Jarvie <djarvie@kde.org> 00005 * 00006 * Based originally on KOrganizer module koeditorrecurrence.cpp, 00007 * Copyright (c) 2000,2001 Cornelius Schumacher <schumacher@kde.org> 00008 * 00009 * This program is free software; you can redistribute it and/or modify 00010 * it under the terms of the GNU General Public License as published by 00011 * the Free Software Foundation; either version 2 of the License, or 00012 * (at your option) any later version. 00013 * 00014 * This program is distributed in the hope that it will be useful, 00015 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00017 * GNU General Public License for more details. 00018 * 00019 * You should have received a copy of the GNU General Public License along 00020 * with this program; if not, write to the Free Software Foundation, Inc., 00021 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00022 */ 00023 00024 #include "kalarm.h" 00025 00026 #include <tqtooltip.h> 00027 #include <tqlayout.h> 00028 #include <tqvbox.h> 00029 #include <tqwidgetstack.h> 00030 #include <tqlistbox.h> 00031 #include <tqframe.h> 00032 #include <tqlabel.h> 00033 #include <tqpushbutton.h> 00034 #include <tqlineedit.h> 00035 #include <tqwhatsthis.h> 00036 00037 #include <tdeglobal.h> 00038 #include <tdelocale.h> 00039 #include <kcalendarsystem.h> 00040 #include <kiconloader.h> 00041 #include <kdialog.h> 00042 #include <tdemessagebox.h> 00043 #include <kdebug.h> 00044 00045 #include <libkcal/event.h> 00046 00047 #include "alarmevent.h" 00048 #include "alarmtimewidget.h" 00049 #include "checkbox.h" 00050 #include "combobox.h" 00051 #include "dateedit.h" 00052 #include "functions.h" 00053 #include "kalarmapp.h" 00054 #include "karecurrence.h" 00055 #include "preferences.h" 00056 #include "radiobutton.h" 00057 #include "repetition.h" 00058 #include "spinbox.h" 00059 #include "timeedit.h" 00060 #include "timespinbox.h" 00061 #include "buttongroup.h" 00062 using namespace KCal; 00063 00064 #include "recurrenceedit.moc" 00065 #include "recurrenceeditprivate.moc" 00066 00067 // Collect these widget labels together to ensure consistent wording and 00068 // translations across different modules. 00069 TQString RecurrenceEdit::i18n_Norecur() { return i18n("No recurrence"); } 00070 TQString RecurrenceEdit::i18n_NoRecur() { return i18n("No Recurrence"); } 00071 TQString RecurrenceEdit::i18n_AtLogin() { return i18n("At Login"); } 00072 TQString RecurrenceEdit::i18n_l_Atlogin() { return i18n("At &login"); } 00073 TQString RecurrenceEdit::i18n_HourlyMinutely() { return i18n("Hourly/Minutely"); } 00074 TQString RecurrenceEdit::i18n_u_HourlyMinutely() { return i18n("Ho&urly/Minutely"); } 00075 TQString RecurrenceEdit::i18n_Daily() { return i18n("Daily"); } 00076 TQString RecurrenceEdit::i18n_d_Daily() { return i18n("&Daily"); } 00077 TQString RecurrenceEdit::i18n_Weekly() { return i18n("Weekly"); } 00078 TQString RecurrenceEdit::i18n_w_Weekly() { return i18n("&Weekly"); } 00079 TQString RecurrenceEdit::i18n_Monthly() { return i18n("Monthly"); } 00080 TQString RecurrenceEdit::i18n_m_Monthly() { return i18n("&Monthly"); } 00081 TQString RecurrenceEdit::i18n_Yearly() { return i18n("Yearly"); } 00082 TQString RecurrenceEdit::i18n_y_Yearly() { return i18n("&Yearly"); } 00083 00084 00085 RecurrenceEdit::RecurrenceEdit(bool readOnly, TQWidget* parent, const char* name) 00086 : TQFrame(parent, name), 00087 mRule(0), 00088 mRuleButtonType(INVALID_RECUR), 00089 mDailyShown(false), 00090 mWeeklyShown(false), 00091 mMonthlyShown(false), 00092 mYearlyShown(false), 00093 mNoEmitTypeChanged(true), 00094 mReadOnly(readOnly) 00095 { 00096 TQBoxLayout* layout; 00097 TQVBoxLayout* topLayout = new TQVBoxLayout(this, 0, KDialog::spacingHint()); 00098 00099 /* Create the recurrence rule Group box which holds the recurrence period 00100 * selection buttons, and the weekly, monthly and yearly recurrence rule 00101 * frames which specify options individual to each of these distinct 00102 * sections of the recurrence rule. Each frame is made visible by the 00103 * selection of its corresponding radio button. 00104 */ 00105 00106 TQGroupBox* recurGroup = new TQGroupBox(1, Qt::Vertical, i18n("Recurrence Rule"), this, "recurGroup"); 00107 topLayout->addWidget(recurGroup); 00108 TQFrame* ruleFrame = new TQFrame(recurGroup, "ruleFrame"); 00109 layout = new TQVBoxLayout(ruleFrame, 0); 00110 layout->addSpacing(KDialog::spacingHint()/2); 00111 00112 layout = new TQHBoxLayout(layout, 0); 00113 TQBoxLayout* lay = new TQVBoxLayout(layout, 0); 00114 mRuleButtonGroup = new ButtonGroup(1, Qt::Horizontal, ruleFrame); 00115 mRuleButtonGroup->setInsideMargin(0); 00116 mRuleButtonGroup->setFrameStyle(TQFrame::NoFrame); 00117 lay->addWidget(mRuleButtonGroup); 00118 lay->addStretch(); // top-adjust the interval radio buttons 00119 connect(mRuleButtonGroup, TQT_SIGNAL(buttonSet(int)), TQT_SLOT(periodClicked(int))); 00120 00121 mNoneButton = new RadioButton(i18n_Norecur(), mRuleButtonGroup); 00122 mNoneButton->setFixedSize(mNoneButton->sizeHint()); 00123 mNoneButton->setReadOnly(mReadOnly); 00124 TQWhatsThis::add(mNoneButton, i18n("Do not repeat the alarm")); 00125 00126 mAtLoginButton = new RadioButton(i18n_l_Atlogin(), mRuleButtonGroup); 00127 mAtLoginButton->setFixedSize(mAtLoginButton->sizeHint()); 00128 mAtLoginButton->setReadOnly(mReadOnly); 00129 TQWhatsThis::add(mAtLoginButton, 00130 i18n("Trigger the alarm at the specified date/time and at every login until then.\n" 00131 "Note that it will also be triggered any time the alarm daemon is restarted.")); 00132 00133 mSubDailyButton = new RadioButton(i18n_u_HourlyMinutely(), mRuleButtonGroup); 00134 mSubDailyButton->setFixedSize(mSubDailyButton->sizeHint()); 00135 mSubDailyButton->setReadOnly(mReadOnly); 00136 TQWhatsThis::add(mSubDailyButton, 00137 i18n("Repeat the alarm at hourly/minutely intervals")); 00138 00139 mDailyButton = new RadioButton(i18n_d_Daily(), mRuleButtonGroup); 00140 mDailyButton->setFixedSize(mDailyButton->sizeHint()); 00141 mDailyButton->setReadOnly(mReadOnly); 00142 TQWhatsThis::add(mDailyButton, 00143 i18n("Repeat the alarm at daily intervals")); 00144 00145 mWeeklyButton = new RadioButton(i18n_w_Weekly(), mRuleButtonGroup); 00146 mWeeklyButton->setFixedSize(mWeeklyButton->sizeHint()); 00147 mWeeklyButton->setReadOnly(mReadOnly); 00148 TQWhatsThis::add(mWeeklyButton, 00149 i18n("Repeat the alarm at weekly intervals")); 00150 00151 mMonthlyButton = new RadioButton(i18n_m_Monthly(), mRuleButtonGroup); 00152 mMonthlyButton->setFixedSize(mMonthlyButton->sizeHint()); 00153 mMonthlyButton->setReadOnly(mReadOnly); 00154 TQWhatsThis::add(mMonthlyButton, 00155 i18n("Repeat the alarm at monthly intervals")); 00156 00157 mYearlyButton = new RadioButton(i18n_y_Yearly(), mRuleButtonGroup); 00158 mYearlyButton->setFixedSize(mYearlyButton->sizeHint()); 00159 mYearlyButton->setReadOnly(mReadOnly); 00160 TQWhatsThis::add(mYearlyButton, 00161 i18n("Repeat the alarm at annual intervals")); 00162 00163 mNoneButtonId = mRuleButtonGroup->id(mNoneButton); 00164 mAtLoginButtonId = mRuleButtonGroup->id(mAtLoginButton); 00165 mSubDailyButtonId = mRuleButtonGroup->id(mSubDailyButton); 00166 mDailyButtonId = mRuleButtonGroup->id(mDailyButton); 00167 mWeeklyButtonId = mRuleButtonGroup->id(mWeeklyButton); 00168 mMonthlyButtonId = mRuleButtonGroup->id(mMonthlyButton); 00169 mYearlyButtonId = mRuleButtonGroup->id(mYearlyButton); 00170 00171 // Sub-repetition button 00172 mSubRepetition = new RepetitionButton(i18n("Sub-Repetition"), true, ruleFrame); 00173 mSubRepetition->setFixedSize(mSubRepetition->sizeHint()); 00174 mSubRepetition->setReadOnly(mReadOnly); 00175 connect(mSubRepetition, TQT_SIGNAL(needsInitialisation()), TQT_SIGNAL(repeatNeedsInitialisation())); 00176 connect(mSubRepetition, TQT_SIGNAL(changed()), TQT_SIGNAL(frequencyChanged())); 00177 TQWhatsThis::add(mSubRepetition, i18n("Set up a repetition within the recurrence, to trigger the alarm multiple times each time the recurrence is due.")); 00178 lay->addSpacing(KDialog::spacingHint()); 00179 lay->addWidget(mSubRepetition); 00180 00181 lay = new TQVBoxLayout(layout); 00182 00183 lay->addStretch(); 00184 layout = new TQHBoxLayout(lay); 00185 00186 layout->addSpacing(KDialog::marginHint()); 00187 TQFrame* divider = new TQFrame(ruleFrame); 00188 divider->setFrameStyle(TQFrame::VLine | TQFrame::Sunken); 00189 layout->addWidget(divider); 00190 layout->addSpacing(KDialog::marginHint()); 00191 00192 mNoRule = new NoRule(ruleFrame, "noFrame"); 00193 mSubDailyRule = new SubDailyRule(mReadOnly, ruleFrame, "subdayFrame"); 00194 mDailyRule = new DailyRule(mReadOnly, ruleFrame, "dayFrame"); 00195 mWeeklyRule = new WeeklyRule(mReadOnly, ruleFrame, "weekFrame"); 00196 mMonthlyRule = new MonthlyRule(mReadOnly, ruleFrame, "monthFrame"); 00197 mYearlyRule = new YearlyRule(mReadOnly, ruleFrame, "yearFrame"); 00198 00199 connect(mSubDailyRule, TQT_SIGNAL(frequencyChanged()), this, TQT_SIGNAL(frequencyChanged())); 00200 connect(mDailyRule, TQT_SIGNAL(frequencyChanged()), this, TQT_SIGNAL(frequencyChanged())); 00201 connect(mWeeklyRule, TQT_SIGNAL(frequencyChanged()), this, TQT_SIGNAL(frequencyChanged())); 00202 connect(mMonthlyRule, TQT_SIGNAL(frequencyChanged()), this, TQT_SIGNAL(frequencyChanged())); 00203 connect(mYearlyRule, TQT_SIGNAL(frequencyChanged()), this, TQT_SIGNAL(frequencyChanged())); 00204 00205 mRuleStack = new TQWidgetStack(ruleFrame); 00206 layout->addWidget(mRuleStack); 00207 layout->addStretch(1); 00208 mRuleStack->addWidget(mNoRule, 0); 00209 mRuleStack->addWidget(mSubDailyRule, 1); 00210 mRuleStack->addWidget(mDailyRule, 2); 00211 mRuleStack->addWidget(mWeeklyRule, 3); 00212 mRuleStack->addWidget(mMonthlyRule, 4); 00213 mRuleStack->addWidget(mYearlyRule, 5); 00214 layout->addSpacing(KDialog::marginHint()); 00215 00216 // Create the recurrence range group which contains the controls 00217 // which specify how long the recurrence is to last. 00218 00219 mRangeButtonGroup = new ButtonGroup(i18n("Recurrence End"), this, "mRangeButtonGroup"); 00220 connect(mRangeButtonGroup, TQT_SIGNAL(buttonSet(int)), TQT_SLOT(rangeTypeClicked())); 00221 topLayout->addWidget(mRangeButtonGroup); 00222 00223 TQVBoxLayout* vlayout = new TQVBoxLayout(mRangeButtonGroup, KDialog::marginHint(), KDialog::spacingHint()); 00224 vlayout->addSpacing(fontMetrics().lineSpacing()/2); 00225 mNoEndDateButton = new RadioButton(i18n("No &end"), mRangeButtonGroup); 00226 mNoEndDateButton->setFixedSize(mNoEndDateButton->sizeHint()); 00227 mNoEndDateButton->setReadOnly(mReadOnly); 00228 TQWhatsThis::add(mNoEndDateButton, i18n("Repeat the alarm indefinitely")); 00229 vlayout->addWidget(mNoEndDateButton, 1, TQt::AlignAuto); 00230 TQSize size = mNoEndDateButton->size(); 00231 00232 layout = new TQHBoxLayout(vlayout, KDialog::spacingHint()); 00233 mRepeatCountButton = new RadioButton(i18n("End a&fter:"), mRangeButtonGroup); 00234 mRepeatCountButton->setReadOnly(mReadOnly); 00235 TQWhatsThis::add(mRepeatCountButton, 00236 i18n("Repeat the alarm for the number of times specified")); 00237 mRepeatCountEntry = new SpinBox(1, 9999, 1, mRangeButtonGroup); 00238 mRepeatCountEntry->setFixedSize(mRepeatCountEntry->sizeHint()); 00239 mRepeatCountEntry->setLineShiftStep(10); 00240 mRepeatCountEntry->setSelectOnStep(false); 00241 mRepeatCountEntry->setReadOnly(mReadOnly); 00242 connect(mRepeatCountEntry, TQT_SIGNAL(valueChanged(int)), TQT_SLOT(repeatCountChanged(int))); 00243 TQWhatsThis::add(mRepeatCountEntry, 00244 i18n("Enter the total number of times to trigger the alarm")); 00245 mRepeatCountButton->setFocusWidget(mRepeatCountEntry); 00246 mRepeatCountLabel = new TQLabel(i18n("occurrence(s)"), mRangeButtonGroup); 00247 mRepeatCountLabel->setFixedSize(mRepeatCountLabel->sizeHint()); 00248 layout->addWidget(mRepeatCountButton); 00249 layout->addSpacing(KDialog::spacingHint()); 00250 layout->addWidget(mRepeatCountEntry); 00251 layout->addWidget(mRepeatCountLabel); 00252 layout->addStretch(); 00253 size = size.expandedTo(mRepeatCountButton->sizeHint()); 00254 00255 layout = new TQHBoxLayout(vlayout, KDialog::spacingHint()); 00256 mEndDateButton = new RadioButton(i18n("End &by:"), mRangeButtonGroup); 00257 mEndDateButton->setReadOnly(mReadOnly); 00258 TQWhatsThis::add(mEndDateButton, 00259 i18n("Repeat the alarm until the date/time specified.\n\n" 00260 "Note: This applies to the main recurrence only. It does not limit any sub-repetition which will occur regardless after the last main recurrence.")); 00261 mEndDateEdit = new DateEdit(mRangeButtonGroup); 00262 mEndDateEdit->setFixedSize(mEndDateEdit->sizeHint()); 00263 mEndDateEdit->setReadOnly(mReadOnly); 00264 TQWhatsThis::add(mEndDateEdit, 00265 i18n("Enter the last date to repeat the alarm")); 00266 mEndDateButton->setFocusWidget(mEndDateEdit); 00267 mEndTimeEdit = new TimeEdit(mRangeButtonGroup); 00268 mEndTimeEdit->setFixedSize(mEndTimeEdit->sizeHint()); 00269 mEndTimeEdit->setReadOnly(mReadOnly); 00270 static const TQString lastTimeText = i18n("Enter the last time to repeat the alarm."); 00271 TQWhatsThis::add(mEndTimeEdit, TQString("%1\n\n%2").arg(lastTimeText).arg(TimeSpinBox::shiftWhatsThis())); 00272 mEndAnyTimeCheckBox = new CheckBox(i18n("Any time"), mRangeButtonGroup); 00273 mEndAnyTimeCheckBox->setFixedSize(mEndAnyTimeCheckBox->sizeHint()); 00274 mEndAnyTimeCheckBox->setReadOnly(mReadOnly); 00275 connect(mEndAnyTimeCheckBox, TQT_SIGNAL(toggled(bool)), TQT_SLOT(slotAnyTimeToggled(bool))); 00276 TQWhatsThis::add(mEndAnyTimeCheckBox, 00277 i18n("Stop repeating the alarm after your first login on or after the specified end date")); 00278 layout->addWidget(mEndDateButton); 00279 layout->addSpacing(KDialog::spacingHint()); 00280 layout->addWidget(mEndDateEdit); 00281 layout->addWidget(mEndTimeEdit); 00282 layout->addWidget(mEndAnyTimeCheckBox); 00283 layout->addStretch(); 00284 size = size.expandedTo(mEndDateButton->sizeHint()); 00285 00286 // Line up the widgets to the right of the radio buttons 00287 mRepeatCountButton->setFixedSize(size); 00288 mEndDateButton->setFixedSize(size); 00289 00290 // Create the exceptions group which specifies dates to be excluded 00291 // from the recurrence. 00292 00293 mExceptionGroup = new TQGroupBox(i18n("E&xceptions"), this, "mExceptionGroup"); 00294 topLayout->addWidget(mExceptionGroup); 00295 topLayout->setStretchFactor(mExceptionGroup, 2); 00296 vlayout = new TQVBoxLayout(mExceptionGroup, KDialog::marginHint(), KDialog::spacingHint()); 00297 vlayout->addSpacing(fontMetrics().lineSpacing()/2); 00298 layout = new TQHBoxLayout(vlayout, KDialog::spacingHint()); 00299 vlayout = new TQVBoxLayout(layout); 00300 00301 mExceptionDateList = new TQListBox(mExceptionGroup); 00302 mExceptionDateList->setSizePolicy(TQSizePolicy(TQSizePolicy::Expanding, TQSizePolicy::Expanding)); 00303 connect(mExceptionDateList, TQT_SIGNAL(selectionChanged()), TQT_SLOT(enableExceptionButtons())); 00304 TQWhatsThis::add(mExceptionDateList, 00305 i18n("The list of exceptions, i.e. dates/times excluded from the recurrence")); 00306 vlayout->addWidget(mExceptionDateList); 00307 00308 if (mReadOnly) 00309 { 00310 mExceptionDateEdit = 0; 00311 mChangeExceptionButton = 0; 00312 mDeleteExceptionButton = 0; 00313 } 00314 else 00315 { 00316 vlayout = new TQVBoxLayout(layout); 00317 mExceptionDateEdit = new DateEdit(mExceptionGroup); 00318 mExceptionDateEdit->setFixedSize(mExceptionDateEdit->sizeHint()); 00319 mExceptionDateEdit->setDate(TQDate::currentDate()); 00320 TQWhatsThis::add(mExceptionDateEdit, 00321 i18n("Enter a date to insert in the exceptions list. " 00322 "Use in conjunction with the Add or Change button below.")); 00323 vlayout->addWidget(mExceptionDateEdit); 00324 00325 layout = new TQHBoxLayout(vlayout, KDialog::spacingHint()); 00326 TQPushButton* button = new TQPushButton(i18n("Add"), mExceptionGroup); 00327 button->setFixedSize(button->sizeHint()); 00328 connect(button, TQT_SIGNAL(clicked()), TQT_SLOT(addException())); 00329 TQWhatsThis::add(button, 00330 i18n("Add the date entered above to the exceptions list")); 00331 layout->addWidget(button); 00332 00333 mChangeExceptionButton = new TQPushButton(i18n("Change"), mExceptionGroup); 00334 mChangeExceptionButton->setFixedSize(mChangeExceptionButton->sizeHint()); 00335 connect(mChangeExceptionButton, TQT_SIGNAL(clicked()), TQT_SLOT(changeException())); 00336 TQWhatsThis::add(mChangeExceptionButton, 00337 i18n("Replace the currently highlighted item in the exceptions list with the date entered above")); 00338 layout->addWidget(mChangeExceptionButton); 00339 00340 mDeleteExceptionButton = new TQPushButton(i18n("Delete"), mExceptionGroup); 00341 mDeleteExceptionButton->setFixedSize(mDeleteExceptionButton->sizeHint()); 00342 connect(mDeleteExceptionButton, TQT_SIGNAL(clicked()), TQT_SLOT(deleteException())); 00343 TQWhatsThis::add(mDeleteExceptionButton, 00344 i18n("Remove the currently highlighted item from the exceptions list")); 00345 layout->addWidget(mDeleteExceptionButton); 00346 } 00347 00348 mNoEmitTypeChanged = false; 00349 } 00350 00351 /****************************************************************************** 00352 * Verify the consistency of the entered data. 00353 * Reply = widget to receive focus on error, or 0 if no error. 00354 */ 00355 TQWidget* RecurrenceEdit::checkData(const TQDateTime& startDateTime, TQString& errorMessage) const 00356 { 00357 if (mAtLoginButton->isOn()) 00358 return 0; 00359 const_cast<RecurrenceEdit*>(this)->mCurrStartDateTime = startDateTime; 00360 if (mEndDateButton->isChecked()) 00361 { 00362 TQWidget* errWidget = 0; 00363 bool noTime = !mEndTimeEdit->isEnabled(); 00364 TQDate endDate = mEndDateEdit->date(); 00365 if (endDate < startDateTime.date()) 00366 errWidget = mEndDateEdit; 00367 else if (!noTime && TQDateTime(endDate, mEndTimeEdit->time()) < startDateTime) 00368 errWidget = mEndTimeEdit; 00369 if (errWidget) 00370 { 00371 errorMessage = noTime 00372 ? i18n("End date is earlier than start date") 00373 : i18n("End date/time is earlier than start date/time"); 00374 return errWidget; 00375 } 00376 } 00377 if (!mRule) 00378 return 0; 00379 return mRule->validate(errorMessage); 00380 } 00381 00382 /****************************************************************************** 00383 * Called when a recurrence period radio button is clicked. 00384 */ 00385 void RecurrenceEdit::periodClicked(int id) 00386 { 00387 RepeatType oldType = mRuleButtonType; 00388 bool none = (id == mNoneButtonId); 00389 bool atLogin = (id == mAtLoginButtonId); 00390 bool subdaily = (id == mSubDailyButtonId); 00391 if (none) 00392 { 00393 mRule = 0; 00394 mRuleButtonType = NO_RECUR; 00395 } 00396 else if (atLogin) 00397 { 00398 mRule = 0; 00399 mRuleButtonType = AT_LOGIN; 00400 mRangeButtonGroup->setButton(mRangeButtonGroup->id(mEndDateButton)); 00401 } 00402 else if (subdaily) 00403 { 00404 mRule = mSubDailyRule; 00405 mRuleButtonType = SUBDAILY; 00406 } 00407 else if (id == mDailyButtonId) 00408 { 00409 mRule = mDailyRule; 00410 mRuleButtonType = DAILY; 00411 mDailyShown = true; 00412 } 00413 else if (id == mWeeklyButtonId) 00414 { 00415 mRule = mWeeklyRule; 00416 mRuleButtonType = WEEKLY; 00417 mWeeklyShown = true; 00418 } 00419 else if (id == mMonthlyButtonId) 00420 { 00421 mRule = mMonthlyRule; 00422 mRuleButtonType = MONTHLY; 00423 mMonthlyShown = true; 00424 } 00425 else if (id == mYearlyButtonId) 00426 { 00427 mRule = mYearlyRule; 00428 mRuleButtonType = ANNUAL; 00429 mYearlyShown = true; 00430 } 00431 else 00432 return; 00433 00434 if (mRuleButtonType != oldType) 00435 { 00436 mRuleStack->raiseWidget(mRule ? mRule : mNoRule); 00437 if (oldType == NO_RECUR || none) 00438 mRangeButtonGroup->setEnabled(!none); 00439 mExceptionGroup->setEnabled(!(none || atLogin)); 00440 mEndAnyTimeCheckBox->setEnabled(atLogin); 00441 if (!none) 00442 { 00443 mNoEndDateButton->setEnabled(!atLogin); 00444 mRepeatCountButton->setEnabled(!atLogin); 00445 } 00446 rangeTypeClicked(); 00447 mSubRepetition->setEnabled(!(none || atLogin)); 00448 if (!mNoEmitTypeChanged) 00449 emit typeChanged(mRuleButtonType); 00450 } 00451 } 00452 00453 void RecurrenceEdit::slotAnyTimeToggled(bool on) 00454 { 00455 TQButton* button = mRuleButtonGroup->selected(); 00456 mEndTimeEdit->setEnabled((button == mAtLoginButton && !on) 00457 || (button == mSubDailyButton && mEndDateButton->isChecked())); 00458 } 00459 00460 /****************************************************************************** 00461 * Called when a recurrence range type radio button is clicked. 00462 */ 00463 void RecurrenceEdit::rangeTypeClicked() 00464 { 00465 bool endDate = mEndDateButton->isOn(); 00466 mEndDateEdit->setEnabled(endDate); 00467 mEndTimeEdit->setEnabled(endDate 00468 && ((mAtLoginButton->isOn() && !mEndAnyTimeCheckBox->isChecked()) 00469 || mSubDailyButton->isOn())); 00470 bool repeatCount = mRepeatCountButton->isOn(); 00471 mRepeatCountEntry->setEnabled(repeatCount); 00472 mRepeatCountLabel->setEnabled(repeatCount); 00473 } 00474 00475 void RecurrenceEdit::showEvent(TQShowEvent*) 00476 { 00477 if (mRule) 00478 mRule->setFrequencyFocus(); 00479 else 00480 mRuleButtonGroup->selected()->setFocus(); 00481 emit shown(); 00482 } 00483 00484 /****************************************************************************** 00485 * Return the sub-repetition count within the recurrence, i.e. the number of 00486 * repetitions after the main recurrence. 00487 */ 00488 int RecurrenceEdit::subRepeatCount(int* subRepeatInterval) const 00489 { 00490 int count = (mRuleButtonType >= SUBDAILY) ? mSubRepetition->count() : 0; 00491 if (subRepeatInterval) 00492 *subRepeatInterval = count ? mSubRepetition->interval() : 0; 00493 return count; 00494 } 00495 00496 /****************************************************************************** 00497 * Called when the Sub-Repetition button has been pressed to display the 00498 * sub-repetition dialog. 00499 * Alarm repetition has the following restrictions: 00500 * 1) Not allowed for a repeat-at-login alarm 00501 * 2) For a date-only alarm, the repeat interval must be a whole number of days. 00502 * 3) The overall repeat duration must be less than the recurrence interval. 00503 */ 00504 void RecurrenceEdit::setSubRepetition(int reminderMinutes, bool dateOnly) 00505 { 00506 int maxDuration; 00507 switch (mRuleButtonType) 00508 { 00509 case RecurrenceEdit::NO_RECUR: 00510 case RecurrenceEdit::AT_LOGIN: // alarm repeat not allowed 00511 maxDuration = 0; 00512 break; 00513 default: // repeat duration must be less than recurrence interval 00514 { 00515 KAEvent event; 00516 updateEvent(event, false); 00517 maxDuration = event.longestRecurrenceInterval() - reminderMinutes - 1; 00518 break; 00519 } 00520 } 00521 mSubRepetition->initialise(mSubRepetition->interval(), mSubRepetition->count(), dateOnly, maxDuration); 00522 mSubRepetition->setEnabled(mRuleButtonType >= SUBDAILY && maxDuration); 00523 } 00524 00525 /****************************************************************************** 00526 * Activate the sub-repetition dialog. 00527 */ 00528 void RecurrenceEdit::activateSubRepetition() 00529 { 00530 mSubRepetition->activate(); 00531 } 00532 00533 /****************************************************************************** 00534 * For weekly, monthly and yearly recurrence, checks that the specified date 00535 * matches the days allowed. For the other recurrence simply return true. 00536 */ 00537 bool RecurrenceEdit::validateDate(const DateTime &date) const 00538 { 00539 if (mRuleButtonType == RecurrenceEdit::DAILY) 00540 { 00541 TQBitArray selectedDays = mDailyRule->days(); 00542 if (!selectedDays[date.date().dayOfWeek()-1]) 00543 return false; 00544 } 00545 else if (mRuleButtonType == RecurrenceEdit::WEEKLY) 00546 { 00547 TQBitArray selectedDays = mWeeklyRule->days(); 00548 if (!selectedDays[date.date().dayOfWeek()-1]) 00549 return false; 00550 } 00551 else if (mRuleButtonType == RecurrenceEdit::MONTHLY) 00552 { 00553 if (mMonthlyRule->type() == MonthYearRule::DATE) 00554 { 00555 // on the nth day of the month 00556 int comboDate = mMonthlyRule->date(); 00557 if ((comboDate > 0 && date.date().day() != comboDate) || 00558 (comboDate <=0 && date.date().day() != date.date().daysInMonth())) 00559 return false; 00560 } 00561 else 00562 { 00563 // on the nth weekday (i.e. Monday) of the month 00564 if (date.date().dayOfWeek() != mMonthlyRule->dayOfWeek()) 00565 return false; 00566 00567 int monthDay = date.date().day(); 00568 int weekNum = mMonthlyRule->week(); 00569 int minDay = 0, maxDay = 0; 00570 if (weekNum > 0 ) 00571 { 00572 minDay = (weekNum-1) * 7; 00573 maxDay = weekNum * 7; 00574 } 00575 else if (weekNum < 0) 00576 { 00577 int dim = date.date().daysInMonth(); 00578 minDay = dim + weekNum * 7; 00579 maxDay = dim + (weekNum+1) * 7; 00580 } 00581 if (monthDay <= minDay || monthDay > maxDay) 00582 return false; 00583 } 00584 } 00585 else if (mRuleButtonType == RecurrenceEdit::ANNUAL) 00586 { 00587 TQValueList<int> months = mYearlyRule->months(); 00588 if (!months.contains(date.date().month())) 00589 return false; 00590 00591 if (mYearlyRule->type() == MonthYearRule::DATE) 00592 { 00593 // on the nth day of the month 00594 int comboDate = mYearlyRule->date(); 00595 if ((comboDate > 0 && date.date().day() != comboDate) || 00596 (comboDate <=0 && date.date().day() != date.date().daysInMonth())) 00597 return false; 00598 } 00599 else 00600 { 00601 // on the nth weekday (i.e. Monday) of the month 00602 if (date.date().dayOfWeek() != mYearlyRule->dayOfWeek()) 00603 return false; 00604 00605 int monthDay = date.date().day(); 00606 int weekNum = mYearlyRule->week(); 00607 int minDay = 0, maxDay = 0; 00608 if (weekNum > 0 ) 00609 { 00610 minDay = (weekNum-1) * 7; 00611 maxDay = weekNum * 7; 00612 } 00613 else if (weekNum < 0) 00614 { 00615 int dim = date.date().daysInMonth(); 00616 minDay = dim + weekNum * 7; 00617 maxDay = dim + (weekNum+1) * 7; 00618 } 00619 if (monthDay <= minDay || monthDay > maxDay) 00620 return false; 00621 } 00622 } 00623 return true; 00624 } 00625 00626 /****************************************************************************** 00627 * Called when the value of the repeat count field changes, to reset the 00628 * minimum value to 1 if the value was 0. 00629 */ 00630 void RecurrenceEdit::repeatCountChanged(int value) 00631 { 00632 if (value > 0 && mRepeatCountEntry->minValue() == 0) 00633 mRepeatCountEntry->setMinValue(1); 00634 } 00635 00636 /****************************************************************************** 00637 * Add the date entered in the exception date edit control to the list of 00638 * exception dates. 00639 */ 00640 void RecurrenceEdit::addException() 00641 { 00642 if (!mExceptionDateEdit || !mExceptionDateEdit->isValid()) 00643 return; 00644 TQDate date = mExceptionDateEdit->date(); 00645 TQValueList<TQDate>::Iterator it; 00646 int index = 0; 00647 bool insert = true; 00648 for (it = mExceptionDates.begin(); it != mExceptionDates.end(); ++index, ++it) 00649 { 00650 if (date <= *it) 00651 { 00652 insert = (date != *it); 00653 break; 00654 } 00655 } 00656 if (insert) 00657 { 00658 mExceptionDates.insert(it, date); 00659 mExceptionDateList->insertItem(TDEGlobal::locale()->formatDate(date), index); 00660 } 00661 mExceptionDateList->setCurrentItem(index); 00662 enableExceptionButtons(); 00663 } 00664 00665 /****************************************************************************** 00666 * Change the currently highlighted exception date to that entered in the 00667 * exception date edit control. 00668 */ 00669 void RecurrenceEdit::changeException() 00670 { 00671 if (!mExceptionDateEdit || !mExceptionDateEdit->isValid()) 00672 return; 00673 int index = mExceptionDateList->currentItem(); 00674 if (index >= 0 && mExceptionDateList->isSelected(index)) 00675 { 00676 TQDate olddate = mExceptionDates[index]; 00677 TQDate newdate = mExceptionDateEdit->date(); 00678 if (newdate != olddate) 00679 { 00680 mExceptionDates.remove(mExceptionDates.at(index)); 00681 mExceptionDateList->removeItem(index); 00682 addException(); 00683 } 00684 } 00685 } 00686 00687 /****************************************************************************** 00688 * Delete the currently highlighted exception date. 00689 */ 00690 void RecurrenceEdit::deleteException() 00691 { 00692 int index = mExceptionDateList->currentItem(); 00693 if (index >= 0 && mExceptionDateList->isSelected(index)) 00694 { 00695 mExceptionDates.remove(mExceptionDates.at(index)); 00696 mExceptionDateList->removeItem(index); 00697 enableExceptionButtons(); 00698 } 00699 } 00700 00701 /****************************************************************************** 00702 * Enable/disable the exception group buttons according to whether any item is 00703 * selected in the exceptions listbox. 00704 */ 00705 void RecurrenceEdit::enableExceptionButtons() 00706 { 00707 int index = mExceptionDateList->currentItem(); 00708 bool enable = (index >= 0 && mExceptionDateList->isSelected(index)); 00709 if (mDeleteExceptionButton) 00710 mDeleteExceptionButton->setEnabled(enable); 00711 if (mChangeExceptionButton) 00712 mChangeExceptionButton->setEnabled(enable); 00713 00714 // Prevent the exceptions list box receiving keyboard focus is it's empty 00715 mExceptionDateList->setFocusPolicy(mExceptionDateList->count() ? TQ_WheelFocus : TQ_NoFocus); 00716 } 00717 00718 /****************************************************************************** 00719 * Notify this instance of a change in the alarm start date. 00720 */ 00721 void RecurrenceEdit::setStartDate(const TQDate& start, const TQDate& today) 00722 { 00723 if (!mReadOnly) 00724 { 00725 setRuleDefaults(start); 00726 if (start < today) 00727 { 00728 mEndDateEdit->setMinDate(today); 00729 if (mExceptionDateEdit) 00730 mExceptionDateEdit->setMinDate(today); 00731 } 00732 else 00733 { 00734 const TQString startString = i18n("Date cannot be earlier than start date", "start date"); 00735 mEndDateEdit->setMinDate(start, startString); 00736 if (mExceptionDateEdit) 00737 mExceptionDateEdit->setMinDate(start, startString); 00738 } 00739 } 00740 } 00741 00742 /****************************************************************************** 00743 * Specify the default recurrence end date. 00744 */ 00745 void RecurrenceEdit::setDefaultEndDate(const TQDate& end) 00746 { 00747 if (!mEndDateButton->isOn()) 00748 mEndDateEdit->setDate(end); 00749 } 00750 00751 void RecurrenceEdit::setEndDateTime(const DateTime& end) 00752 { 00753 mEndDateEdit->setDate(end.date()); 00754 mEndTimeEdit->setValue(end.time()); 00755 mEndTimeEdit->setEnabled(!end.isDateOnly()); 00756 mEndAnyTimeCheckBox->setChecked(end.isDateOnly()); 00757 } 00758 00759 DateTime RecurrenceEdit::endDateTime() const 00760 { 00761 if (mRuleButtonGroup->selected() == mAtLoginButton && mEndAnyTimeCheckBox->isChecked()) 00762 return DateTime(mEndDateEdit->date()); 00763 return DateTime(mEndDateEdit->date(), mEndTimeEdit->time()); 00764 } 00765 00766 /****************************************************************************** 00767 * Set all controls to their default values. 00768 */ 00769 void RecurrenceEdit::setDefaults(const TQDateTime& from) 00770 { 00771 mCurrStartDateTime = from; 00772 TQDate fromDate = from.date(); 00773 mNoEndDateButton->setChecked(true); 00774 00775 mSubDailyRule->setFrequency(1); 00776 mDailyRule->setFrequency(1); 00777 mWeeklyRule->setFrequency(1); 00778 mMonthlyRule->setFrequency(1); 00779 mYearlyRule->setFrequency(1); 00780 00781 setRuleDefaults(fromDate); 00782 mMonthlyRule->setType(MonthYearRule::DATE); // date in month 00783 mYearlyRule->setType(MonthYearRule::DATE); // date in year 00784 00785 mEndDateEdit->setDate(fromDate); 00786 00787 mNoEmitTypeChanged = true; 00788 int button; 00789 switch (Preferences::defaultRecurPeriod()) 00790 { 00791 case AT_LOGIN: button = mAtLoginButtonId; break; 00792 case ANNUAL: button = mYearlyButtonId; break; 00793 case MONTHLY: button = mMonthlyButtonId; break; 00794 case WEEKLY: button = mWeeklyButtonId; break; 00795 case DAILY: button = mDailyButtonId; break; 00796 case SUBDAILY: button = mSubDailyButtonId; break; 00797 case NO_RECUR: 00798 default: button = mNoneButtonId; break; 00799 } 00800 mRuleButtonGroup->setButton(button); 00801 mNoEmitTypeChanged = false; 00802 rangeTypeClicked(); 00803 enableExceptionButtons(); 00804 00805 saveState(); 00806 } 00807 00808 /****************************************************************************** 00809 * Set the controls for weekly, monthly and yearly rules which have not so far 00810 * been shown, to their default values, depending on the recurrence start date. 00811 */ 00812 void RecurrenceEdit::setRuleDefaults(const TQDate& fromDate) 00813 { 00814 int day = fromDate.day(); 00815 int dayOfWeek = fromDate.dayOfWeek(); 00816 int month = fromDate.month(); 00817 if (!mDailyShown) 00818 mDailyRule->setDays(true); 00819 if (!mWeeklyShown) 00820 mWeeklyRule->setDay(dayOfWeek); 00821 if (!mMonthlyShown) 00822 mMonthlyRule->setDefaultValues(day, dayOfWeek); 00823 if (!mYearlyShown) 00824 mYearlyRule->setDefaultValues(day, dayOfWeek, month); 00825 } 00826 00827 /****************************************************************************** 00828 * Set the state of all controls to reflect the data in the specified event. 00829 * Set 'keepDuration' true to prevent the recurrence count being adjusted to the 00830 * remaining number of recurrences. 00831 */ 00832 void RecurrenceEdit::set(const KAEvent& event, bool keepDuration) 00833 { 00834 setDefaults(event.mainDateTime().dateTime()); 00835 if (event.repeatAtLogin()) 00836 { 00837 mRuleButtonGroup->setButton(mAtLoginButtonId); 00838 mEndDateButton->setChecked(true); 00839 return; 00840 } 00841 mRuleButtonGroup->setButton(mNoneButtonId); 00842 KARecurrence* recurrence = event.recurrence(); 00843 if (!recurrence) 00844 return; 00845 KARecurrence::Type rtype = recurrence->type(); 00846 switch (rtype) 00847 { 00848 case KARecurrence::MINUTELY: 00849 mRuleButtonGroup->setButton(mSubDailyButtonId); 00850 break; 00851 00852 case KARecurrence::DAILY: 00853 { 00854 mRuleButtonGroup->setButton(mDailyButtonId); 00855 TQBitArray rDays = recurrence->days(); 00856 bool set = false; 00857 for (int i = 0; i < 7 && !set; ++i) 00858 set = rDays.testBit(i); 00859 if (set) 00860 mDailyRule->setDays(rDays); 00861 else 00862 mDailyRule->setDays(true); 00863 break; 00864 } 00865 case KARecurrence::WEEKLY: 00866 { 00867 mRuleButtonGroup->setButton(mWeeklyButtonId); 00868 TQBitArray rDays = recurrence->days(); 00869 mWeeklyRule->setDays(rDays); 00870 break; 00871 } 00872 case KARecurrence::MONTHLY_POS: // on nth (Tuesday) of the month 00873 { 00874 TQValueList<RecurrenceRule::WDayPos> posns = recurrence->monthPositions(); 00875 int i = posns.first().pos(); 00876 if (!i) 00877 { 00878 // It's every (Tuesday) of the month. Convert to a weekly recurrence 00879 // (but ignoring any non-every xxxDay positions). 00880 mRuleButtonGroup->setButton(mWeeklyButtonId); 00881 mWeeklyRule->setFrequency(recurrence->frequency()); 00882 TQBitArray rDays(7); 00883 for (TQValueList<RecurrenceRule::WDayPos>::ConstIterator it = posns.begin(); it != posns.end(); ++it) 00884 { 00885 if (!(*it).pos()) 00886 rDays.setBit((*it).day() - 1, 1); 00887 } 00888 mWeeklyRule->setDays(rDays); 00889 break; 00890 } 00891 mRuleButtonGroup->setButton(mMonthlyButtonId); 00892 mMonthlyRule->setPosition(i, posns.first().day()); 00893 break; 00894 } 00895 case KARecurrence::MONTHLY_DAY: // on nth day of the month 00896 { 00897 mRuleButtonGroup->setButton(mMonthlyButtonId); 00898 TQValueList<int> rmd = recurrence->monthDays(); 00899 int day = (rmd.isEmpty()) ? event.mainDate().day() : rmd.first(); 00900 mMonthlyRule->setDate(day); 00901 break; 00902 } 00903 case KARecurrence::ANNUAL_DATE: // on the nth day of (months...) in the year 00904 case KARecurrence::ANNUAL_POS: // on the nth (Tuesday) of (months...) in the year 00905 { 00906 if (rtype == KARecurrence::ANNUAL_DATE) 00907 { 00908 mRuleButtonGroup->setButton(mYearlyButtonId); 00909 const TQValueList<int> rmd = recurrence->monthDays(); 00910 int day = (rmd.isEmpty()) ? event.mainDate().day() : rmd.first(); 00911 mYearlyRule->setDate(day); 00912 mYearlyRule->setFeb29Type(recurrence->feb29Type()); 00913 } 00914 else if (rtype == KARecurrence::ANNUAL_POS) 00915 { 00916 mRuleButtonGroup->setButton(mYearlyButtonId); 00917 TQValueList<RecurrenceRule::WDayPos> posns = recurrence->yearPositions(); 00918 mYearlyRule->setPosition(posns.first().pos(), posns.first().day()); 00919 } 00920 mYearlyRule->setMonths(recurrence->yearMonths()); 00921 break; 00922 } 00923 default: 00924 return; 00925 } 00926 00927 mRule->setFrequency(recurrence->frequency()); 00928 00929 // Get range information 00930 TQDateTime endtime = mCurrStartDateTime; 00931 int duration = recurrence->duration(); 00932 if (duration == -1) 00933 mNoEndDateButton->setChecked(true); 00934 else if (duration) 00935 { 00936 mRepeatCountButton->setChecked(true); 00937 mRepeatCountEntry->setValue(duration); 00938 } 00939 else 00940 { 00941 mEndDateButton->setChecked(true); 00942 endtime = recurrence->endDateTime(); 00943 mEndTimeEdit->setValue(endtime.time()); 00944 } 00945 mEndDateEdit->setDate(endtime.date()); 00946 00947 // Get exception information 00948 mExceptionDates = event.recurrence()->exDates(); 00949 qHeapSort(mExceptionDates); 00950 mExceptionDateList->clear(); 00951 for (DateList::ConstIterator it = mExceptionDates.begin(); it != mExceptionDates.end(); ++it) 00952 mExceptionDateList->insertItem(TDEGlobal::locale()->formatDate(*it)); 00953 enableExceptionButtons(); 00954 00955 // Get repetition within recurrence 00956 mSubRepetition->set(event.repeatInterval(), event.repeatCount()); 00957 00958 rangeTypeClicked(); 00959 00960 saveState(); 00961 } 00962 00963 /****************************************************************************** 00964 * Update the specified KAEvent with the entered recurrence data. 00965 * If 'adjustStart' is true, the start date/time will be adjusted if necessary 00966 * to be the first date/time which recurs on or after the original start. 00967 */ 00968 void RecurrenceEdit::updateEvent(KAEvent& event, bool adjustStart) 00969 { 00970 // Get end date and repeat count, common to all types of recurring events 00971 TQDate endDate; 00972 TQTime endTime; 00973 int repeatCount; 00974 if (mNoEndDateButton->isChecked()) 00975 repeatCount = -1; 00976 else if (mRepeatCountButton->isChecked()) 00977 repeatCount = mRepeatCountEntry->value(); 00978 else 00979 { 00980 repeatCount = 0; 00981 endDate = mEndDateEdit->date(); 00982 endTime = mEndTimeEdit->time(); 00983 } 00984 00985 // Set up the recurrence according to the type selected 00986 TQButton* button = mRuleButtonGroup->selected(); 00987 event.setRepeatAtLogin(button == mAtLoginButton); 00988 int frequency = mRule ? mRule->frequency() : 0; 00989 if (button == mSubDailyButton) 00990 { 00991 TQDateTime endDateTime(endDate, endTime); 00992 event.setRecurMinutely(frequency, repeatCount, endDateTime); 00993 } 00994 else if (button == mDailyButton) 00995 { 00996 event.setRecurDaily(frequency, mDailyRule->days(), repeatCount, endDate); 00997 } 00998 else if (button == mWeeklyButton) 00999 { 01000 event.setRecurWeekly(frequency, mWeeklyRule->days(), repeatCount, endDate); 01001 } 01002 else if (button == mMonthlyButton) 01003 { 01004 if (mMonthlyRule->type() == MonthlyRule::POS) 01005 { 01006 // It's by position 01007 KAEvent::MonthPos pos; 01008 pos.days.fill(false); 01009 pos.days.setBit(mMonthlyRule->dayOfWeek() - 1); 01010 pos.weeknum = mMonthlyRule->week(); 01011 TQValueList<KAEvent::MonthPos> poses; 01012 poses.append(pos); 01013 event.setRecurMonthlyByPos(frequency, poses, repeatCount, endDate); 01014 } 01015 else 01016 { 01017 // It's by day 01018 int daynum = mMonthlyRule->date(); 01019 TQValueList<int> daynums; 01020 daynums.append(daynum); 01021 event.setRecurMonthlyByDate(frequency, daynums, repeatCount, endDate); 01022 } 01023 } 01024 else if (button == mYearlyButton) 01025 { 01026 TQValueList<int> months = mYearlyRule->months(); 01027 if (mYearlyRule->type() == YearlyRule::POS) 01028 { 01029 // It's by position 01030 KAEvent::MonthPos pos; 01031 pos.days.fill(false); 01032 pos.days.setBit(mYearlyRule->dayOfWeek() - 1); 01033 pos.weeknum = mYearlyRule->week(); 01034 TQValueList<KAEvent::MonthPos> poses; 01035 poses.append(pos); 01036 event.setRecurAnnualByPos(frequency, poses, months, repeatCount, endDate); 01037 } 01038 else 01039 { 01040 // It's by date in month 01041 event.setRecurAnnualByDate(frequency, months, mYearlyRule->date(), 01042 mYearlyRule->feb29Type(), repeatCount, endDate); 01043 } 01044 } 01045 else 01046 { 01047 event.setNoRecur(); 01048 return; 01049 } 01050 if (!event.recurs()) 01051 return; // an error occurred setting up the recurrence 01052 if (adjustStart) 01053 event.setFirstRecurrence(); 01054 01055 // Set up repetition within the recurrence. 01056 // N.B. This requires the main recurrence to be set up first. 01057 int count = mSubRepetition->count(); 01058 if (mRuleButtonType < SUBDAILY) 01059 count = 0; 01060 event.setRepetition(mSubRepetition->interval(), count); 01061 01062 // Set up exceptions 01063 event.recurrence()->setExDates(mExceptionDates); 01064 01065 event.setUpdated(); 01066 } 01067 01068 /****************************************************************************** 01069 * Save the state of all controls. 01070 */ 01071 void RecurrenceEdit::saveState() 01072 { 01073 mSavedRuleButton = mRuleButtonGroup->selected(); 01074 if (mRule) 01075 mRule->saveState(); 01076 mSavedRangeButton = mRangeButtonGroup->selected(); 01077 if (mSavedRangeButton == mRepeatCountButton) 01078 mSavedRecurCount = mRepeatCountEntry->value(); 01079 else if (mSavedRangeButton == mEndDateButton) 01080 mSavedEndDateTime.set(TQDateTime(mEndDateEdit->date(), mEndTimeEdit->time()), mEndAnyTimeCheckBox->isChecked()); 01081 mSavedExceptionDates = mExceptionDates; 01082 mSavedRepeatInterval = mSubRepetition->interval(); 01083 mSavedRepeatCount = mSubRepetition->count(); 01084 } 01085 01086 /****************************************************************************** 01087 * Check whether any of the controls have changed state since initialisation. 01088 */ 01089 bool RecurrenceEdit::stateChanged() const 01090 { 01091 if (mSavedRuleButton != mRuleButtonGroup->selected() 01092 || mSavedRangeButton != mRangeButtonGroup->selected() 01093 || (mRule && mRule->stateChanged())) 01094 return true; 01095 if (mSavedRangeButton == mRepeatCountButton 01096 && mSavedRecurCount != mRepeatCountEntry->value()) 01097 return true; 01098 if (mSavedRangeButton == mEndDateButton 01099 && mSavedEndDateTime != DateTime(TQDateTime(mEndDateEdit->date(), mEndTimeEdit->time()), mEndAnyTimeCheckBox->isChecked())) 01100 return true; 01101 if (mSavedExceptionDates != mExceptionDates 01102 || mSavedRepeatInterval != mSubRepetition->interval() 01103 || mSavedRepeatCount != mSubRepetition->count()) 01104 return true; 01105 return false; 01106 } 01107 01108 01109 01110 /*============================================================================= 01111 = Class Rule 01112 = Base class for rule widgets, including recurrence frequency. 01113 =============================================================================*/ 01114 01115 Rule::Rule(const TQString& freqText, const TQString& freqWhatsThis, bool time, bool readOnly, TQWidget* parent, const char* name) 01116 : NoRule(parent, name) 01117 { 01118 mLayout = new TQVBoxLayout(this, 0, KDialog::spacingHint()); 01119 TQHBox* freqBox = new TQHBox(this); 01120 mLayout->addWidget(freqBox); 01121 TQHBox* box = new TQHBox(freqBox); // this is to control the TQWhatsThis text display area 01122 box->setSpacing(KDialog::spacingHint()); 01123 01124 TQLabel* label = new TQLabel(i18n("Recur e&very"), box); 01125 label->setFixedSize(label->sizeHint()); 01126 if (time) 01127 { 01128 mIntSpinBox = 0; 01129 mSpinBox = mTimeSpinBox = new TimeSpinBox(1, 5999, box); 01130 mTimeSpinBox->setFixedSize(mTimeSpinBox->sizeHint()); 01131 mTimeSpinBox->setReadOnly(readOnly); 01132 } 01133 else 01134 { 01135 mTimeSpinBox = 0; 01136 mSpinBox = mIntSpinBox = new SpinBox(1, 999, 1, box); 01137 mIntSpinBox->setFixedSize(mIntSpinBox->sizeHint()); 01138 mIntSpinBox->setReadOnly(readOnly); 01139 } 01140 connect(mSpinBox, TQT_SIGNAL(valueChanged(int)), TQT_SIGNAL(frequencyChanged())); 01141 label->setBuddy(mSpinBox); 01142 label = new TQLabel(freqText, box); 01143 label->setFixedSize(label->sizeHint()); 01144 box->setFixedSize(sizeHint()); 01145 TQWhatsThis::add(box, freqWhatsThis); 01146 01147 new TQWidget(freqBox); // left adjust the visible widgets 01148 freqBox->setFixedHeight(freqBox->sizeHint().height()); 01149 freqBox->setFocusProxy(mSpinBox); 01150 } 01151 01152 int Rule::frequency() const 01153 { 01154 if (mIntSpinBox) 01155 return mIntSpinBox->value(); 01156 if (mTimeSpinBox) 01157 return mTimeSpinBox->value(); 01158 return 0; 01159 } 01160 01161 void Rule::setFrequency(int n) 01162 { 01163 if (mIntSpinBox) 01164 mIntSpinBox->setValue(n); 01165 if (mTimeSpinBox) 01166 mTimeSpinBox->setValue(n); 01167 } 01168 01169 /****************************************************************************** 01170 * Save the state of all controls. 01171 */ 01172 void Rule::saveState() 01173 { 01174 mSavedFrequency = frequency(); 01175 } 01176 01177 /****************************************************************************** 01178 * Check whether any of the controls have changed state since initialisation. 01179 */ 01180 bool Rule::stateChanged() const 01181 { 01182 return (mSavedFrequency != frequency()); 01183 } 01184 01185 01186 /*============================================================================= 01187 = Class SubDailyRule 01188 = Sub-daily rule widget. 01189 =============================================================================*/ 01190 01191 SubDailyRule::SubDailyRule(bool readOnly, TQWidget* parent, const char* name) 01192 : Rule(i18n("hours:minutes"), 01193 i18n("Enter the number of hours and minutes between repetitions of the alarm"), 01194 true, readOnly, parent, name) 01195 { } 01196 01197 01198 /*============================================================================= 01199 = Class DayWeekRule 01200 = Daily/weekly rule widget base class. 01201 =============================================================================*/ 01202 01203 DayWeekRule::DayWeekRule(const TQString& freqText, const TQString& freqWhatsThis, const TQString& daysWhatsThis, 01204 bool readOnly, TQWidget* parent, const char* name) 01205 : Rule(freqText, freqWhatsThis, false, readOnly, parent, name), 01206 mSavedDays(7) 01207 { 01208 TQGridLayout* grid = new TQGridLayout(layout(), 1, 4, KDialog::spacingHint()); 01209 grid->setRowStretch(0, 1); 01210 01211 TQLabel* label = new TQLabel(i18n("On: Tuesday", "O&n:"), this); 01212 label->setFixedSize(label->sizeHint()); 01213 grid->addWidget(label, 0, 0, TQt::AlignRight | TQt::AlignTop); 01214 grid->addColSpacing(1, KDialog::spacingHint()); 01215 01216 // List the days of the week starting at the user's start day of the week. 01217 // Save the first day of the week, just in case it changes while the dialog is open. 01218 TQWidget* box = new TQWidget(this); // this is to control the TQWhatsThis text display area 01219 TQGridLayout* dgrid = new TQGridLayout(box, 4, 2, 0, KDialog::spacingHint()); 01220 const KCalendarSystem* calendar = TDEGlobal::locale()->calendar(); 01221 for (int i = 0; i < 7; ++i) 01222 { 01223 int day = KAlarm::localeDayInWeek_to_weekDay(i); 01224 mDayBox[i] = new CheckBox(calendar->weekDayName(day), box); 01225 mDayBox[i]->setFixedSize(mDayBox[i]->sizeHint()); 01226 mDayBox[i]->setReadOnly(readOnly); 01227 dgrid->addWidget(mDayBox[i], i%4, i/4, TQt::AlignAuto); 01228 } 01229 box->setFixedSize(box->sizeHint()); 01230 TQWhatsThis::add(box, daysWhatsThis); 01231 grid->addWidget(box, 0, 2, TQt::AlignAuto); 01232 label->setBuddy(mDayBox[0]); 01233 grid->setColStretch(3, 1); 01234 } 01235 01236 /****************************************************************************** 01237 * Fetch which days of the week have been ticked. 01238 */ 01239 TQBitArray DayWeekRule::days() const 01240 { 01241 TQBitArray ds(7); 01242 ds.fill(false); 01243 for (int i = 0; i < 7; ++i) 01244 if (mDayBox[i]->isChecked()) 01245 ds.setBit(KAlarm::localeDayInWeek_to_weekDay(i) - 1, 1); 01246 return ds; 01247 } 01248 01249 /****************************************************************************** 01250 * Tick/untick every day of the week. 01251 */ 01252 void DayWeekRule::setDays(bool tick) 01253 { 01254 for (int i = 0; i < 7; ++i) 01255 mDayBox[i]->setChecked(tick); 01256 } 01257 01258 /****************************************************************************** 01259 * Tick/untick each day of the week according to the specified bits. 01260 */ 01261 void DayWeekRule::setDays(const TQBitArray& days) 01262 { 01263 for (int i = 0; i < 7; ++i) 01264 { 01265 bool x = days.testBit(KAlarm::localeDayInWeek_to_weekDay(i) - 1); 01266 mDayBox[i]->setChecked(x); 01267 } 01268 } 01269 01270 /****************************************************************************** 01271 * Tick the specified day of the week, and untick all other days. 01272 */ 01273 void DayWeekRule::setDay(int dayOfWeek) 01274 { 01275 for (int i = 0; i < 7; ++i) 01276 mDayBox[i]->setChecked(false); 01277 if (dayOfWeek > 0 && dayOfWeek <= 7) 01278 mDayBox[KAlarm::weekDay_to_localeDayInWeek(dayOfWeek)]->setChecked(true); 01279 } 01280 01281 /****************************************************************************** 01282 * Validate: check that at least one day is selected. 01283 */ 01284 TQWidget* DayWeekRule::validate(TQString& errorMessage) 01285 { 01286 for (int i = 0; i < 7; ++i) 01287 if (mDayBox[i]->isChecked()) 01288 return 0; 01289 errorMessage = i18n("No day selected"); 01290 return mDayBox[0]; 01291 } 01292 01293 /****************************************************************************** 01294 * Save the state of all controls. 01295 */ 01296 void DayWeekRule::saveState() 01297 { 01298 Rule::saveState(); 01299 mSavedDays = days(); 01300 } 01301 01302 /****************************************************************************** 01303 * Check whether any of the controls have changed state since initialisation. 01304 */ 01305 bool DayWeekRule::stateChanged() const 01306 { 01307 return (Rule::stateChanged() 01308 || mSavedDays != days()); 01309 } 01310 01311 01312 /*============================================================================= 01313 = Class DailyRule 01314 = Daily rule widget. 01315 =============================================================================*/ 01316 01317 DailyRule::DailyRule(bool readOnly, TQWidget* parent, const char* name) 01318 : DayWeekRule(i18n("day(s)"), 01319 i18n("Enter the number of days between repetitions of the alarm"), 01320 i18n("Select the days of the week on which the alarm is allowed to occur"), 01321 readOnly, parent, name) 01322 { } 01323 01324 01325 /*============================================================================= 01326 = Class WeeklyRule 01327 = Weekly rule widget. 01328 =============================================================================*/ 01329 01330 WeeklyRule::WeeklyRule(bool readOnly, TQWidget* parent, const char* name) 01331 : DayWeekRule(i18n("week(s)"), 01332 i18n("Enter the number of weeks between repetitions of the alarm"), 01333 i18n("Select the days of the week on which to repeat the alarm"), 01334 readOnly, parent, name) 01335 { } 01336 01337 01338 /*============================================================================= 01339 = Class MonthYearRule 01340 = Monthly/yearly rule widget base class. 01341 =============================================================================*/ 01342 01343 MonthYearRule::MonthYearRule(const TQString& freqText, const TQString& freqWhatsThis, bool allowEveryWeek, 01344 bool readOnly, TQWidget* parent, const char* name) 01345 : Rule(freqText, freqWhatsThis, false, readOnly, parent, name), 01346 mEveryWeek(allowEveryWeek) 01347 { 01348 mButtonGroup = new ButtonGroup(this); 01349 mButtonGroup->hide(); 01350 01351 // Month day selector 01352 TQHBox* box = new TQHBox(this); 01353 box->setSpacing(KDialog::spacingHint()); 01354 layout()->addWidget(box); 01355 01356 mDayButton = new RadioButton(i18n("On day number in the month", "O&n day"), box); 01357 mDayButton->setFixedSize(mDayButton->sizeHint()); 01358 mDayButton->setReadOnly(readOnly); 01359 mDayButtonId = mButtonGroup->insert(mDayButton); 01360 TQWhatsThis::add(mDayButton, i18n("Repeat the alarm on the selected day of the month")); 01361 01362 mDayCombo = new ComboBox(false, box); 01363 mDayCombo->setSizeLimit(11); 01364 for (int i = 0; i < 31; ++i) 01365 mDayCombo->insertItem(TQString::number(i + 1)); 01366 mDayCombo->insertItem(i18n("Last day of month", "Last")); 01367 mDayCombo->setFixedSize(mDayCombo->sizeHint()); 01368 mDayCombo->setReadOnly(readOnly); 01369 TQWhatsThis::add(mDayCombo, i18n("Select the day of the month on which to repeat the alarm")); 01370 mDayButton->setFocusWidget(mDayCombo); 01371 connect(mDayCombo, TQT_SIGNAL(activated(int)), TQT_SLOT(slotDaySelected(int))); 01372 01373 box->setStretchFactor(new TQWidget(box), 1); // left adjust the controls 01374 box->setFixedHeight(box->sizeHint().height()); 01375 01376 // Month position selector 01377 box = new TQHBox(this); 01378 box->setSpacing(KDialog::spacingHint()); 01379 layout()->addWidget(box); 01380 01381 mPosButton = new RadioButton(i18n("On the 1st Tuesday", "On t&he"), box); 01382 mPosButton->setFixedSize(mPosButton->sizeHint()); 01383 mPosButton->setReadOnly(readOnly); 01384 mPosButtonId = mButtonGroup->insert(mPosButton); 01385 TQWhatsThis::add(mPosButton, 01386 i18n("Repeat the alarm on one day of the week, in the selected week of the month")); 01387 01388 mWeekCombo = new ComboBox(false, box); 01389 mWeekCombo->insertItem(i18n("1st")); 01390 mWeekCombo->insertItem(i18n("2nd")); 01391 mWeekCombo->insertItem(i18n("3rd")); 01392 mWeekCombo->insertItem(i18n("4th")); 01393 mWeekCombo->insertItem(i18n("5th")); 01394 mWeekCombo->insertItem(i18n("Last Monday in March", "Last")); 01395 mWeekCombo->insertItem(i18n("2nd Last")); 01396 mWeekCombo->insertItem(i18n("3rd Last")); 01397 mWeekCombo->insertItem(i18n("4th Last")); 01398 mWeekCombo->insertItem(i18n("5th Last")); 01399 if (mEveryWeek) 01400 { 01401 mWeekCombo->insertItem(i18n("Every (Monday...) in month", "Every")); 01402 mWeekCombo->setSizeLimit(11); 01403 } 01404 TQWhatsThis::add(mWeekCombo, i18n("Select the week of the month in which to repeat the alarm")); 01405 mWeekCombo->setFixedSize(mWeekCombo->sizeHint()); 01406 mWeekCombo->setReadOnly(readOnly); 01407 mPosButton->setFocusWidget(mWeekCombo); 01408 01409 mDayOfWeekCombo = new ComboBox(false, box); 01410 const KCalendarSystem* calendar = TDEGlobal::locale()->calendar(); 01411 for (int i = 0; i < 7; ++i) 01412 { 01413 int day = KAlarm::localeDayInWeek_to_weekDay(i); 01414 mDayOfWeekCombo->insertItem(calendar->weekDayName(day)); 01415 } 01416 mDayOfWeekCombo->setReadOnly(readOnly); 01417 TQWhatsThis::add(mDayOfWeekCombo, i18n("Select the day of the week on which to repeat the alarm")); 01418 01419 box->setStretchFactor(new TQWidget(box), 1); // left adjust the controls 01420 box->setFixedHeight(box->sizeHint().height()); 01421 connect(mButtonGroup, TQT_SIGNAL(buttonSet(int)), TQT_SLOT(clicked(int))); 01422 } 01423 01424 MonthYearRule::DayPosType MonthYearRule::type() const 01425 { 01426 return (mButtonGroup->selectedId() == mDayButtonId) ? DATE : POS; 01427 } 01428 01429 void MonthYearRule::setType(MonthYearRule::DayPosType type) 01430 { 01431 mButtonGroup->setButton(type == DATE ? mDayButtonId : mPosButtonId); 01432 } 01433 01434 void MonthYearRule::setDefaultValues(int dayOfMonth, int dayOfWeek) 01435 { 01436 --dayOfMonth; 01437 mDayCombo->setCurrentItem(dayOfMonth); 01438 mWeekCombo->setCurrentItem(dayOfMonth / 7); 01439 mDayOfWeekCombo->setCurrentItem(KAlarm::weekDay_to_localeDayInWeek(dayOfWeek)); 01440 } 01441 01442 int MonthYearRule::date() const 01443 { 01444 int daynum = mDayCombo->currentItem() + 1; 01445 return (daynum <= 31) ? daynum : 31 - daynum; 01446 } 01447 01448 int MonthYearRule::week() const 01449 { 01450 int weeknum = mWeekCombo->currentItem() + 1; 01451 return (weeknum <= 5) ? weeknum : (weeknum == 11) ? 0 : 5 - weeknum; 01452 } 01453 01454 int MonthYearRule::dayOfWeek() const 01455 { 01456 return KAlarm::localeDayInWeek_to_weekDay(mDayOfWeekCombo->currentItem()); 01457 } 01458 01459 void MonthYearRule::setDate(int dayOfMonth) 01460 { 01461 mButtonGroup->setButton(mDayButtonId); 01462 mDayCombo->setCurrentItem(dayOfMonth > 0 ? dayOfMonth - 1 : dayOfMonth < 0 ? 30 - dayOfMonth : 0); // day 0 shouldn't ever occur 01463 } 01464 01465 void MonthYearRule::setPosition(int week, int dayOfWeek) 01466 { 01467 mButtonGroup->setButton(mPosButtonId); 01468 mWeekCombo->setCurrentItem((week > 0) ? week - 1 : (week < 0) ? 4 - week : mEveryWeek ? 10 : 0); 01469 mDayOfWeekCombo->setCurrentItem(KAlarm::weekDay_to_localeDayInWeek(dayOfWeek)); 01470 } 01471 01472 void MonthYearRule::enableSelection(DayPosType type) 01473 { 01474 bool date = (type == DATE); 01475 mDayCombo->setEnabled(date); 01476 mWeekCombo->setEnabled(!date); 01477 mDayOfWeekCombo->setEnabled(!date); 01478 } 01479 01480 void MonthYearRule::clicked(int id) 01481 { 01482 enableSelection(id == mDayButtonId ? DATE : POS); 01483 } 01484 01485 void MonthYearRule::slotDaySelected(int index) 01486 { 01487 daySelected(index <= 30 ? index + 1 : 30 - index); 01488 } 01489 01490 /****************************************************************************** 01491 * Save the state of all controls. 01492 */ 01493 void MonthYearRule::saveState() 01494 { 01495 Rule::saveState(); 01496 mSavedType = type(); 01497 if (mSavedType == DATE) 01498 mSavedDay = date(); 01499 else 01500 { 01501 mSavedWeek = week(); 01502 mSavedWeekDay = dayOfWeek(); 01503 } 01504 } 01505 01506 /****************************************************************************** 01507 * Check whether any of the controls have changed state since initialisation. 01508 */ 01509 bool MonthYearRule::stateChanged() const 01510 { 01511 if (Rule::stateChanged() 01512 || mSavedType != type()) 01513 return true; 01514 if (mSavedType == DATE) 01515 { 01516 if (mSavedDay != date()) 01517 return true; 01518 } 01519 else 01520 { 01521 if (mSavedWeek != week() 01522 || mSavedWeekDay != dayOfWeek()) 01523 return true; 01524 } 01525 return false; 01526 } 01527 01528 01529 /*============================================================================= 01530 = Class MonthlyRule 01531 = Monthly rule widget. 01532 =============================================================================*/ 01533 01534 MonthlyRule::MonthlyRule(bool readOnly, TQWidget* parent, const char* name) 01535 : MonthYearRule(i18n("month(s)"), 01536 i18n("Enter the number of months between repetitions of the alarm"), 01537 false, readOnly, parent, name) 01538 { } 01539 01540 01541 /*============================================================================= 01542 = Class YearlyRule 01543 = Yearly rule widget. 01544 =============================================================================*/ 01545 01546 YearlyRule::YearlyRule(bool readOnly, TQWidget* parent, const char* name) 01547 : MonthYearRule(i18n("year(s)"), 01548 i18n("Enter the number of years between repetitions of the alarm"), 01549 true, readOnly, parent, name) 01550 { 01551 // Set up the month selection widgets 01552 TQBoxLayout* hlayout = new TQHBoxLayout(layout(), KDialog::spacingHint()); 01553 TQLabel* label = new TQLabel(i18n("List of months to select", "Months:"), this); 01554 label->setFixedSize(label->sizeHint()); 01555 hlayout->addWidget(label, 0, TQt::AlignAuto | TQt::AlignTop); 01556 01557 // List the months of the year. 01558 TQWidget* w = new TQWidget(this); // this is to control the TQWhatsThis text display area 01559 hlayout->addWidget(w, 1, TQt::AlignAuto); 01560 TQGridLayout* grid = new TQGridLayout(w, 4, 3, 0, KDialog::spacingHint()); 01561 const KCalendarSystem* calendar = TDEGlobal::locale()->calendar(); 01562 int year = TQDate::currentDate().year(); 01563 for (int i = 0; i < 12; ++i) 01564 { 01565 mMonthBox[i] = new CheckBox(calendar->monthName(i + 1, year, true), w); 01566 mMonthBox[i]->setFixedSize(mMonthBox[i]->sizeHint()); 01567 mMonthBox[i]->setReadOnly(readOnly); 01568 grid->addWidget(mMonthBox[i], i%3, i/3, TQt::AlignAuto); 01569 } 01570 connect(mMonthBox[1], TQT_SIGNAL(toggled(bool)), TQT_SLOT(enableFeb29())); 01571 w->setFixedHeight(w->sizeHint().height()); 01572 TQWhatsThis::add(w, i18n("Select the months of the year in which to repeat the alarm")); 01573 01574 // February 29th handling option 01575 TQHBox* f29box = new TQHBox(this); 01576 layout()->addWidget(f29box); 01577 TQHBox* box = new TQHBox(f29box); // this is to control the TQWhatsThis text display area 01578 box->setSpacing(KDialog::spacingHint()); 01579 mFeb29Label = new TQLabel(i18n("February 2&9th alarm in non-leap years:"), box); 01580 mFeb29Label->setFixedSize(mFeb29Label->sizeHint()); 01581 mFeb29Combo = new ComboBox(false, box); 01582 mFeb29Combo->insertItem(i18n("No date", "None")); 01583 mFeb29Combo->insertItem(i18n("1st March (short form)", "1 Mar")); 01584 mFeb29Combo->insertItem(i18n("28th February (short form)", "28 Feb")); 01585 mFeb29Combo->setFixedSize(mFeb29Combo->sizeHint()); 01586 mFeb29Combo->setReadOnly(readOnly); 01587 mFeb29Label->setBuddy(mFeb29Combo); 01588 box->setFixedSize(box->sizeHint()); 01589 TQWhatsThis::add(box, 01590 i18n("Select which date, if any, the February 29th alarm should trigger in non-leap years")); 01591 new TQWidget(f29box); // left adjust the visible widgets 01592 f29box->setFixedHeight(f29box->sizeHint().height()); 01593 } 01594 01595 void YearlyRule::setDefaultValues(int dayOfMonth, int dayOfWeek, int month) 01596 { 01597 MonthYearRule::setDefaultValues(dayOfMonth, dayOfWeek); 01598 --month; 01599 for (int i = 0; i < 12; ++i) 01600 mMonthBox[i]->setChecked(i == month); 01601 setFeb29Type(Preferences::defaultFeb29Type()); 01602 daySelected(dayOfMonth); // enable/disable month checkboxes as appropriate 01603 } 01604 01605 /****************************************************************************** 01606 * Fetch which months have been checked (1 - 12). 01607 * Reply = true if February has been checked. 01608 */ 01609 TQValueList<int> YearlyRule::months() const 01610 { 01611 TQValueList<int> mnths; 01612 for (int i = 0; i < 12; ++i) 01613 if (mMonthBox[i]->isChecked() && mMonthBox[i]->isEnabled()) 01614 mnths.append(i + 1); 01615 return mnths; 01616 } 01617 01618 /****************************************************************************** 01619 * Check/uncheck each month of the year according to the specified list. 01620 */ 01621 void YearlyRule::setMonths(const TQValueList<int>& mnths) 01622 { 01623 bool checked[12]; 01624 for (int i = 0; i < 12; ++i) 01625 checked[i] = false; 01626 for (TQValueListConstIterator<int> it = mnths.begin(); it != mnths.end(); ++it) 01627 checked[(*it) - 1] = true; 01628 for (int i = 0; i < 12; ++i) 01629 mMonthBox[i]->setChecked(checked[i]); 01630 enableFeb29(); 01631 } 01632 01633 /****************************************************************************** 01634 * Return the date for February 29th alarms in non-leap years. 01635 */ 01636 KARecurrence::Feb29Type YearlyRule::feb29Type() const 01637 { 01638 if (mFeb29Combo->isEnabled()) 01639 { 01640 switch (mFeb29Combo->currentItem()) 01641 { 01642 case 1: return KARecurrence::FEB29_MAR1; 01643 case 2: return KARecurrence::FEB29_FEB28; 01644 default: break; 01645 } 01646 } 01647 return KARecurrence::FEB29_FEB29; 01648 } 01649 01650 /****************************************************************************** 01651 * Set the date for February 29th alarms to trigger in non-leap years. 01652 */ 01653 void YearlyRule::setFeb29Type(KARecurrence::Feb29Type type) 01654 { 01655 int index; 01656 switch (type) 01657 { 01658 default: 01659 case KARecurrence::FEB29_FEB29: index = 0; break; 01660 case KARecurrence::FEB29_MAR1: index = 1; break; 01661 case KARecurrence::FEB29_FEB28: index = 2; break; 01662 } 01663 mFeb29Combo->setCurrentItem(index); 01664 } 01665 01666 /****************************************************************************** 01667 * Validate: check that at least one month is selected. 01668 */ 01669 TQWidget* YearlyRule::validate(TQString& errorMessage) 01670 { 01671 for (int i = 0; i < 12; ++i) 01672 if (mMonthBox[i]->isChecked() && mMonthBox[i]->isEnabled()) 01673 return 0; 01674 errorMessage = i18n("No month selected"); 01675 return mMonthBox[0]; 01676 } 01677 01678 /****************************************************************************** 01679 * Called when a yearly recurrence type radio button is clicked, 01680 * to enable/disable month checkboxes as appropriate for the date selected. 01681 */ 01682 void YearlyRule::clicked(int id) 01683 { 01684 MonthYearRule::clicked(id); 01685 daySelected(buttonType(id) == DATE ? date() : 1); 01686 } 01687 01688 /****************************************************************************** 01689 * Called when a day of the month is selected in a yearly recurrence, to 01690 * disable months for which the day is out of range. 01691 */ 01692 void YearlyRule::daySelected(int day) 01693 { 01694 mMonthBox[1]->setEnabled(day <= 29); // February 01695 bool enable = (day != 31); 01696 mMonthBox[3]->setEnabled(enable); // April 01697 mMonthBox[5]->setEnabled(enable); // June 01698 mMonthBox[8]->setEnabled(enable); // September 01699 mMonthBox[10]->setEnabled(enable); // November 01700 enableFeb29(); 01701 } 01702 01703 /****************************************************************************** 01704 * Enable/disable the February 29th combo box depending on whether February 01705 * 29th is selected. 01706 */ 01707 void YearlyRule::enableFeb29() 01708 { 01709 bool enable = (type() == DATE && date() == 29 && mMonthBox[1]->isChecked() && mMonthBox[1]->isEnabled()); 01710 mFeb29Label->setEnabled(enable); 01711 mFeb29Combo->setEnabled(enable); 01712 } 01713 01714 /****************************************************************************** 01715 * Save the state of all controls. 01716 */ 01717 void YearlyRule::saveState() 01718 { 01719 MonthYearRule::saveState(); 01720 mSavedMonths = months(); 01721 mSavedFeb29Type = feb29Type(); 01722 } 01723 01724 /****************************************************************************** 01725 * Check whether any of the controls have changed state since initialisation. 01726 */ 01727 bool YearlyRule::stateChanged() const 01728 { 01729 return (MonthYearRule::stateChanged() 01730 || mSavedMonths != months() 01731 || mSavedFeb29Type != feb29Type()); 01732 }
