22 #include <QtGui/QAbstractItemView>
23 #include <QtGui/QApplication>
24 #include <QtGui/QKeyEvent>
25 #include <QtGui/QMenu>
26 #include <QtGui/QLineEdit>
27 #include <QtGui/QWidgetAction>
28 #include <QtCore/QVector>
37 class KDateComboBoxPrivate
42 virtual ~KDateComboBoxPrivate();
44 QDate defaultMinDate();
45 QDate defaultMaxDate();
47 QString formatDate(
const QDate &date);
49 void initDateWidget();
50 void addMenuAction(
const QString &text,
const QDate &date);
51 void enableMenuDates();
52 void updateDateWidget();
56 void selectDate(
QAction *action);
57 void editDate(
const QString &text);
58 void enterDate(
const QDate &date);
64 QVector<QAction*> m_actions;
69 KDateComboBox::Options m_options;
81 m_dateMenu(new
QMenu(q)),
84 m_warningShown(false),
85 m_displayFormat(
KLocale::ShortDate)
88 m_date.setDate(QDate::currentDate());
89 m_minDate = defaultMinDate();
90 m_maxDate = defaultMaxDate();
91 m_datePicker->setCloseButton(
false);
92 m_datePickerAction->setObjectName(QLatin1String(
"DatePicker"));
93 m_datePickerAction->setDefaultWidget(m_datePicker);
96 KDateComboBoxPrivate::~KDateComboBoxPrivate()
100 QDate KDateComboBoxPrivate::defaultMinDate()
102 return m_date.calendar()->earliestValidDate();
105 QDate KDateComboBoxPrivate::defaultMaxDate()
107 return m_date.calendar()->latestValidDate();
110 QString KDateComboBoxPrivate::formatDate(
const QDate &date)
112 return m_date.calendar()->formatDate(date, m_displayFormat);
115 void KDateComboBoxPrivate::initDateWidget()
117 q->blockSignals(
true);
127 q->setMaxVisibleItems(1);
129 q->setMaxVisibleItems(0);
132 q->setSizeAdjustPolicy(QComboBox::AdjustToContents);
133 q->addItem(m_date.formatDate(m_displayFormat));
134 q->setCurrentIndex(0);
135 q->setSizeAdjustPolicy(QComboBox::AdjustToContentsOnFirstShow);
136 q->blockSignals(
false);
141 if ((m_options & KDateComboBox::SelectDate) == KDateComboBox::SelectDate) {
143 if ((m_options & KDateComboBox::DatePicker) == KDateComboBox::DatePicker) {
144 m_dateMenu->addAction(m_datePickerAction);
145 m_dateMenu->addSeparator();
149 if (m_dateMap.isEmpty()) {
150 addMenuAction(
i18nc(
"@option next year",
"Next Year" ), m_date.addYears(1).date());
151 addMenuAction(
i18nc(
"@option next month",
"Next Month"), m_date.addMonths(1).date());
152 addMenuAction(
i18nc(
"@option next week",
"Next Week" ), m_date.addDays(m_date.daysInWeek()).date());
153 addMenuAction(
i18nc(
"@option tomorrow",
"Tomorrow" ), m_date.addDays(1).date());
154 addMenuAction(
i18nc(
"@option today",
"Today" ), m_date.date());
155 addMenuAction(
i18nc(
"@option yesterday",
"Yesterday" ), m_date.addDays(-1).date());
156 addMenuAction(
i18nc(
"@option last week",
"Last Week" ), m_date.addDays(-m_date.daysInWeek()).date());
157 addMenuAction(
i18nc(
"@option last month",
"Last Month"), m_date.addMonths(-1).date());
158 addMenuAction(
i18nc(
"@option last year",
"Last Year" ), m_date.addYears(-1).date());
159 m_dateMenu->addSeparator();
160 addMenuAction(
i18nc(
"@option do not specify a date",
"No Date"), QDate());
162 QMapIterator<QDate, QString> i(m_dateMap);
163 while (i.hasNext()) {
165 if (i.value().isEmpty()) {
166 addMenuAction(formatDate(i.key()), i.key());
167 }
else if (i.value().toLower() == QLatin1String(
"separator")) {
168 m_dateMenu->addSeparator();
170 addMenuAction(i.value(), i.key());
179 void KDateComboBoxPrivate::addMenuAction(
const QString &text,
const QDate &date)
182 action->setText(text);
183 action->setData(date);
184 m_dateMenu->addAction(action);
188 void KDateComboBoxPrivate::enableMenuDates()
191 for (
int i = 0; i < m_actions.count(); ++i) {
192 QDate date = m_actions[i]->data().toDate();
193 m_actions[i]->setVisible(!date.isValid() || (date >= m_minDate && date <= m_maxDate));
197 void KDateComboBoxPrivate::updateDateWidget()
199 q->blockSignals(
true);
200 m_datePicker->blockSignals(
true);
201 m_datePicker->
setDate(m_date.date());
203 q->setItemText(0, m_date.formatDate(m_displayFormat));
204 q->lineEdit()->setText(m_date.formatDate(m_displayFormat));
205 q->lineEdit()->setCursorPosition(pos);
206 m_datePicker->blockSignals(
false);
207 q->blockSignals(
false);
210 void KDateComboBoxPrivate::selectDate(
QAction *action)
212 if (action->objectName() != QLatin1String(
"DatePicker")) {
213 enterDate(action->data().toDate());
217 void KDateComboBoxPrivate::clickDate()
219 enterDate(m_datePicker->date());
222 void KDateComboBoxPrivate::editDate(
const QString &text)
224 m_warningShown =
false;
225 emit q->
dateEdited(m_date.readDate(text).date());
228 void KDateComboBoxPrivate::parseDate()
230 m_date.setDate(m_date.readDate(q->lineEdit()->text()).date());
233 void KDateComboBoxPrivate::enterDate(
const QDate &date)
237 q->blockSignals(
true);
239 q->setSizeAdjustPolicy(QComboBox::AdjustToContents);
240 q->addItem(m_date.formatDate(m_displayFormat));
241 q->setCurrentIndex(0);
242 q->setSizeAdjustPolicy(QComboBox::AdjustToContentsOnFirstShow);
243 q->blockSignals(
false);
250 void KDateComboBoxPrivate::warnDate()
252 if (!m_warningShown && !q->
isValid() &&
255 if (!m_date.date().isValid()) {
256 warnMsg =
i18nc(
"@info",
"The date you entered is invalid");
257 }
else if (m_date.date() < m_minDate) {
258 if (m_minWarnMsg.isEmpty()) {
259 warnMsg =
i18nc(
"@info",
"Date cannot be earlier than %1", formatDate(m_minDate));
261 warnMsg = m_minWarnMsg;
262 warnMsg.replace(
"%1", formatDate(m_minDate));
264 }
else if (m_date.date() > m_maxDate) {
265 if (m_maxWarnMsg.isEmpty()) {
266 warnMsg =
i18nc(
"@info",
"Date cannot be later than %1", formatDate(m_maxDate));
268 warnMsg = m_maxWarnMsg;
269 warnMsg.replace(
"%1", formatDate(m_maxDate));
272 m_warningShown =
true;
280 d(new KDateComboBoxPrivate(this))
283 setMaxVisibleItems(1);
284 setInsertPolicy(QComboBox::NoInsert);
285 d->m_datePicker->installEventFilter(
this);
287 d->updateDateWidget();
289 connect(d->m_dateMenu, SIGNAL(triggered(
QAction*)),
290 this, SLOT(selectDate(
QAction*)));
291 connect(
this, SIGNAL(editTextChanged(
QString)),
292 this, SLOT(editDate(
QString)));
293 connect(d->m_datePicker, SIGNAL(
dateEntered(QDate)),
294 this, SLOT(enterDate(QDate)));
295 connect(d->m_datePicker, SIGNAL(tableClicked()),
296 this, SLOT(clickDate()));
307 return d->m_date.date();
312 if (date == d->m_date.date()) {
317 d->updateDateWidget();
328 return d->m_date.calendarSystem();
333 if (calendarSystem != d->m_date.calendarSystem()) {
340 d->m_date.setCalendarSystem(calendarSystem);
345 return d->m_date.calendar();
356 return d->m_date.isValid() &&
357 d->m_date >= d->m_minDate &&
358 d->m_date <= d->m_maxDate;
363 return lineEdit()->text().isEmpty();
373 if (options != d->m_options) {
376 d->updateDateWidget();
387 setDateRange(minDate, d->m_maxDate, minWarnMsg, d->m_maxWarnMsg);
402 setDateRange(d->m_minDate, maxDate, d->m_minWarnMsg, maxWarnMsg);
411 const QDate &maxDate,
415 if (!minDate.isValid() || !maxDate.isValid() || minDate > maxDate) {
419 if (minDate != d->m_minDate || maxDate != d->m_maxDate ||
420 minWarnMsg != d->m_minWarnMsg || maxWarnMsg != d->m_maxWarnMsg) {
421 d->m_minDate = minDate;
422 d->m_maxDate = maxDate;
423 d->m_minWarnMsg = minWarnMsg;
424 d->m_maxWarnMsg = maxWarnMsg;
426 d->enableMenuDates();
436 return d->m_displayFormat;
441 if (format != d->m_displayFormat) {
442 d->m_displayFormat = format;
444 d->updateDateWidget();
455 if (dateMap != d->m_dateMap) {
456 d->m_dateMap.clear();
470 switch (keyEvent->key()) {
472 temp = d->m_date.addDays(-1).date();
475 temp = d->m_date.addDays(1).date();
477 case Qt::Key_PageDown:
478 temp = d->m_date.addMonths(-1).date();
481 temp = d->m_date.addMonths(1).date();
484 KComboBox::keyPressEvent(keyEvent);
487 if (temp.isValid() && temp >= d->m_minDate && temp <= d->m_maxDate) {
496 KComboBox::focusOutEvent(event);
503 (d->m_options &KDateComboBox::SelectDate) != KDateComboBox::SelectDate) {
507 d->m_datePicker->blockSignals(
true);
508 d->m_datePicker->setDate(d->m_date.date());
509 d->m_datePicker->blockSignals(
false);
515 const int dateFrameHeight = d->m_dateMenu->sizeHint().height();
516 if (popupPoint.y() + height() + dateFrameHeight > desk.bottom()) {
517 popupPoint.setY(popupPoint.y() - dateFrameHeight);
519 popupPoint.setY(popupPoint.y() + height());
522 const int dateFrameWidth = d->m_dateMenu->sizeHint().width();
523 if (popupPoint.x() + dateFrameWidth > desk.right()) {
524 popupPoint.setX(desk.right() - dateFrameWidth);
527 if (popupPoint.x() < desk.left()) {
528 popupPoint.setX(desk.left());
531 if (popupPoint.y() < desk.top()) {
532 popupPoint.setY(desk.top());
535 d->m_dateMenu->popup(popupPoint);
540 KComboBox::hidePopup();
545 KComboBox::mousePressEvent(event);
555 KComboBox::focusInEvent(event);
560 KComboBox::resizeEvent(event);
563 #include "kdatecombobox.moc"