00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "kalarm.h"
00025
00026 #include <qtooltip.h>
00027 #include <qlayout.h>
00028 #include <qvbox.h>
00029 #include <qwidgetstack.h>
00030 #include <qlistbox.h>
00031 #include <qframe.h>
00032 #include <qlabel.h>
00033 #include <qpushbutton.h>
00034 #include <qlineedit.h>
00035 #include <qwhatsthis.h>
00036
00037 #include <kglobal.h>
00038 #include <klocale.h>
00039 #include <kcalendarsystem.h>
00040 #include <kiconloader.h>
00041 #include <kdialog.h>
00042 #include <kmessagebox.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
00068
00069 QString RecurrenceEdit::i18n_Norecur() { return i18n("No recurrence"); }
00070 QString RecurrenceEdit::i18n_NoRecur() { return i18n("No Recurrence"); }
00071 QString RecurrenceEdit::i18n_AtLogin() { return i18n("At Login"); }
00072 QString RecurrenceEdit::i18n_l_Atlogin() { return i18n("At &login"); }
00073 QString RecurrenceEdit::i18n_HourlyMinutely() { return i18n("Hourly/Minutely"); }
00074 QString RecurrenceEdit::i18n_u_HourlyMinutely() { return i18n("Ho&urly/Minutely"); }
00075 QString RecurrenceEdit::i18n_Daily() { return i18n("Daily"); }
00076 QString RecurrenceEdit::i18n_d_Daily() { return i18n("&Daily"); }
00077 QString RecurrenceEdit::i18n_Weekly() { return i18n("Weekly"); }
00078 QString RecurrenceEdit::i18n_w_Weekly() { return i18n("&Weekly"); }
00079 QString RecurrenceEdit::i18n_Monthly() { return i18n("Monthly"); }
00080 QString RecurrenceEdit::i18n_m_Monthly() { return i18n("&Monthly"); }
00081 QString RecurrenceEdit::i18n_Yearly() { return i18n("Yearly"); }
00082 QString RecurrenceEdit::i18n_y_Yearly() { return i18n("&Yearly"); }
00083
00084
00085 RecurrenceEdit::RecurrenceEdit(bool readOnly, QWidget* parent, const char* name)
00086 : QFrame(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 QBoxLayout* layout;
00097 QVBoxLayout* topLayout = new QVBoxLayout(this, 0, KDialog::spacingHint());
00098
00099
00100
00101
00102
00103
00104
00105
00106 QGroupBox* recurGroup = new QGroupBox(1, Qt::Vertical, i18n("Recurrence Rule"), this, "recurGroup");
00107 topLayout->addWidget(recurGroup);
00108 QFrame* ruleFrame = new QFrame(recurGroup, "ruleFrame");
00109 layout = new QVBoxLayout(ruleFrame, 0);
00110 layout->addSpacing(KDialog::spacingHint()/2);
00111
00112 layout = new QHBoxLayout(layout, 0);
00113 QBoxLayout* lay = new QVBoxLayout(layout, 0);
00114 mRuleButtonGroup = new ButtonGroup(1, Qt::Horizontal, ruleFrame);
00115 mRuleButtonGroup->setInsideMargin(0);
00116 mRuleButtonGroup->setFrameStyle(QFrame::NoFrame);
00117 lay->addWidget(mRuleButtonGroup);
00118 lay->addStretch();
00119 connect(mRuleButtonGroup, SIGNAL(buttonSet(int)), SLOT(periodClicked(int)));
00120
00121 mNoneButton = new RadioButton(i18n_Norecur(), mRuleButtonGroup);
00122 mNoneButton->setFixedSize(mNoneButton->sizeHint());
00123 mNoneButton->setReadOnly(mReadOnly);
00124 QWhatsThis::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 QWhatsThis::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 QWhatsThis::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 QWhatsThis::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 QWhatsThis::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 QWhatsThis::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 QWhatsThis::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
00172 mSubRepetition = new RepetitionButton(i18n("Sub-Repetition"), true, ruleFrame);
00173 mSubRepetition->setFixedSize(mSubRepetition->sizeHint());
00174 mSubRepetition->setReadOnly(mReadOnly);
00175 connect(mSubRepetition, SIGNAL(needsInitialisation()), SIGNAL(repeatNeedsInitialisation()));
00176 connect(mSubRepetition, SIGNAL(changed()), SIGNAL(frequencyChanged()));
00177 QWhatsThis::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 QVBoxLayout(layout);
00182
00183 lay->addStretch();
00184 layout = new QHBoxLayout(lay);
00185
00186 layout->addSpacing(KDialog::marginHint());
00187 QFrame* divider = new QFrame(ruleFrame);
00188 divider->setFrameStyle(QFrame::VLine | QFrame::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, SIGNAL(frequencyChanged()), this, SIGNAL(frequencyChanged()));
00200 connect(mDailyRule, SIGNAL(frequencyChanged()), this, SIGNAL(frequencyChanged()));
00201 connect(mWeeklyRule, SIGNAL(frequencyChanged()), this, SIGNAL(frequencyChanged()));
00202 connect(mMonthlyRule, SIGNAL(frequencyChanged()), this, SIGNAL(frequencyChanged()));
00203 connect(mYearlyRule, SIGNAL(frequencyChanged()), this, SIGNAL(frequencyChanged()));
00204
00205 mRuleStack = new QWidgetStack(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
00217
00218
00219 mRangeButtonGroup = new ButtonGroup(i18n("Recurrence End"), this, "mRangeButtonGroup");
00220 connect(mRangeButtonGroup, SIGNAL(buttonSet(int)), SLOT(rangeTypeClicked()));
00221 topLayout->addWidget(mRangeButtonGroup);
00222
00223 QVBoxLayout* vlayout = new QVBoxLayout(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 QWhatsThis::add(mNoEndDateButton, i18n("Repeat the alarm indefinitely"));
00229 vlayout->addWidget(mNoEndDateButton, 1, Qt::AlignAuto);
00230 QSize size = mNoEndDateButton->size();
00231
00232 layout = new QHBoxLayout(vlayout, KDialog::spacingHint());
00233 mRepeatCountButton = new RadioButton(i18n("End a&fter:"), mRangeButtonGroup);
00234 mRepeatCountButton->setReadOnly(mReadOnly);
00235 QWhatsThis::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, SIGNAL(valueChanged(int)), SLOT(repeatCountChanged(int)));
00243 QWhatsThis::add(mRepeatCountEntry,
00244 i18n("Enter the total number of times to trigger the alarm"));
00245 mRepeatCountButton->setFocusWidget(mRepeatCountEntry);
00246 mRepeatCountLabel = new QLabel(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 QHBoxLayout(vlayout, KDialog::spacingHint());
00256 mEndDateButton = new RadioButton(i18n("End &by:"), mRangeButtonGroup);
00257 mEndDateButton->setReadOnly(mReadOnly);
00258 QWhatsThis::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 QWhatsThis::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 QString lastTimeText = i18n("Enter the last time to repeat the alarm.");
00271 QWhatsThis::add(mEndTimeEdit, QString("%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, SIGNAL(toggled(bool)), SLOT(slotAnyTimeToggled(bool)));
00276 QWhatsThis::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
00287 mRepeatCountButton->setFixedSize(size);
00288 mEndDateButton->setFixedSize(size);
00289
00290
00291
00292
00293 mExceptionGroup = new QGroupBox(i18n("E&xceptions"), this, "mExceptionGroup");
00294 topLayout->addWidget(mExceptionGroup);
00295 topLayout->setStretchFactor(mExceptionGroup, 2);
00296 vlayout = new QVBoxLayout(mExceptionGroup, KDialog::marginHint(), KDialog::spacingHint());
00297 vlayout->addSpacing(fontMetrics().lineSpacing()/2);
00298 layout = new QHBoxLayout(vlayout, KDialog::spacingHint());
00299 vlayout = new QVBoxLayout(layout);
00300
00301 mExceptionDateList = new QListBox(mExceptionGroup);
00302 mExceptionDateList->setSizePolicy(QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding));
00303 connect(mExceptionDateList, SIGNAL(selectionChanged()), SLOT(enableExceptionButtons()));
00304 QWhatsThis::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 QVBoxLayout(layout);
00317 mExceptionDateEdit = new DateEdit(mExceptionGroup);
00318 mExceptionDateEdit->setFixedSize(mExceptionDateEdit->sizeHint());
00319 mExceptionDateEdit->setDate(QDate::currentDate());
00320 QWhatsThis::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 QHBoxLayout(vlayout, KDialog::spacingHint());
00326 QPushButton* button = new QPushButton(i18n("Add"), mExceptionGroup);
00327 button->setFixedSize(button->sizeHint());
00328 connect(button, SIGNAL(clicked()), SLOT(addException()));
00329 QWhatsThis::add(button,
00330 i18n("Add the date entered above to the exceptions list"));
00331 layout->addWidget(button);
00332
00333 mChangeExceptionButton = new QPushButton(i18n("Change"), mExceptionGroup);
00334 mChangeExceptionButton->setFixedSize(mChangeExceptionButton->sizeHint());
00335 connect(mChangeExceptionButton, SIGNAL(clicked()), SLOT(changeException()));
00336 QWhatsThis::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 QPushButton(i18n("Delete"), mExceptionGroup);
00341 mDeleteExceptionButton->setFixedSize(mDeleteExceptionButton->sizeHint());
00342 connect(mDeleteExceptionButton, SIGNAL(clicked()), SLOT(deleteException()));
00343 QWhatsThis::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
00353
00354
00355 QWidget* RecurrenceEdit::checkData(const QDateTime& startDateTime, QString& errorMessage) const
00356 {
00357 if (mAtLoginButton->isOn())
00358 return 0;
00359 const_cast<RecurrenceEdit*>(this)->mCurrStartDateTime = startDateTime;
00360 if (mEndDateButton->isChecked())
00361 {
00362 QWidget* errWidget = 0;
00363 bool noTime = !mEndTimeEdit->isEnabled();
00364 QDate endDate = mEndDateEdit->date();
00365 if (endDate < startDateTime.date())
00366 errWidget = mEndDateEdit;
00367 else if (!noTime && QDateTime(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
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 QButton* button = mRuleButtonGroup->selected();
00456 mEndTimeEdit->setEnabled(button == mAtLoginButton && !on
00457 || button == mSubDailyButton && mEndDateButton->isChecked());
00458 }
00459
00460
00461
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(QShowEvent*)
00476 {
00477 if (mRule)
00478 mRule->setFrequencyFocus();
00479 else
00480 mRuleButtonGroup->selected()->setFocus();
00481 emit shown();
00482 }
00483
00484
00485
00486
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
00498
00499
00500
00501
00502
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:
00511 maxDuration = 0;
00512 break;
00513 default:
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
00527
00528 void RecurrenceEdit::activateSubRepetition()
00529 {
00530 mSubRepetition->activate();
00531 }
00532
00533
00534
00535
00536
00537 void RecurrenceEdit::repeatCountChanged(int value)
00538 {
00539 if (value > 0 && mRepeatCountEntry->minValue() == 0)
00540 mRepeatCountEntry->setMinValue(1);
00541 }
00542
00543
00544
00545
00546
00547 void RecurrenceEdit::addException()
00548 {
00549 if (!mExceptionDateEdit || !mExceptionDateEdit->isValid())
00550 return;
00551 QDate date = mExceptionDateEdit->date();
00552 QValueList<QDate>::Iterator it;
00553 int index = 0;
00554 bool insert = true;
00555 for (it = mExceptionDates.begin(); it != mExceptionDates.end(); ++index, ++it)
00556 {
00557 if (date <= *it)
00558 {
00559 insert = (date != *it);
00560 break;
00561 }
00562 }
00563 if (insert)
00564 {
00565 mExceptionDates.insert(it, date);
00566 mExceptionDateList->insertItem(KGlobal::locale()->formatDate(date), index);
00567 }
00568 mExceptionDateList->setCurrentItem(index);
00569 enableExceptionButtons();
00570 }
00571
00572
00573
00574
00575
00576 void RecurrenceEdit::changeException()
00577 {
00578 if (!mExceptionDateEdit || !mExceptionDateEdit->isValid())
00579 return;
00580 int index = mExceptionDateList->currentItem();
00581 if (index >= 0 && mExceptionDateList->isSelected(index))
00582 {
00583 QDate olddate = mExceptionDates[index];
00584 QDate newdate = mExceptionDateEdit->date();
00585 if (newdate != olddate)
00586 {
00587 mExceptionDates.remove(mExceptionDates.at(index));
00588 mExceptionDateList->removeItem(index);
00589 addException();
00590 }
00591 }
00592 }
00593
00594
00595
00596
00597 void RecurrenceEdit::deleteException()
00598 {
00599 int index = mExceptionDateList->currentItem();
00600 if (index >= 0 && mExceptionDateList->isSelected(index))
00601 {
00602 mExceptionDates.remove(mExceptionDates.at(index));
00603 mExceptionDateList->removeItem(index);
00604 enableExceptionButtons();
00605 }
00606 }
00607
00608
00609
00610
00611
00612 void RecurrenceEdit::enableExceptionButtons()
00613 {
00614 int index = mExceptionDateList->currentItem();
00615 bool enable = (index >= 0 && mExceptionDateList->isSelected(index));
00616 if (mDeleteExceptionButton)
00617 mDeleteExceptionButton->setEnabled(enable);
00618 if (mChangeExceptionButton)
00619 mChangeExceptionButton->setEnabled(enable);
00620
00621
00622 mExceptionDateList->setFocusPolicy(mExceptionDateList->count() ? QWidget::WheelFocus : QWidget::NoFocus);
00623 }
00624
00625
00626
00627
00628 void RecurrenceEdit::setStartDate(const QDate& start, const QDate& today)
00629 {
00630 if (!mReadOnly)
00631 {
00632 setRuleDefaults(start);
00633 if (start < today)
00634 {
00635 mEndDateEdit->setMinDate(today);
00636 if (mExceptionDateEdit)
00637 mExceptionDateEdit->setMinDate(today);
00638 }
00639 else
00640 {
00641 const QString startString = i18n("Date cannot be earlier than start date", "start date");
00642 mEndDateEdit->setMinDate(start, startString);
00643 if (mExceptionDateEdit)
00644 mExceptionDateEdit->setMinDate(start, startString);
00645 }
00646 }
00647 }
00648
00649
00650
00651
00652 void RecurrenceEdit::setDefaultEndDate(const QDate& end)
00653 {
00654 if (!mEndDateButton->isOn())
00655 mEndDateEdit->setDate(end);
00656 }
00657
00658 void RecurrenceEdit::setEndDateTime(const DateTime& end)
00659 {
00660 mEndDateEdit->setDate(end.date());
00661 mEndTimeEdit->setValue(end.time());
00662 mEndTimeEdit->setEnabled(!end.isDateOnly());
00663 mEndAnyTimeCheckBox->setChecked(end.isDateOnly());
00664 }
00665
00666 DateTime RecurrenceEdit::endDateTime() const
00667 {
00668 if (mRuleButtonGroup->selected() == mAtLoginButton && mEndAnyTimeCheckBox->isChecked())
00669 return DateTime(mEndDateEdit->date());
00670 return DateTime(mEndDateEdit->date(), mEndTimeEdit->time());
00671 }
00672
00673
00674
00675
00676 void RecurrenceEdit::setDefaults(const QDateTime& from)
00677 {
00678 mCurrStartDateTime = from;
00679 QDate fromDate = from.date();
00680 mNoEndDateButton->setChecked(true);
00681
00682 mSubDailyRule->setFrequency(1);
00683 mDailyRule->setFrequency(1);
00684 mWeeklyRule->setFrequency(1);
00685 mMonthlyRule->setFrequency(1);
00686 mYearlyRule->setFrequency(1);
00687
00688 setRuleDefaults(fromDate);
00689 mMonthlyRule->setType(MonthYearRule::DATE);
00690 mYearlyRule->setType(MonthYearRule::DATE);
00691
00692 mEndDateEdit->setDate(fromDate);
00693
00694 mNoEmitTypeChanged = true;
00695 int button;
00696 switch (Preferences::defaultRecurPeriod())
00697 {
00698 case AT_LOGIN: button = mAtLoginButtonId; break;
00699 case ANNUAL: button = mYearlyButtonId; break;
00700 case MONTHLY: button = mMonthlyButtonId; break;
00701 case WEEKLY: button = mWeeklyButtonId; break;
00702 case DAILY: button = mDailyButtonId; break;
00703 case SUBDAILY: button = mSubDailyButtonId; break;
00704 case NO_RECUR:
00705 default: button = mNoneButtonId; break;
00706 }
00707 mRuleButtonGroup->setButton(button);
00708 mNoEmitTypeChanged = false;
00709 rangeTypeClicked();
00710 enableExceptionButtons();
00711
00712 saveState();
00713 }
00714
00715
00716
00717
00718
00719 void RecurrenceEdit::setRuleDefaults(const QDate& fromDate)
00720 {
00721 int day = fromDate.day();
00722 int dayOfWeek = fromDate.dayOfWeek();
00723 int month = fromDate.month();
00724 if (!mDailyShown)
00725 mDailyRule->setDays(true);
00726 if (!mWeeklyShown)
00727 mWeeklyRule->setDay(dayOfWeek);
00728 if (!mMonthlyShown)
00729 mMonthlyRule->setDefaultValues(day, dayOfWeek);
00730 if (!mYearlyShown)
00731 mYearlyRule->setDefaultValues(day, dayOfWeek, month);
00732 }
00733
00734
00735
00736
00737
00738
00739 void RecurrenceEdit::set(const KAEvent& event, bool keepDuration)
00740 {
00741 setDefaults(event.mainDateTime().dateTime());
00742 if (event.repeatAtLogin())
00743 {
00744 mRuleButtonGroup->setButton(mAtLoginButtonId);
00745 mEndDateButton->setChecked(true);
00746 return;
00747 }
00748 mRuleButtonGroup->setButton(mNoneButtonId);
00749 KARecurrence* recurrence = event.recurrence();
00750 if (!recurrence)
00751 return;
00752 KARecurrence::Type rtype = recurrence->type();
00753 switch (rtype)
00754 {
00755 case KARecurrence::MINUTELY:
00756 mRuleButtonGroup->setButton(mSubDailyButtonId);
00757 break;
00758
00759 case KARecurrence::DAILY:
00760 {
00761 mRuleButtonGroup->setButton(mDailyButtonId);
00762 QBitArray rDays = recurrence->days();
00763 bool set = false;
00764 for (int i = 0; i < 7 && !set; ++i)
00765 set = rDays.testBit(i);
00766 if (set)
00767 mDailyRule->setDays(rDays);
00768 else
00769 mDailyRule->setDays(true);
00770 break;
00771 }
00772 case KARecurrence::WEEKLY:
00773 {
00774 mRuleButtonGroup->setButton(mWeeklyButtonId);
00775 QBitArray rDays = recurrence->days();
00776 mWeeklyRule->setDays(rDays);
00777 break;
00778 }
00779 case KARecurrence::MONTHLY_POS:
00780 {
00781 QValueList<RecurrenceRule::WDayPos> posns = recurrence->monthPositions();
00782 int i = posns.first().pos();
00783 if (!i)
00784 {
00785
00786
00787 mRuleButtonGroup->setButton(mWeeklyButtonId);
00788 mWeeklyRule->setFrequency(recurrence->frequency());
00789 QBitArray rDays(7);
00790 for (QValueList<RecurrenceRule::WDayPos>::ConstIterator it = posns.begin(); it != posns.end(); ++it)
00791 {
00792 if (!(*it).pos())
00793 rDays.setBit((*it).day() - 1, 1);
00794 }
00795 mWeeklyRule->setDays(rDays);
00796 break;
00797 }
00798 mRuleButtonGroup->setButton(mMonthlyButtonId);
00799 mMonthlyRule->setPosition(i, posns.first().day());
00800 break;
00801 }
00802 case KARecurrence::MONTHLY_DAY:
00803 {
00804 mRuleButtonGroup->setButton(mMonthlyButtonId);
00805 QValueList<int> rmd = recurrence->monthDays();
00806 int day = (rmd.isEmpty()) ? event.mainDate().day() : rmd.first();
00807 mMonthlyRule->setDate(day);
00808 break;
00809 }
00810 case KARecurrence::ANNUAL_DATE:
00811 case KARecurrence::ANNUAL_POS:
00812 {
00813 if (rtype == KARecurrence::ANNUAL_DATE)
00814 {
00815 mRuleButtonGroup->setButton(mYearlyButtonId);
00816 const QValueList<int> rmd = recurrence->monthDays();
00817 int day = (rmd.isEmpty()) ? event.mainDate().day() : rmd.first();
00818 mYearlyRule->setDate(day);
00819 mYearlyRule->setFeb29Type(recurrence->feb29Type());
00820 }
00821 else if (rtype == KARecurrence::ANNUAL_POS)
00822 {
00823 mRuleButtonGroup->setButton(mYearlyButtonId);
00824 QValueList<RecurrenceRule::WDayPos> posns = recurrence->yearPositions();
00825 mYearlyRule->setPosition(posns.first().pos(), posns.first().day());
00826 }
00827 mYearlyRule->setMonths(recurrence->yearMonths());
00828 break;
00829 }
00830 default:
00831 return;
00832 }
00833
00834 mRule->setFrequency(recurrence->frequency());
00835
00836
00837 QDateTime endtime = mCurrStartDateTime;
00838 int duration = recurrence->duration();
00839 if (duration == -1)
00840 mNoEndDateButton->setChecked(true);
00841 else if (duration)
00842 {
00843 mRepeatCountButton->setChecked(true);
00844 mRepeatCountEntry->setValue(duration);
00845 }
00846 else
00847 {
00848 mEndDateButton->setChecked(true);
00849 endtime = recurrence->endDateTime();
00850 mEndTimeEdit->setValue(endtime.time());
00851 }
00852 mEndDateEdit->setDate(endtime.date());
00853
00854
00855 mExceptionDates = event.recurrence()->exDates();
00856 qHeapSort(mExceptionDates);
00857 mExceptionDateList->clear();
00858 for (DateList::ConstIterator it = mExceptionDates.begin(); it != mExceptionDates.end(); ++it)
00859 mExceptionDateList->insertItem(KGlobal::locale()->formatDate(*it));
00860 enableExceptionButtons();
00861
00862
00863 mSubRepetition->set(event.repeatInterval(), event.repeatCount());
00864
00865 rangeTypeClicked();
00866
00867 saveState();
00868 }
00869
00870
00871
00872
00873
00874
00875 void RecurrenceEdit::updateEvent(KAEvent& event, bool adjustStart)
00876 {
00877
00878 QDate endDate;
00879 QTime endTime;
00880 int repeatCount;
00881 if (mNoEndDateButton->isChecked())
00882 repeatCount = -1;
00883 else if (mRepeatCountButton->isChecked())
00884 repeatCount = mRepeatCountEntry->value();
00885 else
00886 {
00887 repeatCount = 0;
00888 endDate = mEndDateEdit->date();
00889 endTime = mEndTimeEdit->time();
00890 }
00891
00892
00893 QButton* button = mRuleButtonGroup->selected();
00894 event.setRepeatAtLogin(button == mAtLoginButton);
00895 int frequency = mRule ? mRule->frequency() : 0;
00896 if (button == mSubDailyButton)
00897 {
00898 QDateTime endDateTime(endDate, endTime);
00899 event.setRecurMinutely(frequency, repeatCount, endDateTime);
00900 }
00901 else if (button == mDailyButton)
00902 {
00903 event.setRecurDaily(frequency, mDailyRule->days(), repeatCount, endDate);
00904 }
00905 else if (button == mWeeklyButton)
00906 {
00907 event.setRecurWeekly(frequency, mWeeklyRule->days(), repeatCount, endDate);
00908 }
00909 else if (button == mMonthlyButton)
00910 {
00911 if (mMonthlyRule->type() == MonthlyRule::POS)
00912 {
00913
00914 KAEvent::MonthPos pos;
00915 pos.days.fill(false);
00916 pos.days.setBit(mMonthlyRule->dayOfWeek() - 1);
00917 pos.weeknum = mMonthlyRule->week();
00918 QValueList<KAEvent::MonthPos> poses;
00919 poses.append(pos);
00920 event.setRecurMonthlyByPos(frequency, poses, repeatCount, endDate);
00921 }
00922 else
00923 {
00924
00925 int daynum = mMonthlyRule->date();
00926 QValueList<int> daynums;
00927 daynums.append(daynum);
00928 event.setRecurMonthlyByDate(frequency, daynums, repeatCount, endDate);
00929 }
00930 }
00931 else if (button == mYearlyButton)
00932 {
00933 QValueList<int> months = mYearlyRule->months();
00934 if (mYearlyRule->type() == YearlyRule::POS)
00935 {
00936
00937 KAEvent::MonthPos pos;
00938 pos.days.fill(false);
00939 pos.days.setBit(mYearlyRule->dayOfWeek() - 1);
00940 pos.weeknum = mYearlyRule->week();
00941 QValueList<KAEvent::MonthPos> poses;
00942 poses.append(pos);
00943 event.setRecurAnnualByPos(frequency, poses, months, repeatCount, endDate);
00944 }
00945 else
00946 {
00947
00948 event.setRecurAnnualByDate(frequency, months, mYearlyRule->date(),
00949 mYearlyRule->feb29Type(), repeatCount, endDate);
00950 }
00951 }
00952 else
00953 {
00954 event.setNoRecur();
00955 return;
00956 }
00957 if (!event.recurs())
00958 return;
00959 if (adjustStart)
00960 event.setFirstRecurrence();
00961
00962
00963
00964 int count = mSubRepetition->count();
00965 if (mRuleButtonType < SUBDAILY)
00966 count = 0;
00967 event.setRepetition(mSubRepetition->interval(), count);
00968
00969
00970 event.recurrence()->setExDates(mExceptionDates);
00971
00972 event.setUpdated();
00973 }
00974
00975
00976
00977
00978 void RecurrenceEdit::saveState()
00979 {
00980 mSavedRuleButton = mRuleButtonGroup->selected();
00981 if (mRule)
00982 mRule->saveState();
00983 mSavedRangeButton = mRangeButtonGroup->selected();
00984 if (mSavedRangeButton == mRepeatCountButton)
00985 mSavedRecurCount = mRepeatCountEntry->value();
00986 else if (mSavedRangeButton == mEndDateButton)
00987 mSavedEndDateTime.set(QDateTime(mEndDateEdit->date(), mEndTimeEdit->time()), mEndAnyTimeCheckBox->isChecked());
00988 mSavedExceptionDates = mExceptionDates;
00989 mSavedRepeatInterval = mSubRepetition->interval();
00990 mSavedRepeatCount = mSubRepetition->count();
00991 }
00992
00993
00994
00995
00996 bool RecurrenceEdit::stateChanged() const
00997 {
00998 if (mSavedRuleButton != mRuleButtonGroup->selected()
00999 || mSavedRangeButton != mRangeButtonGroup->selected()
01000 || mRule && mRule->stateChanged())
01001 return true;
01002 if (mSavedRangeButton == mRepeatCountButton
01003 && mSavedRecurCount != mRepeatCountEntry->value())
01004 return true;
01005 if (mSavedRangeButton == mEndDateButton
01006 && mSavedEndDateTime != DateTime(QDateTime(mEndDateEdit->date(), mEndTimeEdit->time()), mEndAnyTimeCheckBox->isChecked()))
01007 return true;
01008 if (mSavedExceptionDates != mExceptionDates
01009 || mSavedRepeatInterval != mSubRepetition->interval()
01010 || mSavedRepeatCount != mSubRepetition->count())
01011 return true;
01012 return false;
01013 }
01014
01015
01016
01017
01018
01019
01020
01021
01022 Rule::Rule(const QString& freqText, const QString& freqWhatsThis, bool time, bool readOnly, QWidget* parent, const char* name)
01023 : NoRule(parent, name)
01024 {
01025 mLayout = new QVBoxLayout(this, 0, KDialog::spacingHint());
01026 QHBox* freqBox = new QHBox(this);
01027 mLayout->addWidget(freqBox);
01028 QHBox* box = new QHBox(freqBox);
01029 box->setSpacing(KDialog::spacingHint());
01030
01031 QLabel* label = new QLabel(i18n("Recur e&very"), box);
01032 label->setFixedSize(label->sizeHint());
01033 if (time)
01034 {
01035 mIntSpinBox = 0;
01036 mSpinBox = mTimeSpinBox = new TimeSpinBox(1, 5999, box);
01037 mTimeSpinBox->setFixedSize(mTimeSpinBox->sizeHint());
01038 mTimeSpinBox->setReadOnly(readOnly);
01039 }
01040 else
01041 {
01042 mTimeSpinBox = 0;
01043 mSpinBox = mIntSpinBox = new SpinBox(1, 999, 1, box);
01044 mIntSpinBox->setFixedSize(mIntSpinBox->sizeHint());
01045 mIntSpinBox->setReadOnly(readOnly);
01046 }
01047 connect(mSpinBox, SIGNAL(valueChanged(int)), SIGNAL(frequencyChanged()));
01048 label->setBuddy(mSpinBox);
01049 label = new QLabel(freqText, box);
01050 label->setFixedSize(label->sizeHint());
01051 box->setFixedSize(sizeHint());
01052 QWhatsThis::add(box, freqWhatsThis);
01053
01054 new QWidget(freqBox);
01055 freqBox->setFixedHeight(freqBox->sizeHint().height());
01056 freqBox->setFocusProxy(mSpinBox);
01057 }
01058
01059 int Rule::frequency() const
01060 {
01061 if (mIntSpinBox)
01062 return mIntSpinBox->value();
01063 if (mTimeSpinBox)
01064 return mTimeSpinBox->value();
01065 return 0;
01066 }
01067
01068 void Rule::setFrequency(int n)
01069 {
01070 if (mIntSpinBox)
01071 mIntSpinBox->setValue(n);
01072 if (mTimeSpinBox)
01073 mTimeSpinBox->setValue(n);
01074 }
01075
01076
01077
01078
01079 void Rule::saveState()
01080 {
01081 mSavedFrequency = frequency();
01082 }
01083
01084
01085
01086
01087 bool Rule::stateChanged() const
01088 {
01089 return (mSavedFrequency != frequency());
01090 }
01091
01092
01093
01094
01095
01096
01097
01098 SubDailyRule::SubDailyRule(bool readOnly, QWidget* parent, const char* name)
01099 : Rule(i18n("hours:minutes"),
01100 i18n("Enter the number of hours and minutes between repetitions of the alarm"),
01101 true, readOnly, parent, name)
01102 { }
01103
01104
01105
01106
01107
01108
01109
01110 DayWeekRule::DayWeekRule(const QString& freqText, const QString& freqWhatsThis, const QString& daysWhatsThis,
01111 bool readOnly, QWidget* parent, const char* name)
01112 : Rule(freqText, freqWhatsThis, false, readOnly, parent, name),
01113 mSavedDays(7)
01114 {
01115 QGridLayout* grid = new QGridLayout(layout(), 1, 4, KDialog::spacingHint());
01116 grid->setRowStretch(0, 1);
01117
01118 QLabel* label = new QLabel(i18n("On: Tuesday", "O&n:"), this);
01119 label->setFixedSize(label->sizeHint());
01120 grid->addWidget(label, 0, 0, Qt::AlignRight | Qt::AlignTop);
01121 grid->addColSpacing(1, KDialog::spacingHint());
01122
01123
01124
01125 QWidget* box = new QWidget(this);
01126 QGridLayout* dgrid = new QGridLayout(box, 4, 2, 0, KDialog::spacingHint());
01127 const KCalendarSystem* calendar = KGlobal::locale()->calendar();
01128 for (int i = 0; i < 7; ++i)
01129 {
01130 int day = KAlarm::localeDayInWeek_to_weekDay(i);
01131 mDayBox[i] = new CheckBox(calendar->weekDayName(day), box);
01132 mDayBox[i]->setFixedSize(mDayBox[i]->sizeHint());
01133 mDayBox[i]->setReadOnly(readOnly);
01134 dgrid->addWidget(mDayBox[i], i%4, i/4, Qt::AlignAuto);
01135 }
01136 box->setFixedSize(box->sizeHint());
01137 QWhatsThis::add(box, daysWhatsThis);
01138 grid->addWidget(box, 0, 2, Qt::AlignAuto);
01139 label->setBuddy(mDayBox[0]);
01140 grid->setColStretch(3, 1);
01141 }
01142
01143
01144
01145
01146 QBitArray DayWeekRule::days() const
01147 {
01148 QBitArray ds(7);
01149 ds.fill(false);
01150 for (int i = 0; i < 7; ++i)
01151 if (mDayBox[i]->isChecked())
01152 ds.setBit(KAlarm::localeDayInWeek_to_weekDay(i) - 1, 1);
01153 return ds;
01154 }
01155
01156
01157
01158
01159 void DayWeekRule::setDays(bool tick)
01160 {
01161 for (int i = 0; i < 7; ++i)
01162 mDayBox[i]->setChecked(tick);
01163 }
01164
01165
01166
01167
01168 void DayWeekRule::setDays(const QBitArray& days)
01169 {
01170 for (int i = 0; i < 7; ++i)
01171 {
01172 bool x = days.testBit(KAlarm::localeDayInWeek_to_weekDay(i) - 1);
01173 mDayBox[i]->setChecked(x);
01174 }
01175 }
01176
01177
01178
01179
01180 void DayWeekRule::setDay(int dayOfWeek)
01181 {
01182 for (int i = 0; i < 7; ++i)
01183 mDayBox[i]->setChecked(false);
01184 if (dayOfWeek > 0 && dayOfWeek <= 7)
01185 mDayBox[KAlarm::weekDay_to_localeDayInWeek(dayOfWeek)]->setChecked(true);
01186 }
01187
01188
01189
01190
01191 QWidget* DayWeekRule::validate(QString& errorMessage)
01192 {
01193 for (int i = 0; i < 7; ++i)
01194 if (mDayBox[i]->isChecked())
01195 return 0;
01196 errorMessage = i18n("No day selected");
01197 return mDayBox[0];
01198 }
01199
01200
01201
01202
01203 void DayWeekRule::saveState()
01204 {
01205 Rule::saveState();
01206 mSavedDays = days();
01207 }
01208
01209
01210
01211
01212 bool DayWeekRule::stateChanged() const
01213 {
01214 return (Rule::stateChanged()
01215 || mSavedDays != days());
01216 }
01217
01218
01219
01220
01221
01222
01223
01224 DailyRule::DailyRule(bool readOnly, QWidget* parent, const char* name)
01225 : DayWeekRule(i18n("day(s)"),
01226 i18n("Enter the number of days between repetitions of the alarm"),
01227 i18n("Select the days of the week on which the alarm is allowed to occur"),
01228 readOnly, parent, name)
01229 { }
01230
01231
01232
01233
01234
01235
01236
01237 WeeklyRule::WeeklyRule(bool readOnly, QWidget* parent, const char* name)
01238 : DayWeekRule(i18n("week(s)"),
01239 i18n("Enter the number of weeks between repetitions of the alarm"),
01240 i18n("Select the days of the week on which to repeat the alarm"),
01241 readOnly, parent, name)
01242 { }
01243
01244
01245
01246
01247
01248
01249
01250 MonthYearRule::MonthYearRule(const QString& freqText, const QString& freqWhatsThis, bool allowEveryWeek,
01251 bool readOnly, QWidget* parent, const char* name)
01252 : Rule(freqText, freqWhatsThis, false, readOnly, parent, name),
01253 mEveryWeek(allowEveryWeek)
01254 {
01255 mButtonGroup = new ButtonGroup(this);
01256 mButtonGroup->hide();
01257
01258
01259 QHBox* box = new QHBox(this);
01260 box->setSpacing(KDialog::spacingHint());
01261 layout()->addWidget(box);
01262
01263 mDayButton = new RadioButton(i18n("On day number in the month", "O&n day"), box);
01264 mDayButton->setFixedSize(mDayButton->sizeHint());
01265 mDayButton->setReadOnly(readOnly);
01266 mDayButtonId = mButtonGroup->insert(mDayButton);
01267 QWhatsThis::add(mDayButton, i18n("Repeat the alarm on the selected day of the month"));
01268
01269 mDayCombo = new ComboBox(false, box);
01270 mDayCombo->setSizeLimit(11);
01271 for (int i = 0; i < 31; ++i)
01272 mDayCombo->insertItem(QString::number(i + 1));
01273 mDayCombo->insertItem(i18n("Last day of month", "Last"));
01274 mDayCombo->setFixedSize(mDayCombo->sizeHint());
01275 mDayCombo->setReadOnly(readOnly);
01276 QWhatsThis::add(mDayCombo, i18n("Select the day of the month on which to repeat the alarm"));
01277 mDayButton->setFocusWidget(mDayCombo);
01278 connect(mDayCombo, SIGNAL(activated(int)), SLOT(slotDaySelected(int)));
01279
01280 box->setStretchFactor(new QWidget(box), 1);
01281 box->setFixedHeight(box->sizeHint().height());
01282
01283
01284 box = new QHBox(this);
01285 box->setSpacing(KDialog::spacingHint());
01286 layout()->addWidget(box);
01287
01288 mPosButton = new RadioButton(i18n("On the 1st Tuesday", "On t&he"), box);
01289 mPosButton->setFixedSize(mPosButton->sizeHint());
01290 mPosButton->setReadOnly(readOnly);
01291 mPosButtonId = mButtonGroup->insert(mPosButton);
01292 QWhatsThis::add(mPosButton,
01293 i18n("Repeat the alarm on one day of the week, in the selected week of the month"));
01294
01295 mWeekCombo = new ComboBox(false, box);
01296 mWeekCombo->insertItem(i18n("1st"));
01297 mWeekCombo->insertItem(i18n("2nd"));
01298 mWeekCombo->insertItem(i18n("3rd"));
01299 mWeekCombo->insertItem(i18n("4th"));
01300 mWeekCombo->insertItem(i18n("5th"));
01301 mWeekCombo->insertItem(i18n("Last Monday in March", "Last"));
01302 mWeekCombo->insertItem(i18n("2nd Last"));
01303 mWeekCombo->insertItem(i18n("3rd Last"));
01304 mWeekCombo->insertItem(i18n("4th Last"));
01305 mWeekCombo->insertItem(i18n("5th Last"));
01306 if (mEveryWeek)
01307 {
01308 mWeekCombo->insertItem(i18n("Every (Monday...) in month", "Every"));
01309 mWeekCombo->setSizeLimit(11);
01310 }
01311 QWhatsThis::add(mWeekCombo, i18n("Select the week of the month in which to repeat the alarm"));
01312 mWeekCombo->setFixedSize(mWeekCombo->sizeHint());
01313 mWeekCombo->setReadOnly(readOnly);
01314 mPosButton->setFocusWidget(mWeekCombo);
01315
01316 mDayOfWeekCombo = new ComboBox(false, box);
01317 const KCalendarSystem* calendar = KGlobal::locale()->calendar();
01318 for (int i = 0; i < 7; ++i)
01319 {
01320 int day = KAlarm::localeDayInWeek_to_weekDay(i);
01321 mDayOfWeekCombo->insertItem(calendar->weekDayName(day));
01322 }
01323 mDayOfWeekCombo->setReadOnly(readOnly);
01324 QWhatsThis::add(mDayOfWeekCombo, i18n("Select the day of the week on which to repeat the alarm"));
01325
01326 box->setStretchFactor(new QWidget(box), 1);
01327 box->setFixedHeight(box->sizeHint().height());
01328 connect(mButtonGroup, SIGNAL(buttonSet(int)), SLOT(clicked(int)));
01329 }
01330
01331 MonthYearRule::DayPosType MonthYearRule::type() const
01332 {
01333 return (mButtonGroup->selectedId() == mDayButtonId) ? DATE : POS;
01334 }
01335
01336 void MonthYearRule::setType(MonthYearRule::DayPosType type)
01337 {
01338 mButtonGroup->setButton(type == DATE ? mDayButtonId : mPosButtonId);
01339 }
01340
01341 void MonthYearRule::setDefaultValues(int dayOfMonth, int dayOfWeek)
01342 {
01343 --dayOfMonth;
01344 mDayCombo->setCurrentItem(dayOfMonth);
01345 mWeekCombo->setCurrentItem(dayOfMonth / 7);
01346 mDayOfWeekCombo->setCurrentItem(KAlarm::weekDay_to_localeDayInWeek(dayOfWeek));
01347 }
01348
01349 int MonthYearRule::date() const
01350 {
01351 int daynum = mDayCombo->currentItem() + 1;
01352 return (daynum <= 31) ? daynum : 31 - daynum;
01353 }
01354
01355 int MonthYearRule::week() const
01356 {
01357 int weeknum = mWeekCombo->currentItem() + 1;
01358 return (weeknum <= 5) ? weeknum : (weeknum == 11) ? 0 : 5 - weeknum;
01359 }
01360
01361 int MonthYearRule::dayOfWeek() const
01362 {
01363 return KAlarm::localeDayInWeek_to_weekDay(mDayOfWeekCombo->currentItem());
01364 }
01365
01366 void MonthYearRule::setDate(int dayOfMonth)
01367 {
01368 mButtonGroup->setButton(mDayButtonId);
01369 mDayCombo->setCurrentItem(dayOfMonth > 0 ? dayOfMonth - 1 : dayOfMonth < 0 ? 30 - dayOfMonth : 0);
01370 }
01371
01372 void MonthYearRule::setPosition(int week, int dayOfWeek)
01373 {
01374 mButtonGroup->setButton(mPosButtonId);
01375 mWeekCombo->setCurrentItem((week > 0) ? week - 1 : (week < 0) ? 4 - week : mEveryWeek ? 10 : 0);
01376 mDayOfWeekCombo->setCurrentItem(KAlarm::weekDay_to_localeDayInWeek(dayOfWeek));
01377 }
01378
01379 void MonthYearRule::enableSelection(DayPosType type)
01380 {
01381 bool date = (type == DATE);
01382 mDayCombo->setEnabled(date);
01383 mWeekCombo->setEnabled(!date);
01384 mDayOfWeekCombo->setEnabled(!date);
01385 }
01386
01387 void MonthYearRule::clicked(int id)
01388 {
01389 enableSelection(id == mDayButtonId ? DATE : POS);
01390 }
01391
01392 void MonthYearRule::slotDaySelected(int index)
01393 {
01394 daySelected(index <= 30 ? index + 1 : 30 - index);
01395 }
01396
01397
01398
01399
01400 void MonthYearRule::saveState()
01401 {
01402 Rule::saveState();
01403 mSavedType = type();
01404 if (mSavedType == DATE)
01405 mSavedDay = date();
01406 else
01407 {
01408 mSavedWeek = week();
01409 mSavedWeekDay = dayOfWeek();
01410 }
01411 }
01412
01413
01414
01415
01416 bool MonthYearRule::stateChanged() const
01417 {
01418 if (Rule::stateChanged()
01419 || mSavedType != type())
01420 return true;
01421 if (mSavedType == DATE)
01422 {
01423 if (mSavedDay != date())
01424 return true;
01425 }
01426 else
01427 {
01428 if (mSavedWeek != week()
01429 || mSavedWeekDay != dayOfWeek())
01430 return true;
01431 }
01432 return false;
01433 }
01434
01435
01436
01437
01438
01439
01440
01441 MonthlyRule::MonthlyRule(bool readOnly, QWidget* parent, const char* name)
01442 : MonthYearRule(i18n("month(s)"),
01443 i18n("Enter the number of months between repetitions of the alarm"),
01444 false, readOnly, parent, name)
01445 { }
01446
01447
01448
01449
01450
01451
01452
01453 YearlyRule::YearlyRule(bool readOnly, QWidget* parent, const char* name)
01454 : MonthYearRule(i18n("year(s)"),
01455 i18n("Enter the number of years between repetitions of the alarm"),
01456 true, readOnly, parent, name)
01457 {
01458
01459 QBoxLayout* hlayout = new QHBoxLayout(layout(), KDialog::spacingHint());
01460 QLabel* label = new QLabel(i18n("List of months to select", "Months:"), this);
01461 label->setFixedSize(label->sizeHint());
01462 hlayout->addWidget(label, 0, Qt::AlignAuto | Qt::AlignTop);
01463
01464
01465 QWidget* w = new QWidget(this);
01466 hlayout->addWidget(w, 1, Qt::AlignAuto);
01467 QGridLayout* grid = new QGridLayout(w, 4, 3, 0, KDialog::spacingHint());
01468 const KCalendarSystem* calendar = KGlobal::locale()->calendar();
01469 int year = QDate::currentDate().year();
01470 for (int i = 0; i < 12; ++i)
01471 {
01472 mMonthBox[i] = new CheckBox(calendar->monthName(i + 1, year, true), w);
01473 mMonthBox[i]->setFixedSize(mMonthBox[i]->sizeHint());
01474 mMonthBox[i]->setReadOnly(readOnly);
01475 grid->addWidget(mMonthBox[i], i%3, i/3, Qt::AlignAuto);
01476 }
01477 connect(mMonthBox[1], SIGNAL(toggled(bool)), SLOT(enableFeb29()));
01478 w->setFixedHeight(w->sizeHint().height());
01479 QWhatsThis::add(w, i18n("Select the months of the year in which to repeat the alarm"));
01480
01481
01482 QHBox* f29box = new QHBox(this);
01483 layout()->addWidget(f29box);
01484 QHBox* box = new QHBox(f29box);
01485 box->setSpacing(KDialog::spacingHint());
01486 mFeb29Label = new QLabel(i18n("February 2&9th alarm in non-leap years:"), box);
01487 mFeb29Label->setFixedSize(mFeb29Label->sizeHint());
01488 mFeb29Combo = new ComboBox(false, box);
01489 mFeb29Combo->insertItem(i18n("No date", "None"));
01490 mFeb29Combo->insertItem(i18n("1st March (short form)", "1 Mar"));
01491 mFeb29Combo->insertItem(i18n("28th February (short form)", "28 Feb"));
01492 mFeb29Combo->setFixedSize(mFeb29Combo->sizeHint());
01493 mFeb29Combo->setReadOnly(readOnly);
01494 mFeb29Label->setBuddy(mFeb29Combo);
01495 box->setFixedSize(box->sizeHint());
01496 QWhatsThis::add(box,
01497 i18n("Select which date, if any, the February 29th alarm should trigger in non-leap years"));
01498 new QWidget(f29box);
01499 f29box->setFixedHeight(f29box->sizeHint().height());
01500 }
01501
01502 void YearlyRule::setDefaultValues(int dayOfMonth, int dayOfWeek, int month)
01503 {
01504 MonthYearRule::setDefaultValues(dayOfMonth, dayOfWeek);
01505 --month;
01506 for (int i = 0; i < 12; ++i)
01507 mMonthBox[i]->setChecked(i == month);
01508 setFeb29Type(Preferences::defaultFeb29Type());
01509 daySelected(dayOfMonth);
01510 }
01511
01512
01513
01514
01515
01516 QValueList<int> YearlyRule::months() const
01517 {
01518 QValueList<int> mnths;
01519 for (int i = 0; i < 12; ++i)
01520 if (mMonthBox[i]->isChecked() && mMonthBox[i]->isEnabled())
01521 mnths.append(i + 1);
01522 return mnths;
01523 }
01524
01525
01526
01527
01528 void YearlyRule::setMonths(const QValueList<int>& mnths)
01529 {
01530 bool checked[12];
01531 for (int i = 0; i < 12; ++i)
01532 checked[i] = false;
01533 for (QValueListConstIterator<int> it = mnths.begin(); it != mnths.end(); ++it)
01534 checked[(*it) - 1] = true;
01535 for (int i = 0; i < 12; ++i)
01536 mMonthBox[i]->setChecked(checked[i]);
01537 enableFeb29();
01538 }
01539
01540
01541
01542
01543 KARecurrence::Feb29Type YearlyRule::feb29Type() const
01544 {
01545 if (mFeb29Combo->isEnabled())
01546 {
01547 switch (mFeb29Combo->currentItem())
01548 {
01549 case 1: return KARecurrence::FEB29_MAR1;
01550 case 2: return KARecurrence::FEB29_FEB28;
01551 default: break;
01552 }
01553 }
01554 return KARecurrence::FEB29_FEB29;
01555 }
01556
01557
01558
01559
01560 void YearlyRule::setFeb29Type(KARecurrence::Feb29Type type)
01561 {
01562 int index;
01563 switch (type)
01564 {
01565 default:
01566 case KARecurrence::FEB29_FEB29: index = 0; break;
01567 case KARecurrence::FEB29_MAR1: index = 1; break;
01568 case KARecurrence::FEB29_FEB28: index = 2; break;
01569 }
01570 mFeb29Combo->setCurrentItem(index);
01571 }
01572
01573
01574
01575
01576 QWidget* YearlyRule::validate(QString& errorMessage)
01577 {
01578 for (int i = 0; i < 12; ++i)
01579 if (mMonthBox[i]->isChecked() && mMonthBox[i]->isEnabled())
01580 return 0;
01581 errorMessage = i18n("No month selected");
01582 return mMonthBox[0];
01583 }
01584
01585
01586
01587
01588
01589 void YearlyRule::clicked(int id)
01590 {
01591 MonthYearRule::clicked(id);
01592 daySelected(buttonType(id) == DATE ? date() : 1);
01593 }
01594
01595
01596
01597
01598
01599 void YearlyRule::daySelected(int day)
01600 {
01601 mMonthBox[1]->setEnabled(day <= 29);
01602 bool enable = (day != 31);
01603 mMonthBox[3]->setEnabled(enable);
01604 mMonthBox[5]->setEnabled(enable);
01605 mMonthBox[8]->setEnabled(enable);
01606 mMonthBox[10]->setEnabled(enable);
01607 enableFeb29();
01608 }
01609
01610
01611
01612
01613
01614 void YearlyRule::enableFeb29()
01615 {
01616 bool enable = (type() == DATE && date() == 29 && mMonthBox[1]->isChecked() && mMonthBox[1]->isEnabled());
01617 mFeb29Label->setEnabled(enable);
01618 mFeb29Combo->setEnabled(enable);
01619 }
01620
01621
01622
01623
01624 void YearlyRule::saveState()
01625 {
01626 MonthYearRule::saveState();
01627 mSavedMonths = months();
01628 mSavedFeb29Type = feb29Type();
01629 }
01630
01631
01632
01633
01634 bool YearlyRule::stateChanged() const
01635 {
01636 return (MonthYearRule::stateChanged()
01637 || mSavedMonths != months()
01638 || mSavedFeb29Type != feb29Type());
01639 }