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 #if KDE_IS_VERSION(3,9,0)
01228 i18n("Select the days of the week on which the alarm is allowed to occur"),
01229 #else
01230 i18n("Select the days of the week on which to repeat the alarm"),
01231 #endif
01232 readOnly, parent, name)
01233 { }
01234
01235
01236
01237
01238
01239
01240
01241 WeeklyRule::WeeklyRule(bool readOnly, QWidget* parent, const char* name)
01242 : DayWeekRule(i18n("week(s)"),
01243 i18n("Enter the number of weeks between repetitions of the alarm"),
01244 i18n("Select the days of the week on which to repeat the alarm"),
01245 readOnly, parent, name)
01246 { }
01247
01248
01249
01250
01251
01252
01253
01254 MonthYearRule::MonthYearRule(const QString& freqText, const QString& freqWhatsThis, bool allowEveryWeek,
01255 bool readOnly, QWidget* parent, const char* name)
01256 : Rule(freqText, freqWhatsThis, false, readOnly, parent, name),
01257 mEveryWeek(allowEveryWeek)
01258 {
01259 mButtonGroup = new ButtonGroup(this);
01260 mButtonGroup->hide();
01261
01262
01263 QHBox* box = new QHBox(this);
01264 box->setSpacing(KDialog::spacingHint());
01265 layout()->addWidget(box);
01266
01267 mDayButton = new RadioButton(i18n("On day number in the month", "O&n day"), box);
01268 mDayButton->setFixedSize(mDayButton->sizeHint());
01269 mDayButton->setReadOnly(readOnly);
01270 mDayButtonId = mButtonGroup->insert(mDayButton);
01271 QWhatsThis::add(mDayButton, i18n("Repeat the alarm on the selected day of the month"));
01272
01273 mDayCombo = new ComboBox(false, box);
01274 mDayCombo->setSizeLimit(11);
01275 for (int i = 0; i < 31; ++i)
01276 mDayCombo->insertItem(QString::number(i + 1));
01277 mDayCombo->insertItem(i18n("Last day of month", "Last"));
01278 mDayCombo->setFixedSize(mDayCombo->sizeHint());
01279 mDayCombo->setReadOnly(readOnly);
01280 QWhatsThis::add(mDayCombo, i18n("Select the day of the month on which to repeat the alarm"));
01281 mDayButton->setFocusWidget(mDayCombo);
01282 connect(mDayCombo, SIGNAL(activated(int)), SLOT(slotDaySelected(int)));
01283
01284 box->setStretchFactor(new QWidget(box), 1);
01285 box->setFixedHeight(box->sizeHint().height());
01286
01287
01288 box = new QHBox(this);
01289 box->setSpacing(KDialog::spacingHint());
01290 layout()->addWidget(box);
01291
01292 mPosButton = new RadioButton(i18n("On the 1st Tuesday", "On t&he"), box);
01293 mPosButton->setFixedSize(mPosButton->sizeHint());
01294 mPosButton->setReadOnly(readOnly);
01295 mPosButtonId = mButtonGroup->insert(mPosButton);
01296 QWhatsThis::add(mPosButton,
01297 i18n("Repeat the alarm on one day of the week, in the selected week of the month"));
01298
01299 mWeekCombo = new ComboBox(false, box);
01300 mWeekCombo->insertItem(i18n("1st"));
01301 mWeekCombo->insertItem(i18n("2nd"));
01302 mWeekCombo->insertItem(i18n("3rd"));
01303 mWeekCombo->insertItem(i18n("4th"));
01304 mWeekCombo->insertItem(i18n("5th"));
01305 mWeekCombo->insertItem(i18n("Last Monday in March", "Last"));
01306 mWeekCombo->insertItem(i18n("2nd Last"));
01307 mWeekCombo->insertItem(i18n("3rd Last"));
01308 mWeekCombo->insertItem(i18n("4th Last"));
01309 mWeekCombo->insertItem(i18n("5th Last"));
01310 if (mEveryWeek)
01311 {
01312 mWeekCombo->insertItem(i18n("Every (Monday...) in month", "Every"));
01313 mWeekCombo->setSizeLimit(11);
01314 }
01315 QWhatsThis::add(mWeekCombo, i18n("Select the week of the month in which to repeat the alarm"));
01316 mWeekCombo->setFixedSize(mWeekCombo->sizeHint());
01317 mWeekCombo->setReadOnly(readOnly);
01318 mPosButton->setFocusWidget(mWeekCombo);
01319
01320 mDayOfWeekCombo = new ComboBox(false, box);
01321 const KCalendarSystem* calendar = KGlobal::locale()->calendar();
01322 for (int i = 0; i < 7; ++i)
01323 {
01324 int day = KAlarm::localeDayInWeek_to_weekDay(i);
01325 mDayOfWeekCombo->insertItem(calendar->weekDayName(day));
01326 }
01327 mDayOfWeekCombo->setReadOnly(readOnly);
01328 QWhatsThis::add(mDayOfWeekCombo, i18n("Select the day of the week on which to repeat the alarm"));
01329
01330 box->setStretchFactor(new QWidget(box), 1);
01331 box->setFixedHeight(box->sizeHint().height());
01332 connect(mButtonGroup, SIGNAL(buttonSet(int)), SLOT(clicked(int)));
01333 }
01334
01335 MonthYearRule::DayPosType MonthYearRule::type() const
01336 {
01337 return (mButtonGroup->selectedId() == mDayButtonId) ? DATE : POS;
01338 }
01339
01340 void MonthYearRule::setType(MonthYearRule::DayPosType type)
01341 {
01342 mButtonGroup->setButton(type == DATE ? mDayButtonId : mPosButtonId);
01343 }
01344
01345 void MonthYearRule::setDefaultValues(int dayOfMonth, int dayOfWeek)
01346 {
01347 --dayOfMonth;
01348 mDayCombo->setCurrentItem(dayOfMonth);
01349 mWeekCombo->setCurrentItem(dayOfMonth / 7);
01350 mDayOfWeekCombo->setCurrentItem(KAlarm::weekDay_to_localeDayInWeek(dayOfWeek));
01351 }
01352
01353 int MonthYearRule::date() const
01354 {
01355 int daynum = mDayCombo->currentItem() + 1;
01356 return (daynum <= 31) ? daynum : 31 - daynum;
01357 }
01358
01359 int MonthYearRule::week() const
01360 {
01361 int weeknum = mWeekCombo->currentItem() + 1;
01362 return (weeknum <= 5) ? weeknum : (weeknum == 11) ? 0 : 5 - weeknum;
01363 }
01364
01365 int MonthYearRule::dayOfWeek() const
01366 {
01367 return KAlarm::localeDayInWeek_to_weekDay(mDayOfWeekCombo->currentItem());
01368 }
01369
01370 void MonthYearRule::setDate(int dayOfMonth)
01371 {
01372 mButtonGroup->setButton(mDayButtonId);
01373 mDayCombo->setCurrentItem(dayOfMonth > 0 ? dayOfMonth - 1 : dayOfMonth < 0 ? 30 - dayOfMonth : 0);
01374 }
01375
01376 void MonthYearRule::setPosition(int week, int dayOfWeek)
01377 {
01378 mButtonGroup->setButton(mPosButtonId);
01379 mWeekCombo->setCurrentItem((week > 0) ? week - 1 : (week < 0) ? 4 - week : mEveryWeek ? 10 : 0);
01380 mDayOfWeekCombo->setCurrentItem(KAlarm::weekDay_to_localeDayInWeek(dayOfWeek));
01381 }
01382
01383 void MonthYearRule::enableSelection(DayPosType type)
01384 {
01385 bool date = (type == DATE);
01386 mDayCombo->setEnabled(date);
01387 mWeekCombo->setEnabled(!date);
01388 mDayOfWeekCombo->setEnabled(!date);
01389 }
01390
01391 void MonthYearRule::clicked(int id)
01392 {
01393 enableSelection(id == mDayButtonId ? DATE : POS);
01394 }
01395
01396 void MonthYearRule::slotDaySelected(int index)
01397 {
01398 daySelected(index <= 30 ? index + 1 : 30 - index);
01399 }
01400
01401
01402
01403
01404 void MonthYearRule::saveState()
01405 {
01406 Rule::saveState();
01407 mSavedType = type();
01408 if (mSavedType == DATE)
01409 mSavedDay = date();
01410 else
01411 {
01412 mSavedWeek = week();
01413 mSavedWeekDay = dayOfWeek();
01414 }
01415 }
01416
01417
01418
01419
01420 bool MonthYearRule::stateChanged() const
01421 {
01422 if (Rule::stateChanged()
01423 || mSavedType != type())
01424 return true;
01425 if (mSavedType == DATE)
01426 {
01427 if (mSavedDay != date())
01428 return true;
01429 }
01430 else
01431 {
01432 if (mSavedWeek != week()
01433 || mSavedWeekDay != dayOfWeek())
01434 return true;
01435 }
01436 return false;
01437 }
01438
01439
01440
01441
01442
01443
01444
01445 MonthlyRule::MonthlyRule(bool readOnly, QWidget* parent, const char* name)
01446 : MonthYearRule(i18n("month(s)"),
01447 i18n("Enter the number of months between repetitions of the alarm"),
01448 false, readOnly, parent, name)
01449 { }
01450
01451
01452
01453
01454
01455
01456
01457 YearlyRule::YearlyRule(bool readOnly, QWidget* parent, const char* name)
01458 : MonthYearRule(i18n("year(s)"),
01459 i18n("Enter the number of years between repetitions of the alarm"),
01460 true, readOnly, parent, name)
01461 {
01462
01463 QBoxLayout* hlayout = new QHBoxLayout(layout(), KDialog::spacingHint());
01464 QLabel* label = new QLabel(i18n("List of months to select", "Months:"), this);
01465 label->setFixedSize(label->sizeHint());
01466 hlayout->addWidget(label, 0, Qt::AlignAuto | Qt::AlignTop);
01467
01468
01469 QWidget* w = new QWidget(this);
01470 hlayout->addWidget(w, 1, Qt::AlignAuto);
01471 QGridLayout* grid = new QGridLayout(w, 4, 3, 0, KDialog::spacingHint());
01472 const KCalendarSystem* calendar = KGlobal::locale()->calendar();
01473 int year = QDate::currentDate().year();
01474 for (int i = 0; i < 12; ++i)
01475 {
01476 mMonthBox[i] = new CheckBox(calendar->monthName(i + 1, year, true), w);
01477 mMonthBox[i]->setFixedSize(mMonthBox[i]->sizeHint());
01478 mMonthBox[i]->setReadOnly(readOnly);
01479 grid->addWidget(mMonthBox[i], i%3, i/3, Qt::AlignAuto);
01480 }
01481 connect(mMonthBox[1], SIGNAL(toggled(bool)), SLOT(enableFeb29()));
01482 w->setFixedHeight(w->sizeHint().height());
01483 QWhatsThis::add(w, i18n("Select the months of the year in which to repeat the alarm"));
01484
01485
01486 QHBox* f29box = new QHBox(this);
01487 layout()->addWidget(f29box);
01488 QHBox* box = new QHBox(f29box);
01489 box->setSpacing(KDialog::spacingHint());
01490 mFeb29Label = new QLabel(i18n("February 2&9th alarm in non-leap years:"), box);
01491 mFeb29Label->setFixedSize(mFeb29Label->sizeHint());
01492 mFeb29Combo = new ComboBox(false, box);
01493 mFeb29Combo->insertItem(i18n("No date", "None"));
01494 mFeb29Combo->insertItem(i18n("1st March (short form)", "1 Mar"));
01495 mFeb29Combo->insertItem(i18n("28th February (short form)", "28 Feb"));
01496 mFeb29Combo->setFixedSize(mFeb29Combo->sizeHint());
01497 mFeb29Combo->setReadOnly(readOnly);
01498 mFeb29Label->setBuddy(mFeb29Combo);
01499 box->setFixedSize(box->sizeHint());
01500 QWhatsThis::add(box,
01501 i18n("Select which date, if any, the February 29th alarm should trigger in non-leap years"));
01502 new QWidget(f29box);
01503 f29box->setFixedHeight(f29box->sizeHint().height());
01504 }
01505
01506 void YearlyRule::setDefaultValues(int dayOfMonth, int dayOfWeek, int month)
01507 {
01508 MonthYearRule::setDefaultValues(dayOfMonth, dayOfWeek);
01509 --month;
01510 for (int i = 0; i < 12; ++i)
01511 mMonthBox[i]->setChecked(i == month);
01512 setFeb29Type(Preferences::defaultFeb29Type());
01513 daySelected(dayOfMonth);
01514 }
01515
01516
01517
01518
01519
01520 QValueList<int> YearlyRule::months() const
01521 {
01522 QValueList<int> mnths;
01523 for (int i = 0; i < 12; ++i)
01524 if (mMonthBox[i]->isChecked() && mMonthBox[i]->isEnabled())
01525 mnths.append(i + 1);
01526 return mnths;
01527 }
01528
01529
01530
01531
01532 void YearlyRule::setMonths(const QValueList<int>& mnths)
01533 {
01534 bool checked[12];
01535 for (int i = 0; i < 12; ++i)
01536 checked[i] = false;
01537 for (QValueListConstIterator<int> it = mnths.begin(); it != mnths.end(); ++it)
01538 checked[(*it) - 1] = true;
01539 for (int i = 0; i < 12; ++i)
01540 mMonthBox[i]->setChecked(checked[i]);
01541 enableFeb29();
01542 }
01543
01544
01545
01546
01547 KARecurrence::Feb29Type YearlyRule::feb29Type() const
01548 {
01549 if (mFeb29Combo->isEnabled())
01550 {
01551 switch (mFeb29Combo->currentItem())
01552 {
01553 case 1: return KARecurrence::FEB29_MAR1;
01554 case 2: return KARecurrence::FEB29_FEB28;
01555 default: break;
01556 }
01557 }
01558 return KARecurrence::FEB29_FEB29;
01559 }
01560
01561
01562
01563
01564 void YearlyRule::setFeb29Type(KARecurrence::Feb29Type type)
01565 {
01566 int index;
01567 switch (type)
01568 {
01569 default:
01570 case KARecurrence::FEB29_FEB29: index = 0; break;
01571 case KARecurrence::FEB29_MAR1: index = 1; break;
01572 case KARecurrence::FEB29_FEB28: index = 2; break;
01573 }
01574 mFeb29Combo->setCurrentItem(index);
01575 }
01576
01577
01578
01579
01580 QWidget* YearlyRule::validate(QString& errorMessage)
01581 {
01582 for (int i = 0; i < 12; ++i)
01583 if (mMonthBox[i]->isChecked() && mMonthBox[i]->isEnabled())
01584 return 0;
01585 errorMessage = i18n("No month selected");
01586 return mMonthBox[0];
01587 }
01588
01589
01590
01591
01592
01593 void YearlyRule::clicked(int id)
01594 {
01595 MonthYearRule::clicked(id);
01596 daySelected(buttonType(id) == DATE ? date() : 1);
01597 }
01598
01599
01600
01601
01602
01603 void YearlyRule::daySelected(int day)
01604 {
01605 mMonthBox[1]->setEnabled(day <= 29);
01606 bool enable = (day != 31);
01607 mMonthBox[3]->setEnabled(enable);
01608 mMonthBox[5]->setEnabled(enable);
01609 mMonthBox[8]->setEnabled(enable);
01610 mMonthBox[10]->setEnabled(enable);
01611 enableFeb29();
01612 }
01613
01614
01615
01616
01617
01618 void YearlyRule::enableFeb29()
01619 {
01620 bool enable = (type() == DATE && date() == 29 && mMonthBox[1]->isChecked() && mMonthBox[1]->isEnabled());
01621 mFeb29Label->setEnabled(enable);
01622 mFeb29Combo->setEnabled(enable);
01623 }
01624
01625
01626
01627
01628 void YearlyRule::saveState()
01629 {
01630 MonthYearRule::saveState();
01631 mSavedMonths = months();
01632 mSavedFeb29Type = feb29Type();
01633 }
01634
01635
01636
01637
01638 bool YearlyRule::stateChanged() const
01639 {
01640 return (MonthYearRule::stateChanged()
01641 || mSavedMonths != months()
01642 || mSavedFeb29Type != feb29Type());
01643 }