22#include <QtGui/QAbstractItemView>
23#include <QtGui/QApplication>
24#include <QtGui/QKeyEvent>
26#include <QtGui/QLineEdit>
27#include <QtGui/QWidgetAction>
28#include <QtCore/QVector>
37class 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);
96KDateComboBoxPrivate::~KDateComboBoxPrivate()
100QDate KDateComboBoxPrivate::defaultMinDate()
102 return m_date.calendar()->earliestValidDate();
105QDate KDateComboBoxPrivate::defaultMaxDate()
107 return m_date.calendar()->latestValidDate();
110QString KDateComboBoxPrivate::formatDate(
const QDate &date)
112 return m_date.calendar()->formatDate(date, m_displayFormat);
115void 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);
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());
179void KDateComboBoxPrivate::addMenuAction(
const QString &text,
const QDate &date)
182 action->setText(text);
183 action->setData(date);
184 m_dateMenu->addAction(action);
188void 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));
197void 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);
210void KDateComboBoxPrivate::selectDate(
QAction *action)
212 if (action->objectName() != QLatin1String(
"DatePicker")) {
213 enterDate(action->data().toDate());
217void KDateComboBoxPrivate::clickDate()
219 enterDate(m_datePicker->date());
222void KDateComboBoxPrivate::editDate(
const QString &text)
224 m_warningShown =
false;
225 emit q->
dateEdited(m_date.readDate(text).date());
228void KDateComboBoxPrivate::parseDate()
230 m_date.setDate(m_date.readDate(q->lineEdit()->text()).date());
233void 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);
250void 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) {
374 d->m_options = options;
376 d->updateDateWidget();
387 setDateRange(minDate, d->m_maxDate, minWarnMsg, d->m_maxWarnMsg);
392 setDateRange(d->defaultMinDate(), d->m_maxDate, QString(), d->m_maxWarnMsg);
402 setDateRange(d->m_minDate, maxDate, d->m_minWarnMsg, maxWarnMsg);
407 setDateRange(d->m_minDate, d->defaultMaxDate(), d->m_minWarnMsg, QString());
411 const QDate &maxDate,
412 const QString &minWarnMsg,
413 const QString &maxWarnMsg)
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();
431 setDateRange(d->defaultMinDate(), d->defaultMaxDate(), QString(), QString());
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();
457 d->m_dateMap = dateMap;
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);
507 d->m_datePicker->blockSignals(
true);
508 d->m_datePicker->setDate(d->m_date.date());
509 d->m_datePicker->blockSignals(
false);
513 QPoint popupPoint = mapToGlobal(QPoint(0, 0));
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"
virtual bool eventFilter(QObject *, QEvent *)
Re-implemented for internal reasons.
virtual void wheelEvent(QWheelEvent *ev)
void setEditable(bool editable)
"Re-implemented" so that setEditable(true) creates a KLineEdit instead of QLineEdit.
int cursorPosition() const
Returns the current cursor position.
virtual bool eventFilter(QObject *object, QEvent *event)
Re-implemented for internal reasons.
void setOptions(Options options)
Set the new widget options.
void setMinimumDate(const QDate &minTime, const QString &minWarnMsg=QString())
Set the minimum allowed date.
void setCalendar(KCalendarSystem *calendar=0)
Changes the calendar system to use.
void dateEdited(const QDate &date)
Signal if the date is being manually edited by the user.
bool isNull() const
Return if the current user input is null.
virtual void keyPressEvent(QKeyEvent *event)
void setDisplayFormat(KLocale::DateFormat format)
Sets the date format to display.
virtual void resizeEvent(QResizeEvent *event)
void resetMinimumDate()
Reset the minimum date to the default.
KDateComboBox(QWidget *parent=0)
Create a new KDateComboBox widget.
KLocale::DateFormat displayFormat() const
Return the currently set date display format.
virtual ~KDateComboBox()
Destroy the widget.
KLocale::CalendarSystem calendarSystem() const
Returns the Calendar System type used by the widget.
const KCalendarSystem * calendar() const
Returns a pointer to the Calendar System object used by this widget.
@ SelectDate
Allow the user to select the date from a drop-down menu.
@ DateKeywords
Show date keywords in the drop-down.
@ WarnOnInvalid
Show a warning on focus out if the date is invalid.
@ EditDate
Allow the user to manually edit the date in the combo line edit.
@ DatePicker
Show a date picker in the drop-down.
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 setMaximumDate(const QDate &maxDate, const QString &maxWarnMsg=QString())
Set the maximum allowed date.
void resetDateRange()
Reset the minimum and maximum date to the default values.
virtual void focusOutEvent(QFocusEvent *event)
virtual void focusInEvent(QFocusEvent *event)
void setCalendarSystem(KLocale::CalendarSystem calendarSystem)
Set the Calendar System used for this widget.
QMap< QDate, QString > dateMap() const
Return the map of dates listed in the drop-down and their displayed string forms.
virtual void assignDate(const QDate &date)
Assign the date for the widget.
virtual void wheelEvent(QWheelEvent *event)
void resetMaximumDate()
Reset the maximum date to the default.
virtual void mousePressEvent(QMouseEvent *event)
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 programatically.
virtual void assignCalendarSystem(KLocale::CalendarSystem calendarSystem)
Assign the calendar system for the widget.
void dateEntered(const QDate &date)
Signal if the date has been manually entered or selected by the user.
void setDateRange(const QDate &minDate, const QDate &maxDate, const QString &minWarnMsg=QString(), const QString &maxWarnMsg=QString())
Set the valid date range to be applied by isValid().
static QRect desktopGeometry(const QPoint &point)
This function returns the desktop geometry for an application that needs to set the geometry of a wid...
static void sorry(QWidget *parent, const QString &text, const QString &caption=QString(), Options options=Notify)
Display an "Sorry" dialog.
QString i18nc(const char *ctxt, const char *text)