File indexing completed on 2025-02-02 14:20:00
0001 /* 0002 SPDX-FileCopyrightText: 2011 John Layt <john@layt.net> 0003 0004 SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 0007 #include "kdatetimeedit.h" 0008 0009 #include "kdatecombobox.h" 0010 #include "kdatepicker.h" 0011 #include "kmessagebox.h" 0012 0013 #include "ui_kdatetimeedit.h" 0014 0015 class KDateTimeEditPrivate 0016 { 0017 public: 0018 KDateTimeEditPrivate(KDateTimeEdit *qq); 0019 virtual ~KDateTimeEditPrivate(); 0020 0021 QDateTime defaultMinDateTime(); 0022 QDateTime defaultMaxDateTime(); 0023 0024 void initWidgets(); 0025 void initDateWidget(); 0026 void initTimeWidget(); 0027 void initCalendarWidget(); 0028 void updateCalendarWidget(); 0029 void initTimeZoneWidget(); 0030 void updateTimeZoneWidget(); 0031 0032 void warnDateTime(); 0033 0034 // private Q_SLOTS: 0035 void selectCalendar(int index); 0036 void enterCalendar(const QLocale &calendarLocale); 0037 void selectTimeZone(int index); 0038 void enterTimeZone(const QByteArray &zoneId); 0039 0040 KDateTimeEdit *const q; 0041 0042 KDateTimeEdit::Options m_options; 0043 QDateTime m_dateTime; 0044 QDateTime m_minDateTime; 0045 QDateTime m_maxDateTime; 0046 QString m_minWarnMsg; 0047 QString m_maxWarnMsg; 0048 0049 QList<QLocale> m_calendarLocales; 0050 QList<QTimeZone> m_zones; 0051 0052 Ui::KDateTimeEdit ui; 0053 }; 0054 0055 KDateTimeEditPrivate::KDateTimeEditPrivate(KDateTimeEdit *qq) 0056 : q(qq) 0057 { 0058 m_options = KDateTimeEdit::ShowDate | KDateTimeEdit::EditDate | KDateTimeEdit::SelectDate | KDateTimeEdit::ShowTime | KDateTimeEdit::EditTime 0059 | KDateTimeEdit::SelectTime | KDateTimeEdit::DatePicker | KDateTimeEdit::DateKeywords; 0060 m_dateTime = QDateTime::currentDateTime(); 0061 m_dateTime.setTime(QTime(0, 0, 0)); 0062 m_calendarLocales << q->locale(); 0063 const auto zoneIds = QTimeZone::availableTimeZoneIds(); 0064 m_zones.reserve(zoneIds.size()); 0065 for (const QByteArray &zoneId : zoneIds) { 0066 m_zones << QTimeZone(zoneId); 0067 } 0068 } 0069 0070 KDateTimeEditPrivate::~KDateTimeEditPrivate() 0071 { 0072 } 0073 0074 QDateTime KDateTimeEditPrivate::defaultMinDateTime() 0075 { 0076 // TODO: Find a way to get it from QLocale 0077 // return KDateTime(calendar()->earliestValidDate(), QTime(0, 0, 0, 0)); 0078 return QDateTime(); 0079 } 0080 0081 QDateTime KDateTimeEditPrivate::defaultMaxDateTime() 0082 { 0083 // TODO: Find a way to get it from QLocale 0084 // return KDateTime(calendar()->latestValidDate(), QTime(23, 59, 59, 999)); 0085 return QDateTime(); 0086 } 0087 0088 void KDateTimeEditPrivate::initWidgets() 0089 { 0090 initDateWidget(); 0091 initTimeWidget(); 0092 initCalendarWidget(); 0093 initTimeZoneWidget(); 0094 } 0095 0096 void KDateTimeEditPrivate::initDateWidget() 0097 { 0098 ui.m_dateCombo->blockSignals(true); 0099 ui.m_dateCombo->setVisible((m_options & KDateTimeEdit::ShowDate) == KDateTimeEdit::ShowDate); 0100 KDateComboBox::Options options; 0101 if ((m_options & KDateTimeEdit::EditDate) == KDateTimeEdit::EditDate) { 0102 options = options | KDateComboBox::EditDate; 0103 } 0104 if ((m_options & KDateTimeEdit::SelectDate) == KDateTimeEdit::SelectDate) { 0105 options = options | KDateComboBox::SelectDate; 0106 } 0107 if ((m_options & KDateTimeEdit::DatePicker) == KDateTimeEdit::DatePicker) { 0108 options = options | KDateComboBox::DatePicker; 0109 } 0110 if ((m_options & KDateTimeEdit::DateKeywords) == KDateTimeEdit::DateKeywords) { 0111 options = options | KDateComboBox::DateKeywords; 0112 } 0113 ui.m_dateCombo->setOptions(options); 0114 ui.m_dateCombo->blockSignals(false); 0115 } 0116 0117 void KDateTimeEditPrivate::initTimeWidget() 0118 { 0119 ui.m_timeCombo->blockSignals(true); 0120 ui.m_timeCombo->setVisible((m_options & KDateTimeEdit::ShowTime) == KDateTimeEdit::ShowTime); 0121 KTimeComboBox::Options options; 0122 if ((m_options & KDateTimeEdit::EditTime) == KDateTimeEdit::EditTime) { 0123 options = options | KTimeComboBox::EditTime; 0124 } 0125 if ((m_options & KDateTimeEdit::SelectTime) == KDateTimeEdit::SelectTime) { 0126 options = options | KTimeComboBox::SelectTime; 0127 } 0128 if ((m_options & KDateTimeEdit::ForceTime) == KDateTimeEdit::ForceTime) { 0129 options = options | KTimeComboBox::ForceTime; 0130 } 0131 ui.m_timeCombo->setOptions(options); 0132 ui.m_timeCombo->blockSignals(false); 0133 } 0134 0135 void KDateTimeEditPrivate::initCalendarWidget() 0136 { 0137 ui.m_calendarCombo->blockSignals(true); 0138 ui.m_calendarCombo->clear(); 0139 for (const QLocale &calendarLocale : std::as_const(m_calendarLocales)) { 0140 ui.m_calendarCombo->addItem(calendarLocale.name(), calendarLocale); 0141 } 0142 ui.m_calendarCombo->setCurrentIndex(ui.m_calendarCombo->findData(q->locale())); 0143 ui.m_calendarCombo->setVisible((m_options & KDateTimeEdit::ShowCalendar) == KDateTimeEdit::ShowCalendar); 0144 ui.m_calendarCombo->setEnabled((m_options & KDateTimeEdit::SelectCalendar) == KDateTimeEdit::SelectCalendar); 0145 ui.m_calendarCombo->setEditable(false); 0146 ui.m_calendarCombo->blockSignals(false); 0147 } 0148 0149 void KDateTimeEditPrivate::updateCalendarWidget() 0150 { 0151 ui.m_calendarCombo->blockSignals(true); 0152 ui.m_calendarCombo->setCurrentIndex(ui.m_calendarCombo->findData(q->locale())); 0153 ui.m_calendarCombo->blockSignals(false); 0154 } 0155 0156 void KDateTimeEditPrivate::selectCalendar(int index) 0157 { 0158 enterCalendar(ui.m_calendarCombo->itemData(index).toLocale()); 0159 } 0160 0161 void KDateTimeEditPrivate::enterCalendar(const QLocale &calendarLocale) 0162 { 0163 q->setLocale(calendarLocale); 0164 Q_EMIT q->calendarEntered(q->locale()); 0165 } 0166 0167 void KDateTimeEditPrivate::initTimeZoneWidget() 0168 { 0169 ui.m_timeZoneCombo->blockSignals(true); 0170 ui.m_timeZoneCombo->clear(); 0171 ui.m_timeZoneCombo->addItem(KDateTimeEdit::tr("UTC", "@item:inlistbox UTC time zone"), QByteArray("UTC")); 0172 ui.m_timeZoneCombo->addItem(KDateTimeEdit::tr("Floating", "@item:inlistbox No specific time zone"), QByteArray()); 0173 for (const QTimeZone &zone : std::as_const(m_zones)) { 0174 ui.m_timeZoneCombo->addItem(QString::fromUtf8(zone.id()), zone.id()); 0175 } 0176 ui.m_timeZoneCombo->setVisible((m_options & KDateTimeEdit::ShowTimeZone) == KDateTimeEdit::ShowTimeZone); 0177 ui.m_timeZoneCombo->setEnabled((m_options & KDateTimeEdit::SelectTimeZone) == KDateTimeEdit::SelectTimeZone); 0178 ui.m_timeZoneCombo->setEditable(false); 0179 ui.m_timeZoneCombo->blockSignals(false); 0180 } 0181 0182 void KDateTimeEditPrivate::updateTimeZoneWidget() 0183 { 0184 ui.m_timeZoneCombo->blockSignals(true); 0185 ui.m_timeZoneCombo->blockSignals(false); 0186 } 0187 0188 void KDateTimeEditPrivate::selectTimeZone(int index) 0189 { 0190 enterTimeZone(ui.m_timeCombo->itemData(index).toByteArray()); 0191 } 0192 0193 void KDateTimeEditPrivate::enterTimeZone(const QByteArray &zoneId) 0194 { 0195 q->setTimeZone(QTimeZone(zoneId)); 0196 Q_EMIT q->dateTimeEntered(m_dateTime); 0197 Q_EMIT q->timeZoneEntered(m_dateTime.timeZone()); 0198 } 0199 0200 void KDateTimeEditPrivate::warnDateTime() 0201 { 0202 if (!q->isValid() && (m_options & KDateTimeEdit::WarnOnInvalid) == KDateTimeEdit::WarnOnInvalid) { 0203 QString warnMsg; 0204 if (!m_dateTime.isValid()) { 0205 // TODO Add missing string 0206 // warnMsg = tr("The date or time you entered is invalid"); 0207 } else if (m_minDateTime.isValid() && m_dateTime < m_minDateTime) { 0208 if (m_minWarnMsg.isEmpty()) { 0209 // TODO Add datetime to string 0210 // warnMsg = q->tr("Date and time cannot be earlier than %1", "@info").arg(formatDate(m_minDate)); 0211 warnMsg = KDateTimeEdit::tr("The entered date and time is before the minimum allowed date and time.", "@info"); 0212 } else { 0213 warnMsg = m_minWarnMsg; 0214 // TODO localize properly 0215 warnMsg.replace(QLatin1String("%1"), q->locale().toString(m_minDateTime)); 0216 } 0217 } else if (m_maxDateTime.isValid() && m_dateTime > m_maxDateTime) { 0218 if (m_maxWarnMsg.isEmpty()) { 0219 // TODO Add datetime to string 0220 // warnMsg = q->tr("Date cannot be later than %1", "@info").arg(formatDate(m_maxDate)); 0221 warnMsg = KDateTimeEdit::tr("The entered date and time is after the maximum allowed date and time.", "@info"); 0222 } else { 0223 warnMsg = m_maxWarnMsg; 0224 warnMsg.replace(QLatin1String("%1"), q->locale().toString(m_maxDateTime)); 0225 } 0226 } 0227 KMessageBox::error(q, warnMsg); 0228 } 0229 } 0230 0231 KDateTimeEdit::KDateTimeEdit(QWidget *parent) 0232 : QWidget(parent) 0233 , d(new KDateTimeEditPrivate(this)) 0234 { 0235 d->ui.setupUi(this); 0236 // Need to do the min/max defaults here and not in private init as need to wait for ui to init 0237 // the KDateComboBox which holds the calendar object. Revisit this??? 0238 d->m_minDateTime = d->defaultMinDateTime(); 0239 d->m_maxDateTime = d->defaultMaxDateTime(); 0240 d->ui.m_calendarCombo->installEventFilter(this); 0241 d->ui.m_dateCombo->installEventFilter(this); 0242 d->ui.m_timeCombo->installEventFilter(this); 0243 d->ui.m_timeZoneCombo->installEventFilter(this); 0244 d->initWidgets(); 0245 0246 connect(d->ui.m_dateCombo, &KDateComboBox::dateChanged, this, &KDateTimeEdit::setDate); 0247 connect(d->ui.m_timeCombo, &KTimeComboBox::timeChanged, this, &KDateTimeEdit::setTime); 0248 connect(d->ui.m_calendarCombo, qOverload<int>(&QComboBox::activated), this, [this](int index) { 0249 d->selectCalendar(index); 0250 }); 0251 connect(d->ui.m_timeZoneCombo, qOverload<int>(&QComboBox::activated), this, [this](int index) { 0252 d->selectTimeZone(index); 0253 }); 0254 } 0255 0256 KDateTimeEdit::~KDateTimeEdit() = default; 0257 0258 QDateTime KDateTimeEdit::dateTime() const 0259 { 0260 return d->m_dateTime; 0261 } 0262 0263 QDate KDateTimeEdit::date() const 0264 { 0265 return d->m_dateTime.date(); 0266 } 0267 0268 QTime KDateTimeEdit::time() const 0269 { 0270 return d->m_dateTime.time(); 0271 } 0272 0273 QTimeZone KDateTimeEdit::timeZone() const 0274 { 0275 return d->m_dateTime.timeZone(); 0276 } 0277 0278 bool KDateTimeEdit::isValid() const 0279 { 0280 return d->m_dateTime.isValid() // 0281 && (!d->m_minDateTime.isValid() || d->m_dateTime >= d->m_minDateTime) // 0282 && (!d->m_maxDateTime.isValid() || d->m_dateTime <= d->m_maxDateTime); 0283 } 0284 0285 bool KDateTimeEdit::isNull() const 0286 { 0287 return isNullDate() && isNullTime(); 0288 } 0289 0290 bool KDateTimeEdit::isValidDate() const 0291 { 0292 return d->ui.m_dateCombo->isValid(); 0293 } 0294 0295 bool KDateTimeEdit::isNullDate() const 0296 { 0297 return d->ui.m_dateCombo->isNull(); 0298 } 0299 0300 bool KDateTimeEdit::isValidTime() const 0301 { 0302 return d->ui.m_timeCombo->isValid(); 0303 } 0304 0305 bool KDateTimeEdit::isNullTime() const 0306 { 0307 return d->ui.m_timeCombo->isNull(); 0308 } 0309 0310 void KDateTimeEdit::setOptions(Options options) 0311 { 0312 if (options != d->m_options) { 0313 d->m_options = options; 0314 d->initWidgets(); 0315 } 0316 } 0317 0318 KDateTimeEdit::Options KDateTimeEdit::options() const 0319 { 0320 return d->m_options; 0321 } 0322 0323 void KDateTimeEdit::setDateTime(const QDateTime &dateTime) 0324 { 0325 if (dateTime != d->m_dateTime) { 0326 assignDateTime(dateTime); 0327 Q_EMIT dateTimeChanged(d->m_dateTime); 0328 Q_EMIT dateChanged(d->m_dateTime.date()); 0329 Q_EMIT timeChanged(d->m_dateTime.time()); 0330 } 0331 } 0332 0333 void KDateTimeEdit::assignDateTime(const QDateTime &dateTime) 0334 { 0335 d->m_dateTime = dateTime; 0336 d->ui.m_dateCombo->setDate(dateTime.date()); 0337 d->ui.m_timeCombo->setTime(dateTime.time()); 0338 } 0339 0340 void KDateTimeEdit::setDate(const QDate &date) 0341 { 0342 if (date != d->m_dateTime.date()) { 0343 assignDate(date); 0344 Q_EMIT dateTimeChanged(d->m_dateTime); 0345 Q_EMIT dateChanged(d->m_dateTime.date()); 0346 } 0347 } 0348 0349 void KDateTimeEdit::assignDate(const QDate &date) 0350 { 0351 d->m_dateTime.setDate(date); 0352 d->ui.m_dateCombo->setDate(date); 0353 } 0354 0355 void KDateTimeEdit::setTime(const QTime &time) 0356 { 0357 if (time != d->m_dateTime.time()) { 0358 assignTime(time); 0359 Q_EMIT dateTimeChanged(d->m_dateTime); 0360 Q_EMIT timeChanged(d->m_dateTime.time()); 0361 } 0362 } 0363 0364 void KDateTimeEdit::assignTime(const QTime &time) 0365 { 0366 d->m_dateTime.setTime(time); 0367 d->ui.m_timeCombo->setTime(time); 0368 } 0369 0370 void KDateTimeEdit::setTimeZone(const QTimeZone &zone) 0371 { 0372 if (zone == d->m_dateTime.timeZone() || !zone.isValid()) { 0373 return; 0374 } 0375 0376 assignTimeZone(zone); 0377 Q_EMIT dateTimeChanged(d->m_dateTime); 0378 Q_EMIT timeZoneChanged(d->m_dateTime.timeZone()); 0379 } 0380 0381 void KDateTimeEdit::assignTimeZone(const QTimeZone &zone) 0382 { 0383 d->m_dateTime.setTimeZone(zone); 0384 d->updateTimeZoneWidget(); 0385 } 0386 0387 void KDateTimeEdit::setMinimumDateTime(const QDateTime &minDateTime, const QString &minWarnMsg) 0388 { 0389 setDateTimeRange(minDateTime, maximumDateTime(), minWarnMsg, d->m_maxWarnMsg); 0390 } 0391 0392 QDateTime KDateTimeEdit::minimumDateTime() const 0393 { 0394 return d->m_minDateTime; 0395 } 0396 0397 void KDateTimeEdit::resetMinimumDateTime() 0398 { 0399 d->m_minDateTime = d->defaultMinDateTime(); 0400 } 0401 0402 void KDateTimeEdit::setMaximumDateTime(const QDateTime &maxDateTime, const QString &maxWarnMsg) 0403 { 0404 setDateTimeRange(minimumDateTime(), maxDateTime, d->m_minWarnMsg, maxWarnMsg); 0405 } 0406 0407 QDateTime KDateTimeEdit::maximumDateTime() const 0408 { 0409 return d->m_maxDateTime; 0410 } 0411 0412 void KDateTimeEdit::resetMaximumDateTime() 0413 { 0414 d->m_maxDateTime = d->defaultMaxDateTime(); 0415 } 0416 0417 void KDateTimeEdit::setDateTimeRange(const QDateTime &minDateTime, const QDateTime &maxDateTime, const QString &minErrorMsg, const QString &maxErrorMsg) 0418 { 0419 if (minDateTime.isValid() && maxDateTime.isValid() && minDateTime <= maxDateTime) { 0420 d->m_minDateTime = minDateTime; 0421 d->m_minWarnMsg = minErrorMsg; 0422 d->m_maxDateTime = maxDateTime; 0423 d->m_maxWarnMsg = maxErrorMsg; 0424 } 0425 } 0426 0427 void KDateTimeEdit::resetDateTimeRange() 0428 { 0429 setDateTimeRange(d->defaultMinDateTime(), d->defaultMaxDateTime()); 0430 } 0431 0432 void KDateTimeEdit::setCalendarLocalesList(const QList<QLocale> &calendarLocales) 0433 { 0434 if (calendarLocales != d->m_calendarLocales) { 0435 d->m_calendarLocales = calendarLocales; 0436 d->updateCalendarWidget(); 0437 } 0438 } 0439 0440 QList<QLocale> KDateTimeEdit::calendarLocalesList() const 0441 { 0442 return d->m_calendarLocales; 0443 } 0444 0445 void KDateTimeEdit::setDateDisplayFormat(QLocale::FormatType format) 0446 { 0447 d->ui.m_dateCombo->setDisplayFormat(format); 0448 } 0449 0450 QLocale::FormatType KDateTimeEdit::dateDisplayFormat() const 0451 { 0452 return d->ui.m_dateCombo->displayFormat(); 0453 } 0454 0455 void KDateTimeEdit::setDateMap(QMap<QDate, QString> dateMap) 0456 { 0457 d->ui.m_dateCombo->setDateMap(dateMap); 0458 } 0459 0460 QMap<QDate, QString> KDateTimeEdit::dateMap() const 0461 { 0462 return d->ui.m_dateCombo->dateMap(); 0463 } 0464 0465 void KDateTimeEdit::setTimeDisplayFormat(QLocale::FormatType formatOptions) 0466 { 0467 d->ui.m_timeCombo->setDisplayFormat(formatOptions); 0468 } 0469 0470 QLocale::FormatType KDateTimeEdit::timeDisplayFormat() const 0471 { 0472 return d->ui.m_timeCombo->displayFormat(); 0473 } 0474 0475 void KDateTimeEdit::setTimeListInterval(int minutes) 0476 { 0477 d->ui.m_timeCombo->setTimeListInterval(minutes); 0478 } 0479 0480 int KDateTimeEdit::timeListInterval() const 0481 { 0482 return d->ui.m_timeCombo->timeListInterval(); 0483 } 0484 0485 void KDateTimeEdit::setTimeList(QList<QTime> timeList, const QString &minWarnMsg, const QString &maxWarnMsg) 0486 { 0487 d->ui.m_timeCombo->setTimeList(timeList, minWarnMsg, maxWarnMsg); 0488 } 0489 0490 QList<QTime> KDateTimeEdit::timeList() const 0491 { 0492 return d->ui.m_timeCombo->timeList(); 0493 } 0494 0495 void KDateTimeEdit::setTimeZones(const QList<QTimeZone> &zones) 0496 { 0497 if (zones != d->m_zones) { 0498 d->m_zones = zones; 0499 d->updateTimeZoneWidget(); 0500 } 0501 } 0502 0503 QList<QTimeZone> KDateTimeEdit::timeZones() const 0504 { 0505 return d->m_zones; 0506 } 0507 0508 bool KDateTimeEdit::eventFilter(QObject *object, QEvent *event) 0509 { 0510 return QWidget::eventFilter(object, event); 0511 } 0512 0513 void KDateTimeEdit::focusInEvent(QFocusEvent *event) 0514 { 0515 QWidget::focusInEvent(event); 0516 } 0517 0518 void KDateTimeEdit::focusOutEvent(QFocusEvent *event) 0519 { 0520 d->warnDateTime(); 0521 QWidget::focusOutEvent(event); 0522 } 0523 0524 void KDateTimeEdit::resizeEvent(QResizeEvent *event) 0525 { 0526 QWidget::resizeEvent(event); 0527 } 0528 0529 #include "moc_kdatetimeedit.cpp"