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_displayFormat(
KLocale::ShortDate)
87 m_date.setDate(QDate::currentDate());
88 m_minDate = defaultMinDate();
89 m_maxDate = defaultMaxDate();
90 m_datePicker->setCloseButton(
false);
91 m_datePickerAction->setObjectName(QLatin1String(
"DatePicker"));
92 m_datePickerAction->setDefaultWidget(m_datePicker);
95 KDateComboBoxPrivate::~KDateComboBoxPrivate()
99 QDate KDateComboBoxPrivate::defaultMinDate()
101 return m_date.calendar()->earliestValidDate();
104 QDate KDateComboBoxPrivate::defaultMaxDate()
106 return m_date.calendar()->latestValidDate();
109 QString KDateComboBoxPrivate::formatDate(
const QDate &date)
111 return m_date.calendar()->formatDate(date, m_displayFormat);
114 void KDateComboBoxPrivate::initDateWidget()
116 q->blockSignals(
true);
126 q->setMaxVisibleItems(1);
128 q->setMaxVisibleItems(0);
131 q->setSizeAdjustPolicy(QComboBox::AdjustToContents);
132 q->addItem(m_date.formatDate(m_displayFormat));
133 q->setCurrentIndex(0);
134 q->setSizeAdjustPolicy(QComboBox::AdjustToContentsOnFirstShow);
135 q->blockSignals(
false);
140 if ((m_options & KDateComboBox::SelectDate) == KDateComboBox::SelectDate) {
142 if ((m_options & KDateComboBox::DatePicker) == KDateComboBox::DatePicker) {
143 m_dateMenu->addAction(m_datePickerAction);
144 m_dateMenu->addSeparator();
148 if (m_dateMap.isEmpty()) {
149 addMenuAction(
i18nc(
"@option next year",
"Next Year" ), m_date.addYears(1).date());
150 addMenuAction(
i18nc(
"@option next month",
"Next Month"), m_date.addMonths(1).date());
151 addMenuAction(
i18nc(
"@option next week",
"Next Week" ), m_date.addDays(m_date.daysInWeek()).date());
152 addMenuAction(
i18nc(
"@option tomorrow",
"Tomorrow" ), m_date.addDays(1).date());
153 addMenuAction(
i18nc(
"@option today",
"Today" ), m_date.date());
154 addMenuAction(
i18nc(
"@option yesterday",
"Yesterday" ), m_date.addDays(-1).date());
155 addMenuAction(
i18nc(
"@option last week",
"Last Week" ), m_date.addDays(-m_date.daysInWeek()).date());
156 addMenuAction(
i18nc(
"@option last month",
"Last Month"), m_date.addMonths(-1).date());
157 addMenuAction(
i18nc(
"@option last year",
"Last Year" ), m_date.addYears(-1).date());
158 m_dateMenu->addSeparator();
159 addMenuAction(
i18nc(
"@option do not specify a date",
"No Date"), QDate());
161 QMapIterator<QDate, QString> i(m_dateMap);
162 while (i.hasNext()) {
164 if (i.value().isEmpty()) {
165 addMenuAction(formatDate(i.key()), i.key());
166 }
else if (i.value().toLower() == QLatin1String(
"separator")) {
167 m_dateMenu->addSeparator();
169 addMenuAction(i.value(), i.key());
178 void KDateComboBoxPrivate::addMenuAction(
const QString &text,
const QDate &date)
181 action->setText(text);
182 action->setData(date);
183 m_dateMenu->addAction(action);
187 void KDateComboBoxPrivate::enableMenuDates()
190 for (
int i = 0; i < m_actions.count(); ++i) {
191 QDate date = m_actions[i]->data().toDate();
192 m_actions[i]->setVisible(!date.isValid() || (date >= m_minDate && date <= m_maxDate));
196 void KDateComboBoxPrivate::updateDateWidget()
198 q->blockSignals(
true);
199 m_datePicker->blockSignals(
true);
200 m_datePicker->
setDate(m_date.date());
202 q->setItemText(0, m_date.formatDate(m_displayFormat));
203 q->lineEdit()->setText(m_date.formatDate(m_displayFormat));
204 q->lineEdit()->setCursorPosition(pos);
205 m_datePicker->blockSignals(
false);
206 q->blockSignals(
false);
209 void KDateComboBoxPrivate::selectDate(
QAction *action)
211 if (action->objectName() != QLatin1String(
"DatePicker")) {
212 enterDate(action->data().toDate());
216 void KDateComboBoxPrivate::clickDate()
218 enterDate(m_datePicker->date());
221 void KDateComboBoxPrivate::editDate(
const QString &text)
223 m_warningShown =
false;
224 emit q->
dateEdited(m_date.readDate(text).date());
227 void KDateComboBoxPrivate::parseDate()
229 m_date.setDate(m_date.readDate(q->lineEdit()->text()).date());
232 void KDateComboBoxPrivate::enterDate(
const QDate &date)
236 q->blockSignals(
true);
238 q->setSizeAdjustPolicy(QComboBox::AdjustToContents);
239 q->addItem(m_date.formatDate(m_displayFormat));
240 q->setCurrentIndex(0);
241 q->setSizeAdjustPolicy(QComboBox::AdjustToContentsOnFirstShow);
242 q->blockSignals(
false);
249 void KDateComboBoxPrivate::warnDate()
251 if (!m_warningShown && !q->
isValid() &&
254 if (!m_date.date().isValid()) {
255 warnMsg =
i18nc(
"@info",
"The date you entered is invalid");
256 }
else if (m_date.date() < m_minDate) {
257 if (m_minWarnMsg.isEmpty()) {
258 warnMsg =
i18nc(
"@info",
"Date cannot be earlier than %1", formatDate(m_minDate));
260 warnMsg = m_minWarnMsg;
261 warnMsg.replace(
"%1", formatDate(m_minDate));
263 }
else if (m_date.date() > m_maxDate) {
264 if (m_maxWarnMsg.isEmpty()) {
265 warnMsg =
i18nc(
"@info",
"Date cannot be later than %1", formatDate(m_maxDate));
267 warnMsg = m_maxWarnMsg;
268 warnMsg.replace(
"%1", formatDate(m_maxDate));
271 m_warningShown =
true;
279 d(new KDateComboBoxPrivate(this))
282 setMaxVisibleItems(1);
283 setInsertPolicy(QComboBox::NoInsert);
284 d->m_datePicker->installEventFilter(
this);
286 d->updateDateWidget();
288 connect(d->m_dateMenu, SIGNAL(triggered(
QAction*)),
289 this, SLOT(selectDate(
QAction*)));
290 connect(
this, SIGNAL(editTextChanged(
QString)),
291 this, SLOT(editDate(
QString)));
292 connect(d->m_datePicker, SIGNAL(
dateEntered(QDate)),
293 this, SLOT(enterDate(QDate)));
294 connect(d->m_datePicker, SIGNAL(tableClicked()),
295 this, SLOT(clickDate()));
306 return d->m_date.date();
311 if (date == d->m_date.date()) {
316 d->updateDateWidget();
327 return d->m_date.calendarSystem();
332 if (calendarSystem != d->m_date.calendarSystem()) {
339 d->m_date.setCalendarSystem(calendarSystem);
344 return d->m_date.calendar();
355 return d->m_date.isValid() &&
356 d->m_date >= d->m_minDate &&
357 d->m_date <= d->m_maxDate;
362 return lineEdit()->text().isEmpty();
372 if (options != d->m_options) {
375 d->updateDateWidget();
386 setDateRange(minDate, d->m_maxDate, minWarnMsg, d->m_maxWarnMsg);
401 setDateRange(d->m_minDate, maxDate, d->m_minWarnMsg, maxWarnMsg);
410 const QDate &maxDate,
414 if (!minDate.isValid() || !maxDate.isValid() || minDate > maxDate) {
418 if (minDate != d->m_minDate || maxDate != d->m_maxDate ||
419 minWarnMsg != d->m_minWarnMsg || maxWarnMsg != d->m_maxWarnMsg) {
420 d->m_minDate = minDate;
421 d->m_maxDate = maxDate;
422 d->m_minWarnMsg = minWarnMsg;
423 d->m_maxWarnMsg = maxWarnMsg;
425 d->enableMenuDates();
435 return d->m_displayFormat;
440 if (format != d->m_displayFormat) {
441 d->m_displayFormat = format;
443 d->updateDateWidget();
454 if (dateMap != d->m_dateMap) {
455 d->m_dateMap.clear();
469 switch (keyEvent->key()) {
471 temp = d->m_date.addDays(-1).date();
474 temp = d->m_date.addDays(1).date();
476 case Qt::Key_PageDown:
477 temp = d->m_date.addMonths(-1).date();
480 temp = d->m_date.addMonths(1).date();
483 KComboBox::keyPressEvent(keyEvent);
486 if (temp.isValid() && temp >= d->m_minDate && temp <= d->m_maxDate) {
495 KComboBox::focusOutEvent(event);
502 (d->m_options &KDateComboBox::SelectDate) != KDateComboBox::SelectDate) {
506 d->m_datePicker->blockSignals(
true);
507 d->m_datePicker->setDate(d->m_date.date());
508 d->m_datePicker->blockSignals(
false);
514 const int dateFrameHeight = d->m_dateMenu->sizeHint().height();
515 if (popupPoint.y() + height() + dateFrameHeight > desk.bottom()) {
516 popupPoint.setY(popupPoint.y() - dateFrameHeight);
518 popupPoint.setY(popupPoint.y() + height());
521 const int dateFrameWidth = d->m_dateMenu->sizeHint().width();
522 if (popupPoint.x() + dateFrameWidth > desk.right()) {
523 popupPoint.setX(desk.right() - dateFrameWidth);
526 if (popupPoint.x() < desk.left()) {
527 popupPoint.setX(desk.left());
530 if (popupPoint.y() < desk.top()) {
531 popupPoint.setY(desk.top());
534 d->m_dateMenu->popup(popupPoint);
539 KComboBox::hidePopup();
544 KComboBox::mousePressEvent(event);
554 KComboBox::focusInEvent(event);
559 KComboBox::resizeEvent(event);
562 #include "kdatecombobox.moc"