00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include "kalarm.h"
00026
00027 #include <qlayout.h>
00028 #include <qgroupbox.h>
00029 #include <qhbox.h>
00030 #include <qradiobutton.h>
00031 #include <qcheckbox.h>
00032 #include <qpushbutton.h>
00033 #include <qvalidator.h>
00034 #include <qwhatsthis.h>
00035
00036 #include <kdialog.h>
00037 #include <kmessagebox.h>
00038 #include <klocale.h>
00039
00040 #include "dateedit.h"
00041 #include "datetime.moc"
00042
00043
00044
00045
00046
00047 AlarmTimeWidget::AlarmTimeWidget(const QString& groupBoxTitle, int mode, QWidget* parent, const char* name)
00048 : ButtonGroup(groupBoxTitle, parent, name)
00049 {
00050 init(mode);
00051 }
00052
00053
00054
00055
00056 AlarmTimeWidget::AlarmTimeWidget(int mode, QWidget* parent, const char* name)
00057 : ButtonGroup(parent, name)
00058 {
00059 setFrameStyle(QFrame::NoFrame);
00060 init(mode);
00061 }
00062
00063 void AlarmTimeWidget::init(int mode)
00064 {
00065 connect(this, SIGNAL(buttonSet(int)), SLOT(slotButtonSet(int)));
00066 connect(this, SIGNAL(clicked(int)), SLOT(slotButtonClicked(int)));
00067 QBoxLayout* topLayout = new QVBoxLayout(this, 0, KDialog::spacingHint());
00068 if (!title().isEmpty())
00069 topLayout->setMargin(marginKDE2 + KDialog::marginHint());
00070 topLayout->addSpacing(fontMetrics().lineSpacing()/2);
00071
00072
00073 atTimeRadio = new QRadioButton(((mode & DEFER_TIME) ? i18n("&Defer to date/time:") : i18n("At &date/time:")), this, "atTimeRadio");
00074 atTimeRadio->setFixedSize(atTimeRadio->sizeHint());
00075 QWhatsThis::add(atTimeRadio,
00076 ((mode & DEFER_TIME) ? i18n("Reschedule the alarm to the specified date and time.")
00077 : i18n("Schedule the alarm at the specified date and time.")));
00078
00079
00080 dateEdit = new DateEdit(this);
00081 dateEdit->setFixedSize(dateEdit->sizeHint());
00082 QWhatsThis::add(dateEdit, i18n("Enter the date to schedule the alarm."));
00083 connect(dateEdit, SIGNAL(dateChanged(QDate)), this, SLOT(slotDateChanged(QDate)));
00084
00085
00086 QHBox* timeBox = new QHBox(this);
00087 timeBox->setSpacing(2*KDialog::spacingHint());
00088 timeEdit = new TimeSpinBox(timeBox);
00089 timeEdit->setValue(1439);
00090 timeEdit->setFixedSize(timeEdit->sizeHint());
00091 QWhatsThis::add(timeEdit, i18n("Enter the time to schedule the alarm."));
00092 connect(timeEdit, SIGNAL(valueChanged(int)), this, SLOT(slotTimeChanged(int)));
00093
00094 if (mode & DEFER_TIME)
00095 {
00096 anyTimeAllowed = false;
00097 anyTimeCheckBox = 0;
00098 }
00099 else
00100 {
00101 anyTimeAllowed = true;
00102 anyTimeCheckBox = new QCheckBox(i18n("An&y time"), timeBox);
00103 anyTimeCheckBox->setFixedSize(anyTimeCheckBox->sizeHint());
00104 QWhatsThis::add(anyTimeCheckBox, i18n("Schedule the alarm for any time during the day"));
00105 connect(anyTimeCheckBox, SIGNAL(toggled(bool)), this, SLOT(anyTimeToggled(bool)));
00106 }
00107
00108
00109 afterTimeRadio = new QRadioButton(((mode & DEFER_TIME) ? i18n("Defer for time &interval:") : i18n("Time from no&w:")),
00110 this, "afterTimeRadio");
00111 afterTimeRadio->setFixedSize(afterTimeRadio->sizeHint());
00112 QWhatsThis::add(afterTimeRadio,
00113 ((mode & DEFER_TIME) ? i18n("Reschedule the alarm for the specified time interval after now.")
00114 : i18n("Schedule the alarm after the specified time interval from now.")));
00115
00116
00117 delayTime = new TimeSpinBox(1, 99*60+59, this);
00118 delayTime->setValue(1439);
00119 delayTime->setFixedSize(delayTime->sizeHint());
00120 QWhatsThis::add(delayTime,
00121 i18n("Enter the length of time (in hours and minutes) after the current time to schedule the alarm."));
00122 connect(delayTime, SIGNAL(valueChanged(int)), this, SLOT(delayTimeChanged(int)));
00123
00124
00125 if (mode & NARROW)
00126 {
00127 QGridLayout* grid = new QGridLayout(topLayout, 2, 2, KDialog::spacingHint());
00128 grid->addWidget(atTimeRadio, 0, 0);
00129 grid->addWidget(dateEdit, 0, 1, Qt::AlignLeft);
00130 grid->addWidget(timeBox, 1, 1, Qt::AlignLeft);
00131 grid->setColStretch(2, 1);
00132 topLayout->addStretch();
00133 QBoxLayout* layout = new QHBoxLayout(topLayout, KDialog::spacingHint());
00134 layout->addWidget(afterTimeRadio);
00135 layout->addWidget(delayTime);
00136 layout->addStretch();
00137 }
00138 else
00139 {
00140 QGridLayout* grid = new QGridLayout(topLayout, 2, 3, KDialog::spacingHint());
00141 grid->addWidget(atTimeRadio, 0, 0, Qt::AlignLeft);
00142 grid->addWidget(dateEdit, 0, 1, Qt::AlignLeft);
00143 grid->addWidget(timeBox, 0, 2, Qt::AlignLeft);
00144 grid->setRowStretch(0, 1);
00145 grid->addWidget(afterTimeRadio, 1, 0, Qt::AlignLeft);
00146 grid->addWidget(delayTime, 1, 1, Qt::AlignLeft);
00147 grid->setColStretch(3, 1);
00148 topLayout->addStretch();
00149 }
00150
00151
00152 setButton(id(atTimeRadio));
00153
00154
00155
00156 int firstInterval = 61 - QTime::currentTime().second();
00157 timer.start(1000 * firstInterval);
00158 timerSyncing = (firstInterval != 60);
00159 connect(&timer, SIGNAL(timeout()), this, SLOT(slotTimer()));
00160 }
00161
00162
00163
00164
00165
00166
00167
00168 QWidget* AlarmTimeWidget::getDateTime(QDateTime& dateTime, bool& anyTime, bool showErrorMessage) const
00169 {
00170 QTime nowt = QTime::currentTime();
00171 QDateTime now(QDate::currentDate(), QTime(nowt.hour(), nowt.minute()));
00172 if (atTimeRadio->isOn())
00173 {
00174 dateTime.setDate(dateEdit->date());
00175 anyTime = anyTimeAllowed && anyTimeCheckBox && anyTimeCheckBox->isChecked();
00176 if (anyTime)
00177 {
00178 dateTime.setTime(QTime());
00179 if (dateTime.date() < now.date())
00180 {
00181 if (showErrorMessage)
00182 KMessageBox::sorry(const_cast<AlarmTimeWidget*>(this), i18n("Alarm date has already expired"));
00183 return dateEdit;
00184 }
00185 }
00186 else
00187 {
00188 dateTime.setTime(timeEdit->time());
00189 if (dateTime <= now.addSecs(1))
00190 {
00191 if (showErrorMessage)
00192 KMessageBox::sorry(const_cast<AlarmTimeWidget*>(this), i18n("Alarm time has already expired"));
00193 return timeEdit;
00194 }
00195 }
00196 }
00197 else
00198 {
00199 dateTime = now.addSecs(delayTime->value() * 60);
00200 anyTime = false;
00201 }
00202 return 0;
00203 }
00204
00205
00206
00207
00208 void AlarmTimeWidget::setDateTime(const QDateTime& dt, bool anyTime)
00209 {
00210 timeEdit->setValue(dt.time().hour()*60 + dt.time().minute());
00211 dateEdit->setDate(dt.date());
00212 dateTimeChanged();
00213 QDate now = QDate::currentDate();
00214 dateEdit->setMinDate(dt.date() < now ? dt.date() : now);
00215 if (anyTimeCheckBox)
00216 {
00217 if (anyTime)
00218 anyTimeAllowed = true;
00219 anyTimeCheckBox->setChecked(anyTime);
00220 }
00221 }
00222
00223
00224
00225
00226 void AlarmTimeWidget::enableAnyTime(bool enable)
00227 {
00228 if (anyTimeCheckBox)
00229 {
00230 anyTimeAllowed = enable;
00231 bool at = atTimeRadio->isOn();
00232 anyTimeCheckBox->setEnabled(enable && at);
00233 if (at)
00234 timeEdit->setEnabled(!enable || !anyTimeCheckBox->isChecked());
00235 }
00236 }
00237
00238
00239
00240
00241 void AlarmTimeWidget::slotTimer()
00242 {
00243 if (timerSyncing)
00244 {
00245
00246 timer.changeInterval(1000 * 60);
00247 timerSyncing = false;
00248 }
00249 if (atTimeRadio->isOn())
00250 dateTimeChanged();
00251 else
00252 delayTimeChanged(delayTime->value());
00253 }
00254
00255
00256
00257
00258
00259
00260 void AlarmTimeWidget::slotButtonSet(int)
00261 {
00262 bool at = atTimeRadio->isOn();
00263 dateEdit->setEnabled(at);
00264 timeEdit->setEnabled(at && (!anyTimeAllowed || !anyTimeCheckBox || !anyTimeCheckBox->isChecked()));
00265 if (anyTimeCheckBox)
00266 anyTimeCheckBox->setEnabled(at && anyTimeAllowed);
00267
00268 QDateTime dt(dateEdit->date(), timeEdit->time());
00269 int minutes = (QDateTime::currentDateTime().secsTo(dt) + 59) / 60;
00270 if (minutes <= 0)
00271 delayTime->setValid(true);
00272 delayTime->setEnabled(!at);
00273 }
00274
00275
00276
00277
00278
00279 void AlarmTimeWidget::slotButtonClicked(int)
00280 {
00281 if (atTimeRadio->isOn())
00282 dateEdit->setFocus();
00283 else
00284 delayTime->setFocus();
00285 }
00286
00287
00288
00289 void AlarmTimeWidget::anyTimeToggled(bool on)
00290 {
00291 timeEdit->setEnabled((!anyTimeAllowed || !on) && atTimeRadio->isOn());
00292 }
00293
00294
00295
00296
00297
00298 void AlarmTimeWidget::dateTimeChanged()
00299 {
00300 QDateTime dt(dateEdit->date(), timeEdit->time());
00301 int minutes = (QDateTime::currentDateTime().secsTo(dt) + 59) / 60;
00302 bool blocked = delayTime->signalsBlocked();
00303 delayTime->blockSignals(true);
00304 if (minutes <= 0 || minutes > delayTime->maxValue())
00305 delayTime->setValid(false);
00306 else
00307 delayTime->setValue(minutes);
00308 delayTime->blockSignals(blocked);
00309 }
00310
00311
00312
00313
00314
00315 void AlarmTimeWidget::delayTimeChanged(int minutes)
00316 {
00317 if (delayTime->valid())
00318 {
00319 QDateTime dt = QDateTime::currentDateTime().addSecs(minutes * 60);
00320 bool blockedT = timeEdit->signalsBlocked();
00321 bool blockedD = dateEdit->signalsBlocked();
00322 timeEdit->blockSignals(true);
00323 dateEdit->blockSignals(true);
00324 timeEdit->setValue(dt.time().hour()*60 + dt.time().minute());
00325 dateEdit->setDate(dt.date());
00326 timeEdit->blockSignals(blockedT);
00327 dateEdit->blockSignals(blockedD);
00328 }
00329 }
00330
00331
00332
00333
00334
00335 class TimeSpinBox::TimeValidator : public QValidator
00336 {
00337 public:
00338 TimeValidator(int minMin, int maxMin, QWidget* parent, const char* name = 0L)
00339 : QValidator(parent, name), minMinute(minMin), maxMinute(maxMin) { }
00340 virtual State validate(QString&, int&) const;
00341 int minMinute, maxMinute;
00342 };
00343
00344
00345
00346 TimeSpinBox::TimeSpinBox(QWidget* parent, const char* name)
00347 : SpinBox2(0, 1439, 1, 60, parent, name),
00348 minimumValue(0),
00349 invalid(false),
00350 enteredSetValue(false)
00351 {
00352 validator = new TimeValidator(0, 1439, this, "TimeSpinBox validator");
00353 setValidator(validator);
00354 setWrapping(true);
00355 setShiftSteps(5, 360);
00356 }
00357
00358
00359 TimeSpinBox::TimeSpinBox(int minMinute, int maxMinute, QWidget* parent, const char* name)
00360 : SpinBox2(minMinute, maxMinute, 1, 60, parent, name),
00361 minimumValue(minMinute),
00362 invalid(false),
00363 enteredSetValue(false)
00364 {
00365 validator = new TimeValidator(minMinute, maxMinute, this, "TimeSpinBox validator");
00366 setValidator(validator);
00367 setShiftSteps(5, 360);
00368 }
00369
00370 QString TimeSpinBox::shiftWhatsThis()
00371 {
00372 return i18n("\nPress the Shift key while clicking the spin buttons to adjust the time by a larger step (6 hours / 5 minutes).");
00373 }
00374
00375 QTime TimeSpinBox::time() const
00376 {
00377 return QTime(value() / 60, value() % 60);
00378 }
00379
00380 QString TimeSpinBox::mapValueToText(int v)
00381 {
00382 QString s;
00383 s.sprintf("%02d:%02d", v/60, v%60);
00384 return s;
00385 }
00386
00387
00388
00389
00390
00391
00392 int TimeSpinBox::mapTextToValue(bool* ok)
00393 {
00394 QString text = cleanText();
00395 int colon = text.find(':');
00396 if (colon >= 0)
00397 {
00398 QString hour = text.left(colon).stripWhiteSpace();
00399 QString minute = text.mid(colon + 1).stripWhiteSpace();
00400 if (!hour.isEmpty() && !minute.isEmpty())
00401 {
00402 bool okhour, okmin;
00403 int m = minute.toUInt(&okmin);
00404 int t = hour.toUInt(&okhour) * 60 + m;
00405 if (okhour && okmin && m < 60 && t >= minimumValue && t <= maxValue())
00406 {
00407 *ok = true;
00408 return t;
00409 }
00410 }
00411 }
00412 *ok = false;
00413 return 0;
00414 }
00415
00416
00417
00418
00419
00420
00421 void TimeSpinBox::setValid(bool valid)
00422 {
00423 if (valid && invalid)
00424 {
00425 invalid = false;
00426 if (value() < minimumValue)
00427 SpinBox2::setValue(minimumValue);
00428 setSpecialValueText(QString());
00429 setMinValue(minimumValue);
00430 }
00431 else if (!valid && !invalid)
00432 {
00433 invalid = true;
00434 setMinValue(minimumValue - 1);
00435 setSpecialValueText(QString::fromLatin1("**:**"));
00436 SpinBox2::setValue(minimumValue - 1);
00437 }
00438 }
00439
00440
00441
00442
00443 void TimeSpinBox::setValue(int minutes)
00444 {
00445 if (!enteredSetValue)
00446 {
00447 enteredSetValue = true;
00448 if (minutes > maxValue())
00449 setValid(false);
00450 else
00451 {
00452 if (invalid)
00453 {
00454 invalid = false;
00455 setSpecialValueText(QString());
00456 setMinValue(minimumValue);
00457 }
00458 SpinBox2::setValue(minutes);
00459 enteredSetValue = false;
00460 }
00461 }
00462 }
00463
00464
00465
00466
00467
00468 void TimeSpinBox::stepUp()
00469 {
00470 if (invalid)
00471 setValid(true);
00472 else
00473 SpinBox2::stepUp();
00474 }
00475
00476 void TimeSpinBox::stepDown()
00477 {
00478 if (invalid)
00479 setValid(true);
00480 else
00481 SpinBox2::stepDown();
00482 }
00483
00484 bool TimeSpinBox::valid() const
00485 {
00486 return value() >= minimumValue;
00487 }
00488
00489
00490
00491
00492
00493
00494 QValidator::State TimeSpinBox::TimeValidator::validate(QString& text, int& ) const
00495 {
00496 QValidator::State state = QValidator::Acceptable;
00497 QString hour;
00498 int hr;
00499 int mn = 0;
00500 int colon = text.find(':');
00501 if (colon >= 0)
00502 {
00503 QString minute = text.mid(colon + 1).stripWhiteSpace();
00504 if (minute.isEmpty())
00505 state = QValidator::Intermediate;
00506 else
00507 {
00508 bool ok;
00509 if ((mn = minute.toUInt(&ok)) >= 60 || !ok)
00510 return QValidator::Invalid;
00511 }
00512
00513 hour = text.left(colon).stripWhiteSpace();
00514 }
00515 else
00516 {
00517 state = QValidator::Intermediate;
00518 hour = text;
00519 }
00520
00521 if (hour.isEmpty())
00522 return QValidator::Intermediate;
00523 bool ok;
00524 if ((hr = hour.toUInt(&ok)) > maxMinute/60 || !ok)
00525 return QValidator::Invalid;
00526 if (state == QValidator::Acceptable)
00527 {
00528 int t = hr * 60 + mn;
00529 if (t < minMinute || t > maxMinute)
00530 return QValidator::Invalid;
00531 }
00532 return state;
00533 }