• Skip to content
  • Skip to link menu
  • KDE API Reference
  • kdelibs-4.10.5 API Reference
  • KDE Home
  • Contact Us
 

KDEUI

  • kdeui
  • widgets
kdatecombobox.cpp
Go to the documentation of this file.
1 /*
2  Copyright 2011 John Layt <john@layt.net>
3 
4  This library is free software; you can redistribute it and/or
5  modify it under the terms of the GNU Library General Public
6  License as published by the Free Software Foundation; either
7  version 2 of the License, or (at your option) any later version.
8 
9  This library is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  Library General Public License for more details.
13 
14  You should have received a copy of the GNU Library General Public License
15  along with this library; see the file COPYING.LIB. If not, write to
16  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17  Boston, MA 02110-1301, USA.
18 */
19 
20 #include "kdatecombobox.h"
21 
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>
29 
30 #include "kdebug.h"
31 #include "klocale.h"
32 #include "klocalizeddate.h"
33 #include "kcombobox.h"
34 #include "kdatepicker.h"
35 #include "kmessagebox.h"
36 
37 class KDateComboBoxPrivate
38 {
39 public:
40 
41  KDateComboBoxPrivate(KDateComboBox *q);
42  virtual ~KDateComboBoxPrivate();
43 
44  QDate defaultMinDate();
45  QDate defaultMaxDate();
46 
47  QString formatDate(const QDate &date);
48 
49  void initDateWidget();
50  void addMenuAction(const QString &text, const QDate &date);
51  void enableMenuDates();
52  void updateDateWidget();
53 
54 // Q_PRIVATE_SLOTs
55  void clickDate();
56  void selectDate(QAction *action);
57  void editDate(const QString &text);
58  void enterDate(const QDate &date);
59  void parseDate();
60  void warnDate();
61 
62  KDateComboBox *const q;
63  QMenu *m_dateMenu;
64  QVector<QAction*> m_actions;
65  KDatePicker *m_datePicker;
66  QWidgetAction *m_datePickerAction;
67 
68  KLocalizedDate m_date;
69  KDateComboBox::Options m_options;
70  QDate m_minDate;
71  QDate m_maxDate;
72  QString m_minWarnMsg;
73  QString m_maxWarnMsg;
74  bool m_warningShown;
75  KLocale::DateFormat m_displayFormat;
76  QMap<QDate, QString> m_dateMap;
77 };
78 
79 KDateComboBoxPrivate::KDateComboBoxPrivate(KDateComboBox *q)
80  :q(q),
81  m_dateMenu(new QMenu(q)),
82  m_datePicker(new KDatePicker(q)),
83  m_datePickerAction(new QWidgetAction(q)),
84  m_displayFormat(KLocale::ShortDate)
85 {
86  m_options = KDateComboBox::EditDate | KDateComboBox::SelectDate | KDateComboBox::DatePicker | KDateComboBox::DateKeywords;
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);
93 }
94 
95 KDateComboBoxPrivate::~KDateComboBoxPrivate()
96 {
97 }
98 
99 QDate KDateComboBoxPrivate::defaultMinDate()
100 {
101  return m_date.calendar()->earliestValidDate();
102 }
103 
104 QDate KDateComboBoxPrivate::defaultMaxDate()
105 {
106  return m_date.calendar()->latestValidDate();
107 }
108 
109 QString KDateComboBoxPrivate::formatDate(const QDate &date)
110 {
111  return m_date.calendar()->formatDate(date, m_displayFormat);
112 }
113 
114 void KDateComboBoxPrivate::initDateWidget()
115 {
116  q->blockSignals(true);
117  q->clear();
118 
119  // If EditTime then set the line edit
120  q->lineEdit()->setReadOnly((m_options &KDateComboBox::EditDate) != KDateComboBox::EditDate);
121 
122  // If SelectTime then make list items visible
123  if ((m_options &KDateComboBox::SelectDate) == KDateComboBox::SelectDate ||
124  (m_options &KDateComboBox::DatePicker) == KDateComboBox::DatePicker ||
125  (m_options &KDateComboBox::DatePicker) == KDateComboBox::DateKeywords) {
126  q->setMaxVisibleItems(1);
127  } else {
128  q->setMaxVisibleItems(0);
129  }
130 
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);
136 
137  m_dateMenu->clear();
138  m_actions.clear();
139 
140  if ((m_options & KDateComboBox::SelectDate) == KDateComboBox::SelectDate) {
141 
142  if ((m_options & KDateComboBox::DatePicker) == KDateComboBox::DatePicker) {
143  m_dateMenu->addAction(m_datePickerAction);
144  m_dateMenu->addSeparator();
145  }
146 
147  if ((m_options & KDateComboBox::DateKeywords) == KDateComboBox::DateKeywords) {
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());
160  } else {
161  QMapIterator<QDate, QString> i(m_dateMap);
162  while (i.hasNext()) {
163  i.next();
164  if (i.value().isEmpty()) {
165  addMenuAction(formatDate(i.key()), i.key());
166  } else if (i.value().toLower() == QLatin1String("separator")) {
167  m_dateMenu->addSeparator();
168  } else {
169  addMenuAction(i.value(), i.key());
170  }
171  }
172  }
173  enableMenuDates();
174  }
175  }
176 }
177 
178 void KDateComboBoxPrivate::addMenuAction(const QString &text, const QDate &date)
179 {
180  QAction *action = new QAction(m_dateMenu);
181  action->setText(text);
182  action->setData(date);
183  m_dateMenu->addAction(action);
184  m_actions << action;
185 }
186 
187 void KDateComboBoxPrivate::enableMenuDates()
188 {
189  // Hide menu dates if they are outside the date range
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));
193  }
194 }
195 
196 void KDateComboBoxPrivate::updateDateWidget()
197 {
198  q->blockSignals(true);
199  m_datePicker->blockSignals(true);
200  m_datePicker->setDate(m_date.date());
201  int pos = q->lineEdit()->cursorPosition();
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);
207 }
208 
209 void KDateComboBoxPrivate::selectDate(QAction *action)
210 {
211  if (action->objectName() != QLatin1String("DatePicker")) {
212  enterDate(action->data().toDate());
213  }
214 }
215 
216 void KDateComboBoxPrivate::clickDate()
217 {
218  enterDate(m_datePicker->date());
219 }
220 
221 void KDateComboBoxPrivate::editDate(const QString &text)
222 {
223  m_warningShown = false;
224  emit q->dateEdited(m_date.readDate(text).date());
225 }
226 
227 void KDateComboBoxPrivate::parseDate()
228 {
229  m_date.setDate(m_date.readDate(q->lineEdit()->text()).date());
230 }
231 
232 void KDateComboBoxPrivate::enterDate(const QDate &date)
233 {
234  q->setDate(date);
235  // Re-add the combo box item in order to retain the correct widget width
236  q->blockSignals(true);
237  q->clear();
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);
243 
244  m_dateMenu->hide();
245  warnDate();
246  emit q->dateEntered(m_date.date());
247 }
248 
249 void KDateComboBoxPrivate::warnDate()
250 {
251  if (!m_warningShown && !q->isValid() &&
252  (m_options &KDateComboBox::WarnOnInvalid) == KDateComboBox::WarnOnInvalid) {
253  QString warnMsg;
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));
259  } else {
260  warnMsg = m_minWarnMsg;
261  warnMsg.replace("%1", formatDate(m_minDate));
262  }
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));
266  } else {
267  warnMsg = m_maxWarnMsg;
268  warnMsg.replace("%1", formatDate(m_maxDate));
269  }
270  }
271  m_warningShown = true;
272  KMessageBox::sorry(q, warnMsg);
273  }
274 }
275 
276 
277 KDateComboBox::KDateComboBox(QWidget *parent)
278  :KComboBox(parent),
279  d(new KDateComboBoxPrivate(this))
280 {
281  setEditable(true);
282  setMaxVisibleItems(1);
283  setInsertPolicy(QComboBox::NoInsert);
284  d->m_datePicker->installEventFilter(this);
285  d->initDateWidget();
286  d->updateDateWidget();
287 
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()));
296 }
297 
298 KDateComboBox::~KDateComboBox()
299 {
300  delete d;
301 }
302 
303 QDate KDateComboBox::date() const
304 {
305  d->parseDate();
306  return d->m_date.date();
307 }
308 
309 void KDateComboBox::setDate(const QDate &date)
310 {
311  if (date == d->m_date.date()) {
312  return;
313  }
314 
315  assignDate(date);
316  d->updateDateWidget();
317  emit dateChanged(d->m_date.date());
318 }
319 
320 void KDateComboBox::assignDate(const QDate &date)
321 {
322  d->m_date = date;
323 }
324 
325 KLocale::CalendarSystem KDateComboBox::calendarSystem() const
326 {
327  return d->m_date.calendarSystem();
328 }
329 
330 void KDateComboBox::setCalendarSystem(KLocale::CalendarSystem calendarSystem)
331 {
332  if (calendarSystem != d->m_date.calendarSystem()) {
333  assignCalendarSystem(calendarSystem);
334  }
335 }
336 
337 void KDateComboBox::assignCalendarSystem(KLocale::CalendarSystem calendarSystem)
338 {
339  d->m_date.setCalendarSystem(calendarSystem);
340 }
341 
342 const KCalendarSystem *KDateComboBox::calendar() const
343 {
344  return d->m_date.calendar();
345 }
346 
347 void KDateComboBox::setCalendar(KCalendarSystem *calendar)
348 {
349  d->m_date = KLocalizedDate(d->m_date.date(), calendar);
350 }
351 
352 bool KDateComboBox::isValid() const
353 {
354  d->parseDate();
355  return d->m_date.isValid() &&
356  d->m_date >= d->m_minDate &&
357  d->m_date <= d->m_maxDate;
358 }
359 
360 bool KDateComboBox::isNull() const
361 {
362  return lineEdit()->text().isEmpty();
363 }
364 
365 KDateComboBox::Options KDateComboBox::options() const
366 {
367  return d->m_options;
368 }
369 
370 void KDateComboBox::setOptions(Options options)
371 {
372  if (options != d->m_options) {
373  d->m_options = options;
374  d->initDateWidget();
375  d->updateDateWidget();
376  }
377 }
378 
379 QDate KDateComboBox::minimumDate() const
380 {
381  return d->m_minDate;
382 }
383 
384 void KDateComboBox::setMinimumDate(const QDate &minDate, const QString &minWarnMsg)
385 {
386  setDateRange(minDate, d->m_maxDate, minWarnMsg, d->m_maxWarnMsg);
387 }
388 
389 void KDateComboBox::resetMinimumDate()
390 {
391  setDateRange(d->defaultMinDate(), d->m_maxDate, QString(), d->m_maxWarnMsg);
392 }
393 
394 QDate KDateComboBox::maximumDate() const
395 {
396  return d->m_maxDate;
397 }
398 
399 void KDateComboBox::setMaximumDate(const QDate &maxDate, const QString &maxWarnMsg)
400 {
401  setDateRange(d->m_minDate, maxDate, d->m_minWarnMsg, maxWarnMsg);
402 }
403 
404 void KDateComboBox::resetMaximumDate()
405 {
406  setDateRange(d->m_minDate, d->defaultMaxDate(), d->m_minWarnMsg, QString());
407 }
408 
409 void KDateComboBox::setDateRange(const QDate &minDate,
410  const QDate &maxDate,
411  const QString &minWarnMsg,
412  const QString &maxWarnMsg)
413 {
414  if (!minDate.isValid() || !maxDate.isValid() || minDate > maxDate) {
415  return;
416  }
417 
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;
424  }
425  d->enableMenuDates();
426 }
427 
428 void KDateComboBox::resetDateRange()
429 {
430  setDateRange(d->defaultMinDate(), d->defaultMaxDate(), QString(), QString());
431 }
432 
433 KLocale::DateFormat KDateComboBox::displayFormat() const
434 {
435  return d->m_displayFormat;
436 }
437 
438 void KDateComboBox::setDisplayFormat(KLocale::DateFormat format)
439 {
440  if (format != d->m_displayFormat) {
441  d->m_displayFormat = format;
442  d->initDateWidget();
443  d->updateDateWidget();
444  }
445 }
446 
447 QMap<QDate, QString> KDateComboBox::dateMap() const
448 {
449  return d->m_dateMap;
450 }
451 
452 void KDateComboBox::setDateMap(QMap<QDate, QString> dateMap)
453 {
454  if (dateMap != d->m_dateMap) {
455  d->m_dateMap.clear();
456  d->m_dateMap = dateMap;
457  d->initDateWidget();
458  }
459 }
460 
461 bool KDateComboBox::eventFilter(QObject *object, QEvent *event)
462 {
463  return KComboBox::eventFilter(object, event);
464 }
465 
466 void KDateComboBox::keyPressEvent(QKeyEvent *keyEvent)
467 {
468  QDate temp;
469  switch (keyEvent->key()) {
470  case Qt::Key_Down:
471  temp = d->m_date.addDays(-1).date();
472  break;
473  case Qt::Key_Up:
474  temp = d->m_date.addDays(1).date();
475  break;
476  case Qt::Key_PageDown:
477  temp = d->m_date.addMonths(-1).date();
478  break;
479  case Qt::Key_PageUp:
480  temp = d->m_date.addMonths(1).date();
481  break;
482  default:
483  KComboBox::keyPressEvent(keyEvent);
484  return;
485  }
486  if (temp.isValid() && temp >= d->m_minDate && temp <= d->m_maxDate) {
487  d->enterDate(temp);
488  }
489 }
490 
491 void KDateComboBox::focusOutEvent(QFocusEvent *event)
492 {
493  d->parseDate();
494  d->warnDate();
495  KComboBox::focusOutEvent(event);
496 }
497 
498 void KDateComboBox::showPopup()
499 {
500  if (!isEditable() ||
501  !d->m_dateMenu ||
502  (d->m_options &KDateComboBox::SelectDate) != KDateComboBox::SelectDate) {
503  return;
504  }
505 
506  d->m_datePicker->blockSignals(true);
507  d->m_datePicker->setDate(d->m_date.date());
508  d->m_datePicker->blockSignals(false);
509 
510  const QRect desk = KGlobalSettings::desktopGeometry(this);
511 
512  QPoint popupPoint = mapToGlobal(QPoint(0, 0));
513 
514  const int dateFrameHeight = d->m_dateMenu->sizeHint().height();
515  if (popupPoint.y() + height() + dateFrameHeight > desk.bottom()) {
516  popupPoint.setY(popupPoint.y() - dateFrameHeight);
517  } else {
518  popupPoint.setY(popupPoint.y() + height());
519  }
520 
521  const int dateFrameWidth = d->m_dateMenu->sizeHint().width();
522  if (popupPoint.x() + dateFrameWidth > desk.right()) {
523  popupPoint.setX(desk.right() - dateFrameWidth);
524  }
525 
526  if (popupPoint.x() < desk.left()) {
527  popupPoint.setX(desk.left());
528  }
529 
530  if (popupPoint.y() < desk.top()) {
531  popupPoint.setY(desk.top());
532  }
533 
534  d->m_dateMenu->popup(popupPoint);
535 }
536 
537 void KDateComboBox::hidePopup()
538 {
539  KComboBox::hidePopup();
540 }
541 
542 void KDateComboBox::mousePressEvent(QMouseEvent *event)
543 {
544  KComboBox::mousePressEvent(event);
545 }
546 
547 void KDateComboBox::wheelEvent(QWheelEvent *event)
548 {
549  KComboBox::wheelEvent(event);
550 }
551 
552 void KDateComboBox::focusInEvent(QFocusEvent *event)
553 {
554  KComboBox::focusInEvent(event);
555 }
556 
557 void KDateComboBox::resizeEvent(QResizeEvent *event)
558 {
559  KComboBox::resizeEvent(event);
560 }
561 
562 #include "kdatecombobox.moc"
This file is part of the KDE documentation.
Documentation copyright © 1996-2013 The KDE developers.
Generated on Mon Jul 15 2013 13:04:40 by doxygen 1.8.3.1 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

KDEUI

Skip menu "KDEUI"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • File Members
  • Modules
  • Related Pages

kdelibs-4.10.5 API Reference

Skip menu "kdelibs-4.10.5 API Reference"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal