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 void RecurrenceEdit::set(const KAEvent& event)
00738 {
00739 setDefaults(event.mainDateTime().dateTime());
00740 if (event.repeatAtLogin())
00741 {
00742 mRuleButtonGroup->setButton(mAtLoginButtonId);
00743 mEndDateButton->setChecked(true);
00744 return;
00745 }
00746 mRuleButtonGroup->setButton(mNoneButtonId);
00747 KARecurrence* recurrence = event.recurrence();
00748 if (!recurrence)
00749 return;
00750 KARecurrence::Type rtype = recurrence->type();
00751 switch (rtype)
00752 {
00753 case KARecurrence::MINUTELY:
00754 mRuleButtonGroup->setButton(mSubDailyButtonId);
00755 break;
00756
00757 case KARecurrence::DAILY:
00758 {
00759 mRuleButtonGroup->setButton(mDailyButtonId);
00760 QBitArray rDays = recurrence->days();
00761 bool set = false;
00762 for (int i = 0; i < 7 && !set; ++i)
00763 set = rDays.testBit(i);
00764 if (set)
00765 mDailyRule->setDays(rDays);
00766 else
00767 mDailyRule->setDays(true);
00768 break;
00769 }
00770 case KARecurrence::WEEKLY:
00771 {
00772 mRuleButtonGroup->setButton(mWeeklyButtonId);
00773 QBitArray rDays = recurrence->days();
00774 mWeeklyRule->setDays(rDays);
00775 break;
00776 }
00777 case KARecurrence::MONTHLY_POS:
00778 {
00779 QValueList<RecurrenceRule::WDayPos> posns = recurrence->monthPositions();
00780 int i = posns.first().pos();
00781 if (!i)
00782 {
00783
00784
00785 mRuleButtonGroup->setButton(mWeeklyButtonId);
00786 mWeeklyRule->setFrequency(recurrence->frequency());
00787 QBitArray rDays(7);
00788 for (QValueList<RecurrenceRule::WDayPos>::ConstIterator it = posns.begin(); it != posns.end(); ++it)
00789 {
00790 if (!(*it).pos())
00791 rDays.setBit((*it).day() - 1, 1);
00792 }
00793 mWeeklyRule->setDays(rDays);
00794 break;
00795 }
00796 mRuleButtonGroup->setButton(mMonthlyButtonId);
00797 mMonthlyRule->setPosition(i, posns.first().day());
00798 break;
00799 }
00800 case KARecurrence::MONTHLY_DAY:
00801 {
00802 mRuleButtonGroup->setButton(mMonthlyButtonId);
00803 QValueList<int> rmd = recurrence->monthDays();
00804 int day = (rmd.isEmpty()) ? event.mainDate().day() : rmd.first();
00805 mMonthlyRule->setDate(day);
00806 break;
00807 }
00808 case KARecurrence::ANNUAL_DATE:
00809 case KARecurrence::ANNUAL_POS:
00810 {
00811 if (rtype == KARecurrence::ANNUAL_DATE)
00812 {
00813 mRuleButtonGroup->setButton(mYearlyButtonId);
00814 const QValueList<int> rmd = recurrence->monthDays();
00815 int day = (rmd.isEmpty()) ? event.mainDate().day() : rmd.first();
00816 mYearlyRule->setDate(day);
00817 mYearlyRule->setFeb29Type(recurrence->feb29Type());
00818 }
00819 else if (rtype == KARecurrence::ANNUAL_POS)
00820 {
00821 mRuleButtonGroup->setButton(mYearlyButtonId);
00822 QValueList<RecurrenceRule::WDayPos> posns = recurrence->yearPositions();
00823 mYearlyRule->setPosition(posns.first().pos(), posns.first().day());
00824 }
00825 mYearlyRule->setMonths(recurrence->yearMonths());
00826 break;
00827 }
00828 default:
00829 return;
00830 }
00831
00832 mRule->setFrequency(recurrence->frequency());
00833
00834
00835 QDateTime endtime = mCurrStartDateTime;
00836 int duration = recurrence->duration();
00837 if (duration == -1)
00838 mNoEndDateButton->setChecked(true);
00839 else if (duration)
00840 {
00841 mRepeatCountButton->setChecked(true);
00842 int repeatCount;
00843 if (event.expired())
00844 repeatCount = duration;
00845 else if (event.mainExpired())
00846 {
00847 mRepeatCountEntry->setMinValue(0);
00848 repeatCount = 0;
00849 }
00850 else
00851 repeatCount = duration - recurrence->durationTo(QDateTime::currentDateTime());
00852 mRepeatCountEntry->setValue(repeatCount);
00853 }
00854 else
00855 {
00856 mEndDateButton->setChecked(true);
00857 endtime = recurrence->endDateTime();
00858 mEndTimeEdit->setValue(endtime.time());
00859 }
00860 mEndDateEdit->setDate(endtime.date());
00861
00862
00863 mExceptionDates = event.recurrence()->exDates();
00864 qHeapSort(mExceptionDates);
00865 mExceptionDateList->clear();
00866 for (DateList::ConstIterator it = mExceptionDates.begin(); it != mExceptionDates.end(); ++it)
00867 mExceptionDateList->insertItem(KGlobal::locale()->formatDate(*it));
00868 enableExceptionButtons();
00869
00870
00871 mSubRepetition->set(event.repeatInterval(), event.repeatCount());
00872
00873 rangeTypeClicked();
00874
00875 saveState();
00876 }
00877
00878
00879
00880
00881
00882
00883 void RecurrenceEdit::updateEvent(KAEvent& event, bool adjustStart)
00884 {
00885
00886 QDate endDate;
00887 QTime endTime;
00888 int repeatCount;
00889 if (mNoEndDateButton->isChecked())
00890 repeatCount = -1;
00891 else if (mRepeatCountButton->isChecked())
00892 repeatCount = mRepeatCountEntry->value();
00893 else
00894 {
00895 repeatCount = 0;
00896 endDate = mEndDateEdit->date();
00897 endTime = mEndTimeEdit->time();
00898 }
00899
00900
00901 QButton* button = mRuleButtonGroup->selected();
00902 event.setRepeatAtLogin(button == mAtLoginButton);
00903 int frequency = mRule ? mRule->frequency() : 0;
00904 if (button == mSubDailyButton)
00905 {
00906 QDateTime endDateTime(endDate, endTime);
00907 event.setRecurMinutely(frequency, repeatCount, endDateTime);
00908 }
00909 else if (button == mDailyButton)
00910 {
00911 event.setRecurDaily(frequency, mDailyRule->days(), repeatCount, endDate);
00912 }
00913 else if (button == mWeeklyButton)
00914 {
00915 event.setRecurWeekly(frequency, mWeeklyRule->days(), repeatCount, endDate);
00916 }
00917 else if (button == mMonthlyButton)
00918 {
00919 if (mMonthlyRule->type() == MonthlyRule::POS)
00920 {
00921
00922 KAEvent::MonthPos pos;
00923 pos.days.fill(false);
00924 pos.days.setBit(mMonthlyRule->dayOfWeek() - 1);
00925 pos.weeknum = mMonthlyRule->week();
00926 QValueList<KAEvent::MonthPos> poses;
00927 poses.append(pos);
00928 event.setRecurMonthlyByPos(frequency, poses, repeatCount, endDate);
00929 }
00930 else
00931 {
00932
00933 int daynum = mMonthlyRule->date();
00934 QValueList<int> daynums;
00935 daynums.append(daynum);
00936 event.setRecurMonthlyByDate(frequency, daynums, repeatCount, endDate);
00937 }
00938 }
00939 else if (button == mYearlyButton)
00940 {
00941 QValueList<int> months = mYearlyRule->months();
00942 if (mYearlyRule->type() == YearlyRule::POS)
00943 {
00944
00945 KAEvent::MonthPos pos;
00946 pos.days.fill(false);
00947 pos.days.setBit(mYearlyRule->dayOfWeek() - 1);
00948 pos.weeknum = mYearlyRule->week();
00949 QValueList<KAEvent::MonthPos> poses;
00950 poses.append(pos);
00951 event.setRecurAnnualByPos(frequency, poses, months, repeatCount, endDate);
00952 }
00953 else
00954 {
00955
00956 event.setRecurAnnualByDate(frequency, months, mYearlyRule->date(),
00957 mYearlyRule->feb29Type(), repeatCount, endDate);
00958 }
00959 }
00960 else
00961 {
00962 event.setNoRecur();
00963 return;
00964 }
00965 if (!event.recurs())
00966 return;
00967 if (adjustStart)
00968 event.setFirstRecurrence();
00969
00970
00971
00972 int count = mSubRepetition->count();
00973 if (mRuleButtonType < SUBDAILY)
00974 count = 0;
00975 event.setRepetition(mSubRepetition->interval(), count);
00976
00977
00978 event.recurrence()->setExDates(mExceptionDates);
00979
00980 event.setUpdated();
00981 }
00982
00983
00984
00985
00986 void RecurrenceEdit::saveState()
00987 {
00988 mSavedRuleButton = mRuleButtonGroup->selected();
00989 if (mRule)
00990 mRule->saveState();
00991 mSavedRangeButton = mRangeButtonGroup->selected();
00992 if (mSavedRangeButton == mRepeatCountButton)
00993 mSavedRecurCount = mRepeatCountEntry->value();
00994 else if (mSavedRangeButton == mEndDateButton)
00995 mSavedEndDateTime.set(QDateTime(mEndDateEdit->date(), mEndTimeEdit->time()), mEndAnyTimeCheckBox->isChecked());
00996 mSavedExceptionDates = mExceptionDates;
00997 mSavedRepeatInterval = mSubRepetition->interval();
00998 mSavedRepeatCount = mSubRepetition->count();
00999 }
01000
01001
01002
01003
01004 bool RecurrenceEdit::stateChanged() const
01005 {
01006 if (mSavedRuleButton != mRuleButtonGroup->selected()
01007 || mSavedRangeButton != mRangeButtonGroup->selected()
01008 || mRule && mRule->stateChanged())
01009 return true;
01010 if (mSavedRangeButton == mRepeatCountButton
01011 && mSavedRecurCount != mRepeatCountEntry->value())
01012 return true;
01013 if (mSavedRangeButton == mEndDateButton
01014 && mSavedEndDateTime != DateTime(QDateTime(mEndDateEdit->date(), mEndTimeEdit->time()), mEndAnyTimeCheckBox->isChecked()))
01015 return true;
01016 if (mSavedExceptionDates != mExceptionDates
01017 || mSavedRepeatInterval != mSubRepetition->interval()
01018 || mSavedRepeatCount != mSubRepetition->count())
01019 return true;
01020 return false;
01021 }
01022
01023
01024
01025
01026
01027
01028
01029
01030 Rule::Rule(const QString& freqText, const QString& freqWhatsThis, bool time, bool readOnly, QWidget* parent, const char* name)
01031 : NoRule(parent, name)
01032 {
01033 mLayout = new QVBoxLayout(this, 0, KDialog::spacingHint());
01034 QHBox* freqBox = new QHBox(this);
01035 mLayout->addWidget(freqBox);
01036 QHBox* box = new QHBox(freqBox);
01037 box->setSpacing(KDialog::spacingHint());
01038
01039 QLabel* label = new QLabel(i18n("Recur e&very"), box);
01040 label->setFixedSize(label->sizeHint());
01041 if (time)
01042 {
01043 mIntSpinBox = 0;
01044 mSpinBox = mTimeSpinBox = new TimeSpinBox(1, 5999, box);
01045 mTimeSpinBox->setFixedSize(mTimeSpinBox->sizeHint());
01046 mTimeSpinBox->setReadOnly(readOnly);
01047 }
01048 else
01049 {
01050 mTimeSpinBox = 0;
01051 mSpinBox = mIntSpinBox = new SpinBox(1, 999, 1, box);
01052 mIntSpinBox->setFixedSize(mIntSpinBox->sizeHint());
01053 mIntSpinBox->setReadOnly(readOnly);
01054 }
01055 connect(mSpinBox, SIGNAL(valueChanged(int)), SIGNAL(frequencyChanged()));
01056 label->setBuddy(mSpinBox);
01057 label = new QLabel(freqText, box);
01058 label->setFixedSize(label->sizeHint());
01059 box->setFixedSize(sizeHint());
01060 QWhatsThis::add(box, freqWhatsThis);
01061
01062 new QWidget(freqBox);
01063 freqBox->setFixedHeight(freqBox->sizeHint().height());
01064 freqBox->setFocusProxy(mSpinBox);
01065 }
01066
01067 int Rule::frequency() const
01068 {
01069 if (mIntSpinBox)
01070 return mIntSpinBox->value();
01071 if (mTimeSpinBox)
01072 return mTimeSpinBox->value();
01073 return 0;
01074 }
01075
01076 void Rule::setFrequency(int n)
01077 {
01078 if (mIntSpinBox)
01079 mIntSpinBox->setValue(n);
01080 if (mTimeSpinBox)
01081 mTimeSpinBox->setValue(n);
01082 }
01083
01084
01085
01086
01087 void Rule::saveState()
01088 {
01089 mSavedFrequency = frequency();
01090 }
01091
01092
01093
01094
01095 bool Rule::stateChanged() const
01096 {
01097 return (mSavedFrequency != frequency());
01098 }
01099
01100
01101
01102
01103
01104
01105
01106 SubDailyRule::SubDailyRule(bool readOnly, QWidget* parent, const char* name)
01107 : Rule(i18n("hours:minutes"),
01108 i18n("Enter the number of hours and minutes between repetitions of the alarm"),
01109 true, readOnly, parent, name)
01110 { }
01111
01112
01113
01114
01115
01116
01117
01118 DayWeekRule::DayWeekRule(const QString& freqText, const QString& freqWhatsThis, const QString& daysWhatsThis,
01119 bool readOnly, QWidget* parent, const char* name)
01120 : Rule(freqText, freqWhatsThis, false, readOnly, parent, name),
01121 mSavedDays(7)
01122 {
01123 QGridLayout* grid = new QGridLayout(layout(), 1, 4, KDialog::spacingHint());
01124 grid->setRowStretch(0, 1);
01125
01126 QLabel* label = new QLabel(i18n("On: Tuesday", "O&n:"), this);
01127 label->setFixedSize(label->sizeHint());
01128 grid->addWidget(label, 0, 0, Qt::AlignRight | Qt::AlignTop);
01129 grid->addColSpacing(1, KDialog::spacingHint());
01130
01131
01132
01133 QWidget* box = new QWidget(this);
01134 QGridLayout* dgrid = new QGridLayout(box, 4, 2, 0, KDialog::spacingHint());
01135 const KCalendarSystem* calendar = KGlobal::locale()->calendar();
01136 for (int i = 0; i < 7; ++i)
01137 {
01138 int day = KAlarm::localeDayInWeek_to_weekDay(i);
01139 mDayBox[i] = new CheckBox(calendar->weekDayName(day), box);
01140 mDayBox[i]->setFixedSize(mDayBox[i]->sizeHint());
01141 mDayBox[i]->setReadOnly(readOnly);
01142 dgrid->addWidget(mDayBox[i], i%4, i/4, Qt::AlignAuto);
01143 }
01144 box->setFixedSize(box->sizeHint());
01145 QWhatsThis::add(box, daysWhatsThis);
01146 grid->addWidget(box, 0, 2, Qt::AlignAuto);
01147 label->setBuddy(mDayBox[0]);
01148 grid->setColStretch(3, 1);
01149 }
01150
01151
01152
01153
01154 QBitArray DayWeekRule::days() const
01155 {
01156 QBitArray ds(7);
01157 ds.fill(false);
01158 for (int i = 0; i < 7; ++i)
01159 if (mDayBox[i]->isChecked())
01160 ds.setBit(KAlarm::localeDayInWeek_to_weekDay(i) - 1, 1);
01161 return ds;
01162 }
01163
01164
01165
01166
01167 void DayWeekRule::setDays(bool tick)
01168 {
01169 for (int i = 0; i < 7; ++i)
01170 mDayBox[i]->setChecked(tick);
01171 }
01172
01173
01174
01175
01176 void DayWeekRule::setDays(const QBitArray& days)
01177 {
01178 for (int i = 0; i < 7; ++i)
01179 {
01180 bool x = days.testBit(KAlarm::localeDayInWeek_to_weekDay(i) - 1);
01181 mDayBox[i]->setChecked(x);
01182 }
01183 }
01184
01185
01186
01187
01188 void DayWeekRule::setDay(int dayOfWeek)
01189 {
01190 for (int i = 0; i < 7; ++i)
01191 mDayBox[i]->setChecked(false);
01192 if (dayOfWeek > 0 && dayOfWeek <= 7)
01193 mDayBox[KAlarm::weekDay_to_localeDayInWeek(dayOfWeek)]->setChecked(true);
01194 }
01195
01196
01197
01198
01199 QWidget* DayWeekRule::validate(QString& errorMessage)
01200 {
01201 for (int i = 0; i < 7; ++i)
01202 if (mDayBox[i]->isChecked())
01203 return 0;
01204 errorMessage = i18n("No day selected");
01205 return mDayBox[0];
01206 }
01207
01208
01209
01210
01211 void DayWeekRule::saveState()
01212 {
01213 Rule::saveState();
01214 mSavedDays = days();
01215 }
01216
01217
01218
01219
01220 bool DayWeekRule::stateChanged() const
01221 {
01222 return (Rule::stateChanged()
01223 || mSavedDays != days());
01224 }
01225
01226
01227
01228
01229
01230
01231
01232 DailyRule::DailyRule(bool readOnly, QWidget* parent, const char* name)
01233 : DayWeekRule(i18n("day(s)"),
01234 i18n("Enter the number of days between repetitions of the alarm"),
01235 #if KDE_IS_VERSION(3,9,0)
01236 i18n("Select the days of the week on which the alarm is allowed to occur"),
01237 #else
01238 i18n("Select the days of the week on which to repeat the alarm"),
01239 #endif
01240 readOnly, parent, name)
01241 { }
01242
01243
01244
01245
01246
01247
01248
01249 WeeklyRule::WeeklyRule(bool readOnly, QWidget* parent, const char* name)
01250 : DayWeekRule(i18n("week(s)"),
01251 i18n("Enter the number of weeks between repetitions of the alarm"),
01252 i18n("Select the days of the week on which to repeat the alarm"),
01253 readOnly, parent, name)
01254 { }
01255
01256
01257
01258
01259
01260
01261
01262 MonthYearRule::MonthYearRule(const QString& freqText, const QString& freqWhatsThis, bool allowEveryWeek,
01263 bool readOnly, QWidget* parent, const char* name)
01264 : Rule(freqText, freqWhatsThis, false, readOnly, parent, name),
01265 mEveryWeek(allowEveryWeek)
01266 {
01267 mButtonGroup = new ButtonGroup(this);
01268 mButtonGroup->hide();
01269
01270
01271 QHBox* box = new QHBox(this);
01272 box->setSpacing(KDialog::spacingHint());
01273 layout()->addWidget(box);
01274
01275 mDayButton = new RadioButton(i18n("On day number in the month", "O&n day"), box);
01276 mDayButton->setFixedSize(mDayButton->sizeHint());
01277 mDayButton->setReadOnly(readOnly);
01278 mDayButtonId = mButtonGroup->insert(mDayButton);
01279 QWhatsThis::add(mDayButton, i18n("Repeat the alarm on the selected day of the month"));
01280
01281 mDayCombo = new ComboBox(false, box);
01282 mDayCombo->setSizeLimit(11);
01283 for (int i = 0; i < 31; ++i)
01284 mDayCombo->insertItem(QString::number(i + 1));
01285 mDayCombo->insertItem(i18n("Last day of month", "Last"));
01286 mDayCombo->setFixedSize(mDayCombo->sizeHint());
01287 mDayCombo->setReadOnly(readOnly);
01288 QWhatsThis::add(mDayCombo, i18n("Select the day of the month on which to repeat the alarm"));
01289 mDayButton->setFocusWidget(mDayCombo);
01290 connect(mDayCombo, SIGNAL(activated(int)), SLOT(slotDaySelected(int)));
01291
01292 box->setStretchFactor(new QWidget(box), 1);
01293 box->setFixedHeight(box->sizeHint().height());
01294
01295
01296 box = new QHBox(this);
01297 box->setSpacing(KDialog::spacingHint());
01298 layout()->addWidget(box);
01299
01300 mPosButton = new RadioButton(i18n("On the 1st Tuesday", "On t&he"), box);
01301 mPosButton->setFixedSize(mPosButton->sizeHint());
01302 mPosButton->setReadOnly(readOnly);
01303 mPosButtonId = mButtonGroup->insert(mPosButton);
01304 QWhatsThis::add(mPosButton,
01305 i18n("Repeat the alarm on one day of the week, in the selected week of the month"));
01306
01307 mWeekCombo = new ComboBox(false, box);
01308 mWeekCombo->insertItem(i18n("1st"));
01309 mWeekCombo->insertItem(i18n("2nd"));
01310 mWeekCombo->insertItem(i18n("3rd"));
01311 mWeekCombo->insertItem(i18n("4th"));
01312 mWeekCombo->insertItem(i18n("5th"));
01313 mWeekCombo->insertItem(i18n("Last Monday in March", "Last"));
01314 mWeekCombo->insertItem(i18n("2nd Last"));
01315 mWeekCombo->insertItem(i18n("3rd Last"));
01316 mWeekCombo->insertItem(i18n("4th Last"));
01317 mWeekCombo->insertItem(i18n("5th Last"));
01318 if (mEveryWeek)
01319 {
01320 mWeekCombo->insertItem(i18n("Every (Monday...) in month", "Every"));
01321 mWeekCombo->setSizeLimit(11);
01322 }
01323 QWhatsThis::add(mWeekCombo, i18n("Select the week of the month in which to repeat the alarm"));
01324 mWeekCombo->setFixedSize(mWeekCombo->sizeHint());
01325 mWeekCombo->setReadOnly(readOnly);
01326 mPosButton->setFocusWidget(mWeekCombo);
01327
01328 mDayOfWeekCombo = new ComboBox(false, box);
01329 const KCalendarSystem* calendar = KGlobal::locale()->calendar();
01330 for (int i = 0; i < 7; ++i)
01331 {
01332 int day = KAlarm::localeDayInWeek_to_weekDay(i);
01333 mDayOfWeekCombo->insertItem(calendar->weekDayName(day));
01334 }
01335 mDayOfWeekCombo->setReadOnly(readOnly);
01336 QWhatsThis::add(mDayOfWeekCombo, i18n("Select the day of the week on which to repeat the alarm"));
01337
01338 box->setStretchFactor(new QWidget(box), 1);
01339 box->setFixedHeight(box->sizeHint().height());
01340 connect(mButtonGroup, SIGNAL(buttonSet(int)), SLOT(clicked(int)));
01341 }
01342
01343 MonthYearRule::DayPosType MonthYearRule::type() const
01344 {
01345 return (mButtonGroup->selectedId() == mDayButtonId) ? DATE : POS;
01346 }
01347
01348 void MonthYearRule::setType(MonthYearRule::DayPosType type)
01349 {
01350 mButtonGroup->setButton(type == DATE ? mDayButtonId : mPosButtonId);
01351 }
01352
01353 void MonthYearRule::setDefaultValues(int dayOfMonth, int dayOfWeek)
01354 {
01355 --dayOfMonth;
01356 mDayCombo->setCurrentItem(dayOfMonth);
01357 mWeekCombo->setCurrentItem(dayOfMonth / 7);
01358 mDayOfWeekCombo->setCurrentItem(KAlarm::weekDay_to_localeDayInWeek(dayOfWeek));
01359 }
01360
01361 int MonthYearRule::date() const
01362 {
01363 int daynum = mDayCombo->currentItem() + 1;
01364 return (daynum <= 31) ? daynum : 31 - daynum;
01365 }
01366
01367 int MonthYearRule::week() const
01368 {
01369 int weeknum = mWeekCombo->currentItem() + 1;
01370 return (weeknum <= 5) ? weeknum : (weeknum == 11) ? 0 : 5 - weeknum;
01371 }
01372
01373 int MonthYearRule::dayOfWeek() const
01374 {
01375 return KAlarm::localeDayInWeek_to_weekDay(mDayOfWeekCombo->currentItem());
01376 }
01377
01378 void MonthYearRule::setDate(int dayOfMonth)
01379 {
01380 mButtonGroup->setButton(mDayButtonId);
01381 mDayCombo->setCurrentItem(dayOfMonth > 0 ? dayOfMonth - 1 : dayOfMonth < 0 ? 30 - dayOfMonth : 0);
01382 }
01383
01384 void MonthYearRule::setPosition(int week, int dayOfWeek)
01385 {
01386 mButtonGroup->setButton(mPosButtonId);
01387 mWeekCombo->setCurrentItem((week > 0) ? week - 1 : (week < 0) ? 4 - week : mEveryWeek ? 10 : 0);
01388 mDayOfWeekCombo->setCurrentItem(KAlarm::weekDay_to_localeDayInWeek(dayOfWeek));
01389 }
01390
01391 void MonthYearRule::enableSelection(DayPosType type)
01392 {
01393 bool date = (type == DATE);
01394 mDayCombo->setEnabled(date);
01395 mWeekCombo->setEnabled(!date);
01396 mDayOfWeekCombo->setEnabled(!date);
01397 }
01398
01399 void MonthYearRule::clicked(int id)
01400 {
01401 enableSelection(id == mDayButtonId ? DATE : POS);
01402 }
01403
01404 void MonthYearRule::slotDaySelected(int index)
01405 {
01406 daySelected(index <= 30 ? index + 1 : 30 - index);
01407 }
01408
01409
01410
01411
01412 void MonthYearRule::saveState()
01413 {
01414 Rule::saveState();
01415 mSavedType = type();
01416 if (mSavedType == DATE)
01417 mSavedDay = date();
01418 else
01419 {
01420 mSavedWeek = week();
01421 mSavedWeekDay = dayOfWeek();
01422 }
01423 }
01424
01425
01426
01427
01428 bool MonthYearRule::stateChanged() const
01429 {
01430 if (Rule::stateChanged()
01431 || mSavedType != type())
01432 return true;
01433 if (mSavedType == DATE)
01434 {
01435 if (mSavedDay != date())
01436 return true;
01437 }
01438 else
01439 {
01440 if (mSavedWeek != week()
01441 || mSavedWeekDay != dayOfWeek())
01442 return true;
01443 }
01444 return false;
01445 }
01446
01447
01448
01449
01450
01451
01452
01453 MonthlyRule::MonthlyRule(bool readOnly, QWidget* parent, const char* name)
01454 : MonthYearRule(i18n("month(s)"),
01455 i18n("Enter the number of months between repetitions of the alarm"),
01456 false, readOnly, parent, name)
01457 { }
01458
01459
01460
01461
01462
01463
01464
01465 YearlyRule::YearlyRule(bool readOnly, QWidget* parent, const char* name)
01466 : MonthYearRule(i18n("year(s)"),
01467 i18n("Enter the number of years between repetitions of the alarm"),
01468 true, readOnly, parent, name)
01469 {
01470
01471 QBoxLayout* hlayout = new QHBoxLayout(layout(), KDialog::spacingHint());
01472 QLabel* label = new QLabel(i18n("List of months to select", "Months:"), this);
01473 label->setFixedSize(label->sizeHint());
01474 hlayout->addWidget(label, 0, Qt::AlignAuto | Qt::AlignTop);
01475
01476
01477 QWidget* w = new QWidget(this);
01478 hlayout->addWidget(w, 1, Qt::AlignAuto);
01479 QGridLayout* grid = new QGridLayout(w, 4, 3, 0, KDialog::spacingHint());
01480 const KCalendarSystem* calendar = KGlobal::locale()->calendar();
01481 int year = QDate::currentDate().year();
01482 for (int i = 0; i < 12; ++i)
01483 {
01484 mMonthBox[i] = new CheckBox(calendar->monthName(i + 1, year, true), w);
01485 mMonthBox[i]->setFixedSize(mMonthBox[i]->sizeHint());
01486 mMonthBox[i]->setReadOnly(readOnly);
01487 grid->addWidget(mMonthBox[i], i%3, i/3, Qt::AlignAuto);
01488 }
01489 connect(mMonthBox[1], SIGNAL(toggled(bool)), SLOT(enableFeb29()));
01490 w->setFixedHeight(w->sizeHint().height());
01491 QWhatsThis::add(w, i18n("Select the months of the year in which to repeat the alarm"));
01492
01493
01494 QHBox* f29box = new QHBox(this);
01495 layout()->addWidget(f29box);
01496 QHBox* box = new QHBox(f29box);
01497 box->setSpacing(KDialog::spacingHint());
01498 mFeb29Label = new QLabel(i18n("February 2&9th alarm in non-leap years:"), box);
01499 mFeb29Label->setFixedSize(mFeb29Label->sizeHint());
01500 mFeb29Combo = new ComboBox(false, box);
01501 mFeb29Combo->insertItem(i18n("No date", "None"));
01502 mFeb29Combo->insertItem(i18n("1st March (short form)", "1 Mar"));
01503 mFeb29Combo->insertItem(i18n("28th February (short form)", "28 Feb"));
01504 mFeb29Combo->setFixedSize(mFeb29Combo->sizeHint());
01505 mFeb29Combo->setReadOnly(readOnly);
01506 mFeb29Label->setBuddy(mFeb29Combo);
01507 box->setFixedSize(box->sizeHint());
01508 QWhatsThis::add(box,
01509 i18n("Select which date, if any, the February 29th alarm should trigger in non-leap years"));
01510 new QWidget(f29box);
01511 f29box->setFixedHeight(f29box->sizeHint().height());
01512 }
01513
01514 void YearlyRule::setDefaultValues(int dayOfMonth, int dayOfWeek, int month)
01515 {
01516 MonthYearRule::setDefaultValues(dayOfMonth, dayOfWeek);
01517 --month;
01518 for (int i = 0; i < 12; ++i)
01519 mMonthBox[i]->setChecked(i == month);
01520 setFeb29Type(Preferences::defaultFeb29Type());
01521 daySelected(dayOfMonth);
01522 }
01523
01524
01525
01526
01527
01528 QValueList<int> YearlyRule::months() const
01529 {
01530 QValueList<int> mnths;
01531 for (int i = 0; i < 12; ++i)
01532 if (mMonthBox[i]->isChecked() && mMonthBox[i]->isEnabled())
01533 mnths.append(i + 1);
01534 return mnths;
01535 }
01536
01537
01538
01539
01540 void YearlyRule::setMonths(const QValueList<int>& mnths)
01541 {
01542 bool checked[12];
01543 for (int i = 0; i < 12; ++i)
01544 checked[i] = false;
01545 for (QValueListConstIterator<int> it = mnths.begin(); it != mnths.end(); ++it)
01546 checked[(*it) - 1] = true;
01547 for (int i = 0; i < 12; ++i)
01548 mMonthBox[i]->setChecked(checked[i]);
01549 enableFeb29();
01550 }
01551
01552
01553
01554
01555 KARecurrence::Feb29Type YearlyRule::feb29Type() const
01556 {
01557 if (mFeb29Combo->isEnabled())
01558 {
01559 switch (mFeb29Combo->currentItem())
01560 {
01561 case 1: return KARecurrence::FEB29_MAR1;
01562 case 2: return KARecurrence::FEB29_FEB28;
01563 default: break;
01564 }
01565 }
01566 return KARecurrence::FEB29_FEB29;
01567 }
01568
01569
01570
01571
01572 void YearlyRule::setFeb29Type(KARecurrence::Feb29Type type)
01573 {
01574 int index;
01575 switch (type)
01576 {
01577 default:
01578 case KARecurrence::FEB29_FEB29: index = 0; break;
01579 case KARecurrence::FEB29_MAR1: index = 1; break;
01580 case KARecurrence::FEB29_FEB28: index = 2; break;
01581 }
01582 mFeb29Combo->setCurrentItem(index);
01583 }
01584
01585
01586
01587
01588 QWidget* YearlyRule::validate(QString& errorMessage)
01589 {
01590 for (int i = 0; i < 12; ++i)
01591 if (mMonthBox[i]->isChecked() && mMonthBox[i]->isEnabled())
01592 return 0;
01593 errorMessage = i18n("No month selected");
01594 return mMonthBox[0];
01595 }
01596
01597
01598
01599
01600
01601 void YearlyRule::clicked(int id)
01602 {
01603 MonthYearRule::clicked(id);
01604 daySelected(buttonType(id) == DATE ? date() : 1);
01605 }
01606
01607
01608
01609
01610
01611 void YearlyRule::daySelected(int day)
01612 {
01613 mMonthBox[1]->setEnabled(day <= 29);
01614 bool enable = (day != 31);
01615 mMonthBox[3]->setEnabled(enable);
01616 mMonthBox[5]->setEnabled(enable);
01617 mMonthBox[8]->setEnabled(enable);
01618 mMonthBox[10]->setEnabled(enable);
01619 enableFeb29();
01620 }
01621
01622
01623
01624
01625
01626 void YearlyRule::enableFeb29()
01627 {
01628 bool enable = (type() == DATE && date() == 29 && mMonthBox[1]->isChecked() && mMonthBox[1]->isEnabled());
01629 mFeb29Label->setEnabled(enable);
01630 mFeb29Combo->setEnabled(enable);
01631 }
01632
01633
01634
01635
01636 void YearlyRule::saveState()
01637 {
01638 MonthYearRule::saveState();
01639 mSavedMonths = months();
01640 mSavedFeb29Type = feb29Type();
01641 }
01642
01643
01644
01645
01646 bool YearlyRule::stateChanged() const
01647 {
01648 return (MonthYearRule::stateChanged()
01649 || mSavedMonths != months()
01650 || mSavedFeb29Type != feb29Type());
01651 }