KWidgetsAddons

kdatetimeedit.cpp
1/*
2 SPDX-FileCopyrightText: 2011 John Layt <john@layt.net>
3
4 SPDX-License-Identifier: LGPL-2.0-or-later
5*/
6
7#include "kdatetimeedit.h"
8
9#include "kdatecombobox.h"
10#include "kdatepicker.h"
11#include "kmessagebox.h"
12
13#include "ui_kdatetimeedit.h"
14
15class KDateTimeEditPrivate
16{
17public:
18 KDateTimeEditPrivate(KDateTimeEdit *qq);
19 virtual ~KDateTimeEditPrivate();
20
21 QDateTime defaultMinDateTime();
22 QDateTime defaultMaxDateTime();
23
24 void initWidgets();
25 void initDateWidget();
26 void initTimeWidget();
27 void initCalendarWidget();
28 void updateCalendarWidget();
29 void initTimeZoneWidget();
30 void updateTimeZoneWidget();
31
32 void warnDateTime();
33
34 // private Q_SLOTS:
35 void selectCalendar(int index);
36 void enterCalendar(const QLocale &calendarLocale);
37 void selectTimeZone(int index);
38 void enterTimeZone(const QByteArray &zoneId);
39
40 KDateTimeEdit *const q;
41
42 KDateTimeEdit::Options m_options;
43 QDateTime m_dateTime;
44 QDateTime m_minDateTime;
45 QDateTime m_maxDateTime;
46 QString m_minWarnMsg;
47 QString m_maxWarnMsg;
48
49 QList<QLocale> m_calendarLocales;
50 QList<QTimeZone> m_zones;
51
52 Ui::KDateTimeEdit ui;
53};
54
55KDateTimeEditPrivate::KDateTimeEditPrivate(KDateTimeEdit *qq)
56 : q(qq)
57{
60 m_dateTime = QDateTime::currentDateTime();
61 m_dateTime.setTime(QTime(0, 0, 0));
62 m_calendarLocales << q->locale();
63 const auto zoneIds = QTimeZone::availableTimeZoneIds();
64 m_zones.reserve(zoneIds.size());
65 for (const QByteArray &zoneId : zoneIds) {
66 m_zones << QTimeZone(zoneId);
67 }
68}
69
70KDateTimeEditPrivate::~KDateTimeEditPrivate()
71{
72}
73
74QDateTime KDateTimeEditPrivate::defaultMinDateTime()
75{
76 // TODO: Find a way to get it from QLocale
77 // return KDateTime(calendar()->earliestValidDate(), QTime(0, 0, 0, 0));
78 return QDateTime();
79}
80
81QDateTime KDateTimeEditPrivate::defaultMaxDateTime()
82{
83 // TODO: Find a way to get it from QLocale
84 // return KDateTime(calendar()->latestValidDate(), QTime(23, 59, 59, 999));
85 return QDateTime();
86}
87
88void KDateTimeEditPrivate::initWidgets()
89{
90 initDateWidget();
91 initTimeWidget();
92 initCalendarWidget();
93 initTimeZoneWidget();
94}
95
96void KDateTimeEditPrivate::initDateWidget()
97{
98 ui.m_dateCombo->blockSignals(true);
99 ui.m_dateCombo->setVisible((m_options & KDateTimeEdit::ShowDate) == KDateTimeEdit::ShowDate);
102 options = options | KDateComboBox::EditDate;
103 }
105 options = options | KDateComboBox::SelectDate;
106 }
108 options = options | KDateComboBox::DatePicker;
109 }
111 options = options | KDateComboBox::DateKeywords;
112 }
113 ui.m_dateCombo->setOptions(options);
114 ui.m_dateCombo->blockSignals(false);
115}
116
117void KDateTimeEditPrivate::initTimeWidget()
118{
119 ui.m_timeCombo->blockSignals(true);
120 ui.m_timeCombo->setVisible((m_options & KDateTimeEdit::ShowTime) == KDateTimeEdit::ShowTime);
123 options = options | KTimeComboBox::EditTime;
124 }
126 options = options | KTimeComboBox::SelectTime;
127 }
129 options = options | KTimeComboBox::ForceTime;
130 }
131 ui.m_timeCombo->setOptions(options);
132 ui.m_timeCombo->blockSignals(false);
133}
134
135void KDateTimeEditPrivate::initCalendarWidget()
136{
137 ui.m_calendarCombo->blockSignals(true);
138 ui.m_calendarCombo->clear();
139 for (const QLocale &calendarLocale : std::as_const(m_calendarLocales)) {
140 ui.m_calendarCombo->addItem(calendarLocale.name(), calendarLocale);
141 }
142 ui.m_calendarCombo->setCurrentIndex(ui.m_calendarCombo->findData(q->locale()));
143 ui.m_calendarCombo->setVisible((m_options & KDateTimeEdit::ShowCalendar) == KDateTimeEdit::ShowCalendar);
144 ui.m_calendarCombo->setEnabled((m_options & KDateTimeEdit::SelectCalendar) == KDateTimeEdit::SelectCalendar);
145 ui.m_calendarCombo->setEditable(false);
146 ui.m_calendarCombo->blockSignals(false);
147}
148
149void KDateTimeEditPrivate::updateCalendarWidget()
150{
151 ui.m_calendarCombo->blockSignals(true);
152 ui.m_calendarCombo->setCurrentIndex(ui.m_calendarCombo->findData(q->locale()));
153 ui.m_calendarCombo->blockSignals(false);
154}
155
156void KDateTimeEditPrivate::selectCalendar(int index)
157{
158 enterCalendar(ui.m_calendarCombo->itemData(index).toLocale());
159}
160
161void KDateTimeEditPrivate::enterCalendar(const QLocale &calendarLocale)
162{
163 q->setLocale(calendarLocale);
164 Q_EMIT q->calendarEntered(q->locale());
165}
166
167void KDateTimeEditPrivate::initTimeZoneWidget()
168{
169 ui.m_timeZoneCombo->blockSignals(true);
170 ui.m_timeZoneCombo->clear();
171 ui.m_timeZoneCombo->addItem(KDateTimeEdit::tr("UTC", "@item:inlistbox UTC time zone"), QByteArray("UTC"));
172 ui.m_timeZoneCombo->addItem(KDateTimeEdit::tr("Floating", "@item:inlistbox No specific time zone"), QByteArray());
173 for (const QTimeZone &zone : std::as_const(m_zones)) {
174 ui.m_timeZoneCombo->addItem(QString::fromUtf8(zone.id()), zone.id());
175 }
176 ui.m_timeZoneCombo->setVisible((m_options & KDateTimeEdit::ShowTimeZone) == KDateTimeEdit::ShowTimeZone);
177 ui.m_timeZoneCombo->setEnabled((m_options & KDateTimeEdit::SelectTimeZone) == KDateTimeEdit::SelectTimeZone);
178 ui.m_timeZoneCombo->setEditable(false);
179 ui.m_timeZoneCombo->blockSignals(false);
180}
181
182void KDateTimeEditPrivate::updateTimeZoneWidget()
183{
184 ui.m_timeZoneCombo->blockSignals(true);
185 ui.m_timeZoneCombo->blockSignals(false);
186}
187
188void KDateTimeEditPrivate::selectTimeZone(int index)
189{
190 enterTimeZone(ui.m_timeCombo->itemData(index).toByteArray());
191}
192
193void KDateTimeEditPrivate::enterTimeZone(const QByteArray &zoneId)
194{
195 q->setTimeZone(QTimeZone(zoneId));
196 Q_EMIT q->dateTimeEntered(m_dateTime);
197 Q_EMIT q->timeZoneEntered(m_dateTime.timeZone());
198}
199
200void KDateTimeEditPrivate::warnDateTime()
201{
203 QString warnMsg;
204 if (!m_dateTime.isValid()) {
205 // TODO Add missing string
206 // warnMsg = tr("The date or time you entered is invalid");
207 } else if (m_minDateTime.isValid() && m_dateTime < m_minDateTime) {
208 if (m_minWarnMsg.isEmpty()) {
209 // TODO Add datetime to string
210 // warnMsg = q->tr("Date and time cannot be earlier than %1", "@info").arg(formatDate(m_minDate));
211 warnMsg = KDateTimeEdit::tr("The entered date and time is before the minimum allowed date and time.", "@info");
212 } else {
213 warnMsg = m_minWarnMsg;
214 // TODO localize properly
215 warnMsg.replace(QLatin1String("%1"), q->locale().toString(m_minDateTime));
216 }
217 } else if (m_maxDateTime.isValid() && m_dateTime > m_maxDateTime) {
218 if (m_maxWarnMsg.isEmpty()) {
219 // TODO Add datetime to string
220 // warnMsg = q->tr("Date cannot be later than %1", "@info").arg(formatDate(m_maxDate));
221 warnMsg = KDateTimeEdit::tr("The entered date and time is after the maximum allowed date and time.", "@info");
222 } else {
223 warnMsg = m_maxWarnMsg;
224 warnMsg.replace(QLatin1String("%1"), q->locale().toString(m_maxDateTime));
225 }
226 }
227 KMessageBox::error(q, warnMsg);
228 }
229}
230
232 : QWidget(parent)
233 , d(new KDateTimeEditPrivate(this))
234{
235 d->ui.setupUi(this);
236 // Need to do the min/max defaults here and not in private init as need to wait for ui to init
237 // the KDateComboBox which holds the calendar object. Revisit this???
238 d->m_minDateTime = d->defaultMinDateTime();
239 d->m_maxDateTime = d->defaultMaxDateTime();
240 d->ui.m_calendarCombo->installEventFilter(this);
241 d->ui.m_dateCombo->installEventFilter(this);
242 d->ui.m_timeCombo->installEventFilter(this);
243 d->ui.m_timeZoneCombo->installEventFilter(this);
244 d->initWidgets();
245
246 connect(d->ui.m_dateCombo, &KDateComboBox::dateChanged, this, &KDateTimeEdit::setDate);
247 connect(d->ui.m_timeCombo, &KTimeComboBox::timeChanged, this, &KDateTimeEdit::setTime);
248 connect(d->ui.m_calendarCombo, &QComboBox::activated, this, [this](int index) {
249 d->selectCalendar(index);
250 });
251 connect(d->ui.m_timeZoneCombo, &QComboBox::activated, this, [this](int index) {
252 d->selectTimeZone(index);
253 });
254}
255
257
259{
260 return d->m_dateTime;
261}
262
263QDate KDateTimeEdit::date() const
264{
265 return d->m_dateTime.date();
266}
267
268QTime KDateTimeEdit::time() const
269{
270 return d->m_dateTime.time();
271}
272
274{
275 return d->m_dateTime.timeZone();
276}
277
279{
280 return d->m_dateTime.isValid() //
281 && (!d->m_minDateTime.isValid() || d->m_dateTime >= d->m_minDateTime) //
282 && (!d->m_maxDateTime.isValid() || d->m_dateTime <= d->m_maxDateTime);
283}
284
286{
287 return isNullDate() && isNullTime();
288}
289
291{
292 return d->ui.m_dateCombo->isValid();
293}
294
296{
297 return d->ui.m_dateCombo->isNull();
298}
299
301{
302 return d->ui.m_timeCombo->isValid();
303}
304
306{
307 return d->ui.m_timeCombo->isNull();
308}
309
311{
312 if (options != d->m_options) {
313 d->m_options = options;
314 d->initWidgets();
315 }
316}
317
318KDateTimeEdit::Options KDateTimeEdit::options() const
319{
320 return d->m_options;
321}
322
324{
325 if (dateTime != d->m_dateTime) {
327 Q_EMIT dateTimeChanged(d->m_dateTime);
328 Q_EMIT dateChanged(d->m_dateTime.date());
329 Q_EMIT timeChanged(d->m_dateTime.time());
330 }
331}
332
334{
335 d->m_dateTime = dateTime;
336 d->ui.m_dateCombo->setDate(dateTime.date());
337 d->ui.m_timeCombo->setTime(dateTime.time());
338}
339
341{
342 if (date != d->m_dateTime.date()) {
343 assignDate(date);
344 Q_EMIT dateTimeChanged(d->m_dateTime);
345 Q_EMIT dateChanged(d->m_dateTime.date());
346 }
347}
348
350{
351 d->m_dateTime.setDate(date);
352 d->ui.m_dateCombo->setDate(date);
353}
354
356{
357 if (time != d->m_dateTime.time()) {
358 assignTime(time);
359 Q_EMIT dateTimeChanged(d->m_dateTime);
360 Q_EMIT timeChanged(d->m_dateTime.time());
361 }
362}
363
365{
366 d->m_dateTime.setTime(time);
367 d->ui.m_timeCombo->setTime(time);
368}
369
371{
372 if (zone == d->m_dateTime.timeZone() || !zone.isValid()) {
373 return;
374 }
375
377 Q_EMIT dateTimeChanged(d->m_dateTime);
378 Q_EMIT timeZoneChanged(d->m_dateTime.timeZone());
379}
380
382{
383 d->m_dateTime.setTimeZone(zone);
384 d->updateTimeZoneWidget();
385}
386
387void KDateTimeEdit::setMinimumDateTime(const QDateTime &minDateTime, const QString &minWarnMsg)
388{
390}
391
393{
394 return d->m_minDateTime;
395}
396
398{
399 d->m_minDateTime = d->defaultMinDateTime();
400}
401
402void KDateTimeEdit::setMaximumDateTime(const QDateTime &maxDateTime, const QString &maxWarnMsg)
403{
405}
406
408{
409 return d->m_maxDateTime;
410}
411
413{
414 d->m_maxDateTime = d->defaultMaxDateTime();
415}
416
417void KDateTimeEdit::setDateTimeRange(const QDateTime &minDateTime, const QDateTime &maxDateTime, const QString &minErrorMsg, const QString &maxErrorMsg)
418{
419 if (minDateTime.isValid() && maxDateTime.isValid() && minDateTime <= maxDateTime) {
420 d->m_minDateTime = minDateTime;
421 d->m_minWarnMsg = minErrorMsg;
422 d->m_maxDateTime = maxDateTime;
423 d->m_maxWarnMsg = maxErrorMsg;
424 }
425}
426
428{
429 setDateTimeRange(d->defaultMinDateTime(), d->defaultMaxDateTime());
430}
431
433{
434 if (calendarLocales != d->m_calendarLocales) {
435 d->m_calendarLocales = calendarLocales;
436 d->updateCalendarWidget();
437 }
438}
439
441{
442 return d->m_calendarLocales;
443}
444
446{
447 d->ui.m_dateCombo->setDisplayFormat(format);
448}
449
451{
452 return d->ui.m_dateCombo->displayFormat();
453}
454
456{
457 d->ui.m_dateCombo->setDateMap(dateMap);
458}
459
461{
462 return d->ui.m_dateCombo->dateMap();
463}
464
466{
467 d->ui.m_timeCombo->setDisplayFormat(formatOptions);
468}
469
471{
472 return d->ui.m_timeCombo->displayFormat();
473}
474
476{
477 d->ui.m_timeCombo->setTimeListInterval(minutes);
478}
479
480int KDateTimeEdit::timeListInterval() const
481{
482 return d->ui.m_timeCombo->timeListInterval();
483}
484
485void KDateTimeEdit::setTimeList(QList<QTime> timeList, const QString &minWarnMsg, const QString &maxWarnMsg)
486{
487 d->ui.m_timeCombo->setTimeList(timeList, minWarnMsg, maxWarnMsg);
488}
489
491{
492 return d->ui.m_timeCombo->timeList();
493}
494
496{
497 if (zones != d->m_zones) {
498 d->m_zones = zones;
499 d->updateTimeZoneWidget();
500 }
501}
502
504{
505 return d->m_zones;
506}
507
508bool KDateTimeEdit::eventFilter(QObject *object, QEvent *event)
509{
510 return QWidget::eventFilter(object, event);
511}
512
513void KDateTimeEdit::focusInEvent(QFocusEvent *event)
514{
516}
517
518void KDateTimeEdit::focusOutEvent(QFocusEvent *event)
519{
520 d->warnDateTime();
522}
523
524void KDateTimeEdit::resizeEvent(QResizeEvent *event)
525{
527}
528
529#include "moc_kdatetimeedit.cpp"
@ SelectDate
Allow the user to select the date from a drop-down menu.
@ DateKeywords
Show date keywords in the drop-down.
@ EditDate
Allow the user to manually edit the date in the combo line edit.
@ DatePicker
Show a date picker in the drop-down.
void dateChanged(const QDate &date)
Signal if the date has been changed either manually by the user or programmatically.
A widget for editing date and time.
void resetMinimumDateTime()
Reset the minimum date and time to the default.
virtual void assignDateTime(const QDateTime &dateTime)
Assign the date, time and time zone for the widget.
void setTimeZones(const QList< QTimeZone > &zones)
Set the time zones able to be selected.
void setDateMap(QMap< QDate, QString > dateMap)
Set the list of dates able to be selected from the drop-down and the string form to display for those...
void setDate(const QDate &date)
Set the currently selected date.
void assignTimeZone(const QTimeZone &zone)
Assign the time zone for the widget.
bool isNullTime() const
Return if the current user input time is null.
void resetDateTimeRange()
Reset the minimum and maximum date and time to the default.
@ ForceTime
The entered time can only be a selected time.
@ WarnOnInvalid
Show a warning on focus out if the date or time is invalid.
@ ShowCalendar
If the Calendar System edit is displayed.
@ SelectTimeZone
Allow the user to select a time zone.
@ EditTime
Allow the user to manually edit the time.
@ DatePicker
Show a date picker.
@ ShowTime
If the Time is displayed.
@ ShowDate
If the Date is displayed.
@ ShowTimeZone
If the Time Zone is displayed.
@ DateKeywords
Show date keywords.
@ EditDate
Allow the user to manually edit the date.
@ SelectDate
Allow the user to select a date.
@ SelectTime
Allow the user to select a time.
@ SelectCalendar
Allow the user to select a calendar.
bool isValid() const
Return if the current user input is valid.
void dateChanged(const QDate &date)
Signal if the date has been changed either manually by the user or programmatically.
void setMinimumDateTime(const QDateTime &minDateTime, const QString &minWarnMsg=QString())
Set the minimum allowed date.
void setTime(const QTime &time)
Set the currently selected time.
QTimeZone timeZone() const
Return the currently selected time zone.
void timeZoneEntered(const QTimeZone &zone)
Signal if the time zone has been changed manually by the user.
void setMaximumDateTime(const QDateTime &maxDateTime, const QString &maxWarnMsg=QString())
Set the maximum allowed date.
QDateTime dateTime() const
Return the currently selected date, time and time zone.
virtual void assignTime(const QTime &time)
Assign the time for the widget.
~KDateTimeEdit() override
Destroy the widget.
QList< QLocale > calendarLocalesList() const
Returns the list of Calendar Locales displayed.
QList< QTime > timeList() const
Return the list of times able to be selected in the drop-down.
bool isNull() const
Return if the current user input is null.
QLocale::FormatType timeDisplayFormat() const
Return the currently set time format.
void resetMaximumDateTime()
Reset the minimum date and time to the default.
KDateTimeEdit(QWidget *parent=nullptr)
Create a new KDateTimeEdit widget.
void setTimeList(QList< QTime > timeList, const QString &minWarnMsg=QString(), const QString &maxWarnMsg=QString())
Set the list of times able to be selected from the drop-down.
void timeChanged(const QTime &time)
Signal if the time has been changed either manually by the user or programmatically.
QLocale::FormatType dateDisplayFormat() const
Return the currently set date display format.
QDateTime minimumDateTime() const
Return the current minimum date and time.
void setTimeZone(const QTimeZone &zone)
Set the current time zone.
virtual void assignDate(const QDate &date)
Assign the date for the widget.
void setDateDisplayFormat(QLocale::FormatType format)
Sets the date format to display.
void setCalendarLocalesList(const QList< QLocale > &calendarLocales)
Set the list of Calendar Locales to display.
QDateTime maximumDateTime() const
Return the current maximum date and time.
void dateTimeEntered(const QDateTime &dateTime)
Signal if the date or time has been manually entered by the user.
void setOptions(Options options)
Set the new widget options.
QMap< QDate, QString > dateMap() const
Return the map of dates listed in the drop-down and their displayed string forms.
void setDateTimeRange(const QDateTime &minDateTime, const QDateTime &maxDateTime, const QString &minWarnMsg=QString(), const QString &maxWarnMsg=QString())
Set the minimum and maximum date and time range.
void setTimeListInterval(int minutes)
Set the interval between times able to be selected from the drop-down.
void setDateTime(const QDateTime &dateTime)
Set the currently selected date, time and time zone.
bool isValidDate() const
Return if the current user input date is valid.
void calendarEntered(const QLocale &calendarLocale)
Signal if the Calendar Locale has been manually entered by the user.
void dateTimeChanged(const QDateTime &dateTime)
Signal if the date or time has been changed either manually by the user or programmatically.
bool isNullDate() const
Return if the current user input date is null.
void timeZoneChanged(const QTimeZone &zone)
Signal if the time zone has been changed either manually by the user or programmatically.
QList< QTimeZone > timeZones() const
Return the list of time zones able to be selected.
void setTimeDisplayFormat(QLocale::FormatType format)
Sets the time format to display.
bool isValidTime() const
Return if the current user input time is valid.
@ ForceTime
Any set or entered time will be forced to one of the drop-down times.
@ SelectTime
Allow the user to select the time from a drop-down menu.
@ EditTime
Allow the user to manually edit the time in the combo line edit.
void timeChanged(const QTime &time)
Signal if the time has been changed either manually by the user or programmatically.
void error(QWidget *parent, const QString &text, const QString &title, Options options)
Display an "Error" dialog.
void activated(int index)
QDateTime currentDateTime()
QDate date() const const
bool isValid() const const
QTime time() const const
QTimeZone timeZone() const const
Q_EMITQ_EMIT
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
virtual bool eventFilter(QObject *watched, QEvent *event)
T qobject_cast(QObject *object)
QString tr(const char *sourceText, const char *disambiguation, int n)
QString fromUtf8(QByteArrayView str)
bool isEmpty() const const
QString & replace(QChar before, QChar after, Qt::CaseSensitivity cs)
QList< QByteArray > availableTimeZoneIds()
virtual bool event(QEvent *event) override
virtual void focusInEvent(QFocusEvent *event)
virtual void focusOutEvent(QFocusEvent *event)
virtual void resizeEvent(QResizeEvent *event)
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Tue Mar 26 2024 11:14:43 by doxygen 1.10.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.