7#include "ktimecombobox.h"
13#include "kmessagebox.h"
15class KTimeComboBoxPrivate
18 KTimeComboBoxPrivate(KTimeComboBox *qq);
19 virtual ~KTimeComboBoxPrivate();
21 QTime defaultMinTime();
22 QTime defaultMaxTime();
24 std::pair<QString, QString> timeFormatToInputMask(
const QString &format);
25 QTime nearestIntervalTime(
const QTime &time);
26 QString formatTime(
const QTime &time);
28 void initTimeWidget();
29 void updateTimeWidget();
32 void selectTime(
int index);
33 void editTime(
const QString &text);
34 void enterTime(
const QTime &time);
38 KTimeComboBox *
const q;
49 int m_timeListInterval;
50 QList<QTime> m_timeList;
55 , m_time(
QTime(0, 0, 0))
56 , m_warningShown(false)
57 , m_displayFormat(
QLocale::ShortFormat)
58 , m_timeListInterval(15)
61 m_minTime = defaultMinTime();
62 m_maxTime = defaultMaxTime();
65KTimeComboBoxPrivate::~KTimeComboBoxPrivate()
69QTime KTimeComboBoxPrivate::defaultMinTime()
71 return QTime(0, 0, 0, 0);
74QTime KTimeComboBoxPrivate::defaultMaxTime()
76 return QTime(23, 59, 59, 999);
79std::pair<QString, QString> KTimeComboBoxPrivate::timeFormatToInputMask(
const QString &format)
81 const QLocale locale = q->locale();
83 QString example = formatTime(QTime(12, 34, 56, 789));
96 QString am = locale.
amText();
97 QString pm = locale.
pmText();
100 const QString ampmMask(ampmLen, QLatin1Char(
'x'));
107 for (
const QChar c : example) {
108 if (c == QLatin1Char(
'0') || c == QLatin1Char(
'9') || c == QLatin1Char(
'x')) {
111 mask.
append(QLatin1Char(
'\\'));
117 return std::make_pair(mask, null);
120QTime KTimeComboBoxPrivate::nearestIntervalTime(
const QTime &time)
123 while (q->itemData(i).toTime() < time) {
126 QTime before = q->itemData(i).toTime();
127 QTime after = q->itemData(i + 1).toTime();
135QString KTimeComboBoxPrivate::formatTime(
const QTime &time)
137 return q->locale().toString(time, m_displayFormat);
140void KTimeComboBoxPrivate::initTimeWidget()
142 q->blockSignals(
true);
147 std::tie(mask, m_nullString) = timeFormatToInputMask(q->locale().timeFormat(m_displayFormat));
148 q->lineEdit()->setInputMask(mask);
155 q->setMaxVisibleItems(10);
157 q->setMaxVisibleItems(0);
162 if (m_timeList.isEmpty()) {
163 QTime startTime = m_minTime;
164 QTime thisTime(startTime.
hour(), 0, 0, 0);
165 while (thisTime.isValid() && thisTime <= startTime) {
166 thisTime = thisTime.addSecs(m_timeListInterval * 60);
168 QTime endTime = m_maxTime;
169 q->addItem(formatTime(startTime), startTime);
170 while (thisTime.isValid() && thisTime < endTime) {
171 q->addItem(formatTime(thisTime), thisTime);
172 QTime newTime = thisTime.addSecs(m_timeListInterval * 60);
173 if (newTime.
isValid() && newTime > thisTime) {
179 q->addItem(formatTime(endTime), endTime);
181 for (
const QTime &thisTime : std::as_const(m_timeList)) {
182 if (thisTime.isValid() && thisTime >= m_minTime && thisTime <= m_maxTime) {
183 q->addItem(formatTime(thisTime), thisTime);
187 q->blockSignals(
false);
190void KTimeComboBoxPrivate::updateTimeWidget()
192 q->blockSignals(
true);
193 int pos = q->lineEdit()->cursorPosition();
196 if (!m_time.isValid() || m_time < m_minTime) {
198 }
else if (m_time > m_maxTime) {
201 while (q->itemData(i).toTime() < m_time && i < q->count() - 1) {
205 q->setCurrentIndex(i);
206 if (m_time.isValid()) {
207 q->lineEdit()->setText(formatTime(m_time));
209 q->lineEdit()->setText(QString());
211 q->lineEdit()->setCursorPosition(pos);
212 q->blockSignals(
false);
215void KTimeComboBoxPrivate::selectTime(
int index)
217 enterTime(q->itemData(index).toTime());
220void KTimeComboBoxPrivate::editTime(
const QString &text)
222 m_warningShown =
false;
223 Q_EMIT q->timeEdited(q->locale().toTime(text, m_displayFormat));
226void KTimeComboBoxPrivate::parseTime()
228 m_time = q->locale().toTime(q->lineEdit()->text(), m_displayFormat);
231void KTimeComboBoxPrivate::enterTime(
const QTime &time)
235 Q_EMIT q->timeEntered(m_time);
238void KTimeComboBoxPrivate::warnTime()
242 if (!m_time.isValid()) {
244 }
else if (m_time < m_minTime) {
245 if (m_minWarnMsg.isEmpty()) {
246 warnMsg =
KTimeComboBox::tr(
"Time cannot be earlier than %1",
"@info").
arg(formatTime(m_minTime));
248 warnMsg = m_minWarnMsg;
249 warnMsg.
replace(QLatin1String(
"%1"), formatTime(m_minTime));
251 }
else if (m_time > m_maxTime) {
252 if (m_maxWarnMsg.isEmpty()) {
253 warnMsg =
KTimeComboBox::tr(
"Time cannot be later than %1",
"@info").
arg(formatTime(m_maxTime));
255 warnMsg = m_maxWarnMsg;
256 warnMsg.
replace(QLatin1String(
"%1"), formatTime(m_maxTime));
259 m_warningShown =
true;
266 , d(new KTimeComboBoxPrivate(this))
272 d->updateTimeWidget();
275 d->selectTime(value);
292 if (time == d->m_time) {
302 d->updateTimeWidget();
314 return d->m_time.isValid() && d->m_time >= d->m_minTime && d->m_time <= d->m_maxTime;
329 if (options != d->m_options) {
330 d->m_options = options;
332 d->updateTimeWidget();
336QTime KTimeComboBox::minimumTime()
const
343 setTimeRange(minTime, d->m_maxTime, minWarnMsg, d->m_maxWarnMsg);
351QTime KTimeComboBox::maximumTime()
const
358 setTimeRange(d->m_minTime, maxTime, d->m_minWarnMsg, maxWarnMsg);
368 if (!minTime.
isValid() || !maxTime.
isValid() || minTime > maxTime) {
372 if (minTime != d->m_minTime || maxTime != d->m_maxTime
373 || minWarnMsg != d->m_minWarnMsg || maxWarnMsg != d->m_maxWarnMsg) {
374 d->m_minTime = minTime;
375 d->m_maxTime = maxTime;
376 d->m_minWarnMsg = minWarnMsg;
377 d->m_maxWarnMsg = maxWarnMsg;
379 d->updateTimeWidget();
390 return d->m_displayFormat;
395 if (format != d->m_displayFormat) {
396 d->m_displayFormat = format;
398 d->updateTimeWidget();
402int KTimeComboBox::timeListInterval()
const
404 return d->m_timeListInterval;
409 if (minutes != d->m_timeListInterval) {
411 int lowMins = (d->m_minTime.hour() * 60) + d->m_minTime.minute();
412 int hiMins = (d->m_maxTime.hour() * 60) + d->m_maxTime.minute();
413 if (d->m_minTime.minute() == 0 && d->m_maxTime.minute() == 59) {
416 if ((hiMins - lowMins) % minutes == 0) {
417 d->m_timeListInterval = minutes;
418 d->m_timeList.clear();
432 for (
int i = 0; i < c; ++i) {
441 d->m_timeList.clear();
443 if (time.isValid() && !d->m_timeList.contains(time)) {
444 d->m_timeList.append(time);
447 std::sort(d->m_timeList.begin(), d->m_timeList.end());
449 setTimeRange(d->m_timeList.first(), d->m_timeList.last(), minWarnMsg, maxWarnMsg);
453bool KTimeComboBox::eventFilter(
QObject *
object,
QEvent *event)
458void KTimeComboBox::keyPressEvent(
QKeyEvent *keyEvent)
469 temp = d->m_time.
addSecs(-3600);
472 temp = d->m_time.
addSecs(3600);
478 if (temp.
isValid() && temp >= d->m_minTime && temp <= d->m_maxTime) {
483void KTimeComboBox::focusOutEvent(
QFocusEvent *event)
490void KTimeComboBox::showPopup()
495void KTimeComboBox::hidePopup()
500void KTimeComboBox::mousePressEvent(
QMouseEvent *event)
510void KTimeComboBox::focusInEvent(
QFocusEvent *event)
520#include "moc_ktimecombobox.cpp"
KTimeComboBox(QWidget *parent=nullptr)
Create a new KTimeComboBox widget.
~KTimeComboBox() override
Destroy the widget.
void setTimeListInterval(int minutes)
Set the interval between times able to be selected from the drop-down.
@ 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.
@ WarnOnInvalid
Show a warning box on focus out if the user enters an invalid time.
@ EditTime
Allow the user to manually edit the time in the combo line edit.
QLocale::FormatType displayFormat() const
Return the currently set time format.
void resetMinimumTime()
Reset the minimum time to the default of 00:00:00.000.
void setMaximumTime(const QTime &maxTime, const QString &maxWarnMsg=QString())
Set the maximum allowed time.
void resetMaximumTime()
Reset the maximum time to the default of 23:59:59.999.
virtual void assignTime(const QTime &time)
Assign the time for the widget.
bool isNull() const
Return if the current user input is null.
void resetTimeRange()
Reset the minimum and maximum time to the default values.
void setOptions(Options options)
Set the new widget options.
void setTimeRange(const QTime &minTime, const QTime &maxTime, const QString &minWarnMsg=QString(), const QString &maxWarnMsg=QString())
Set the minimum and maximum time range.
QFlags< Option > Options
Stores a combination of Option values.
void setDisplayFormat(QLocale::FormatType format)
Sets the time format to display.
void setTime(const QTime &time)
Set the currently selected time.
QList< QTime > timeList() const
Return the list of times able to be selected in the drop-down.
bool isValid() const
Return if the current user input is valid.
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 setMinimumTime(const QTime &minTime, const QString &minWarnMsg=QString())
Set the minimum allowed time.
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.
QComboBox(QWidget *parent)
void activated(int index)
void editTextChanged(const QString &text)
void setEditable(bool editable)
virtual bool event(QEvent *event) override
virtual void focusInEvent(QFocusEvent *e) override
virtual void focusOutEvent(QFocusEvent *e) override
void setInsertPolicy(InsertPolicy policy)
QVariant itemData(int index, int role) const const
virtual void keyPressEvent(QKeyEvent *e) override
QLineEdit * lineEdit() const const
virtual void mousePressEvent(QMouseEvent *e) override
virtual void resizeEvent(QResizeEvent *e) override
void setSizeAdjustPolicy(SizeAdjustPolicy policy)
virtual void wheelEvent(QWheelEvent *e) override
void append(QList< T > &&value)
void reserve(qsizetype size)
QString amText() const const
QString pmText() const const
QString toString(QDate date, FormatType format) const const
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
virtual bool event(QEvent *e)
virtual bool eventFilter(QObject *watched, QEvent *event)
QObject * parent() const const
QString tr(const char *sourceText, const char *disambiguation, int n)
QString & append(QChar ch)
QString arg(Args &&... args) const const
qsizetype indexOf(QChar ch, qsizetype from, Qt::CaseSensitivity cs) const const
qsizetype length() const const
QString & replace(QChar before, QChar after, Qt::CaseSensitivity cs)
void keyEvent(KeyAction action, QWidget *widget, Qt::Key key, Qt::KeyboardModifiers modifier, int delay)
QTime addSecs(int s) const const
bool isValid(int h, int m, int s, int ms)
int secsTo(QTime t) const const