• Skip to content
  • Skip to link menu
  • KDE API Reference
  • kdelibs-4.11.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_warningShown(false),
85  m_displayFormat(KLocale::ShortDate)
86 {
87  m_options = KDateComboBox::EditDate | KDateComboBox::SelectDate | KDateComboBox::DatePicker | KDateComboBox::DateKeywords;
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);
94 }
95 
96 KDateComboBoxPrivate::~KDateComboBoxPrivate()
97 {
98 }
99 
100 QDate KDateComboBoxPrivate::defaultMinDate()
101 {
102  return m_date.calendar()->earliestValidDate();
103 }
104 
105 QDate KDateComboBoxPrivate::defaultMaxDate()
106 {
107  return m_date.calendar()->latestValidDate();
108 }
109 
110 QString KDateComboBoxPrivate::formatDate(const QDate &date)
111 {
112  return m_date.calendar()->formatDate(date, m_displayFormat);
113 }
114 
115 void KDateComboBoxPrivate::initDateWidget()
116 {
117  q->blockSignals(true);
118  q->clear();
119 
120  // If EditTime then set the line edit
121  q->lineEdit()->setReadOnly((m_options &KDateComboBox::EditDate) != KDateComboBox::EditDate);
122 
123  // If SelectTime then make list items visible
124  if ((m_options &KDateComboBox::SelectDate) == KDateComboBox::SelectDate ||
125  (m_options &KDateComboBox::DatePicker) == KDateComboBox::DatePicker ||
126  (m_options &KDateComboBox::DatePicker) == KDateComboBox::DateKeywords) {
127  q->setMaxVisibleItems(1);
128  } else {
129  q->setMaxVisibleItems(0);
130  }
131 
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);
137 
138  m_dateMenu->clear();
139  m_actions.clear();
140 
141  if ((m_options & KDateComboBox::SelectDate) == KDateComboBox::SelectDate) {
142 
143  if ((m_options & KDateComboBox::DatePicker) == KDateComboBox::DatePicker) {
144  m_dateMenu->addAction(m_datePickerAction);
145  m_dateMenu->addSeparator();
146  }
147 
148  if ((m_options & KDateComboBox::DateKeywords) == KDateComboBox::DateKeywords) {
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());
161  } else {
162  QMapIterator<QDate, QString> i(m_dateMap);
163  while (i.hasNext()) {
164  i.next();
165  if (i.value().isEmpty()) {
166  addMenuAction(formatDate(i.key()), i.key());
167  } else if (i.value().toLower() == QLatin1String("separator")) {
168  m_dateMenu->addSeparator();
169  } else {
170  addMenuAction(i.value(), i.key());
171  }
172  }
173  }
174  enableMenuDates();
175  }
176  }
177 }
178 
179 void KDateComboBoxPrivate::addMenuAction(const QString &text, const QDate &date)
180 {
181  QAction *action = new QAction(m_dateMenu);
182  action->setText(text);
183  action->setData(date);
184  m_dateMenu->addAction(action);
185  m_actions << action;
186 }
187 
188 void KDateComboBoxPrivate::enableMenuDates()
189 {
190  // Hide menu dates if they are outside the date range
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));
194  }
195 }
196 
197 void KDateComboBoxPrivate::updateDateWidget()
198 {
199  q->blockSignals(true);
200  m_datePicker->blockSignals(true);
201  m_datePicker->setDate(m_date.date());
202  int pos = q->lineEdit()->cursorPosition();
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);
208 }
209 
210 void KDateComboBoxPrivate::selectDate(QAction *action)
211 {
212  if (action->objectName() != QLatin1String("DatePicker")) {
213  enterDate(action->data().toDate());
214  }
215 }
216 
217 void KDateComboBoxPrivate::clickDate()
218 {
219  enterDate(m_datePicker->date());
220 }
221 
222 void KDateComboBoxPrivate::editDate(const QString &text)
223 {
224  m_warningShown = false;
225  emit q->dateEdited(m_date.readDate(text).date());
226 }
227 
228 void KDateComboBoxPrivate::parseDate()
229 {
230  m_date.setDate(m_date.readDate(q->lineEdit()->text()).date());
231 }
232 
233 void KDateComboBoxPrivate::enterDate(const QDate &date)
234 {
235  q->setDate(date);
236  // Re-add the combo box item in order to retain the correct widget width
237  q->blockSignals(true);
238  q->clear();
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);
244 
245  m_dateMenu->hide();
246  warnDate();
247  emit q->dateEntered(m_date.date());
248 }
249 
250 void KDateComboBoxPrivate::warnDate()
251 {
252  if (!m_warningShown && !q->isValid() &&
253  (m_options &KDateComboBox::WarnOnInvalid) == KDateComboBox::WarnOnInvalid) {
254  QString warnMsg;
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));
260  } else {
261  warnMsg = m_minWarnMsg;
262  warnMsg.replace("%1", formatDate(m_minDate));
263  }
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));
267  } else {
268  warnMsg = m_maxWarnMsg;
269  warnMsg.replace("%1", formatDate(m_maxDate));
270  }
271  }
272  m_warningShown = true;
273  KMessageBox::sorry(q, warnMsg);
274  }
275 }
276 
277 
278 KDateComboBox::KDateComboBox(QWidget *parent)
279  :KComboBox(parent),
280  d(new KDateComboBoxPrivate(this))
281 {
282  setEditable(true);
283  setMaxVisibleItems(1);
284  setInsertPolicy(QComboBox::NoInsert);
285  d->m_datePicker->installEventFilter(this);
286  d->initDateWidget();
287  d->updateDateWidget();
288 
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()));
297 }
298 
299 KDateComboBox::~KDateComboBox()
300 {
301  delete d;
302 }
303 
304 QDate KDateComboBox::date() const
305 {
306  d->parseDate();
307  return d->m_date.date();
308 }
309 
310 void KDateComboBox::setDate(const QDate &date)
311 {
312  if (date == d->m_date.date()) {
313  return;
314  }
315 
316  assignDate(date);
317  d->updateDateWidget();
318  emit dateChanged(d->m_date.date());
319 }
320 
321 void KDateComboBox::assignDate(const QDate &date)
322 {
323  d->m_date = date;
324 }
325 
326 KLocale::CalendarSystem KDateComboBox::calendarSystem() const
327 {
328  return d->m_date.calendarSystem();
329 }
330 
331 void KDateComboBox::setCalendarSystem(KLocale::CalendarSystem calendarSystem)
332 {
333  if (calendarSystem != d->m_date.calendarSystem()) {
334  assignCalendarSystem(calendarSystem);
335  }
336 }
337 
338 void KDateComboBox::assignCalendarSystem(KLocale::CalendarSystem calendarSystem)
339 {
340  d->m_date.setCalendarSystem(calendarSystem);
341 }
342 
343 const KCalendarSystem *KDateComboBox::calendar() const
344 {
345  return d->m_date.calendar();
346 }
347 
348 void KDateComboBox::setCalendar(KCalendarSystem *calendar)
349 {
350  d->m_date = KLocalizedDate(d->m_date.date(), calendar);
351 }
352 
353 bool KDateComboBox::isValid() const
354 {
355  d->parseDate();
356  return d->m_date.isValid() &&
357  d->m_date >= d->m_minDate &&
358  d->m_date <= d->m_maxDate;
359 }
360 
361 bool KDateComboBox::isNull() const
362 {
363  return lineEdit()->text().isEmpty();
364 }
365 
366 KDateComboBox::Options KDateComboBox::options() const
367 {
368  return d->m_options;
369 }
370 
371 void KDateComboBox::setOptions(Options options)
372 {
373  if (options != d->m_options) {
374  d->m_options = options;
375  d->initDateWidget();
376  d->updateDateWidget();
377  }
378 }
379 
380 QDate KDateComboBox::minimumDate() const
381 {
382  return d->m_minDate;
383 }
384 
385 void KDateComboBox::setMinimumDate(const QDate &minDate, const QString &minWarnMsg)
386 {
387  setDateRange(minDate, d->m_maxDate, minWarnMsg, d->m_maxWarnMsg);
388 }
389 
390 void KDateComboBox::resetMinimumDate()
391 {
392  setDateRange(d->defaultMinDate(), d->m_maxDate, QString(), d->m_maxWarnMsg);
393 }
394 
395 QDate KDateComboBox::maximumDate() const
396 {
397  return d->m_maxDate;
398 }
399 
400 void KDateComboBox::setMaximumDate(const QDate &maxDate, const QString &maxWarnMsg)
401 {
402  setDateRange(d->m_minDate, maxDate, d->m_minWarnMsg, maxWarnMsg);
403 }
404 
405 void KDateComboBox::resetMaximumDate()
406 {
407  setDateRange(d->m_minDate, d->defaultMaxDate(), d->m_minWarnMsg, QString());
408 }
409 
410 void KDateComboBox::setDateRange(const QDate &minDate,
411  const QDate &maxDate,
412  const QString &minWarnMsg,
413  const QString &maxWarnMsg)
414 {
415  if (!minDate.isValid() || !maxDate.isValid() || minDate > maxDate) {
416  return;
417  }
418 
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;
425  }
426  d->enableMenuDates();
427 }
428 
429 void KDateComboBox::resetDateRange()
430 {
431  setDateRange(d->defaultMinDate(), d->defaultMaxDate(), QString(), QString());
432 }
433 
434 KLocale::DateFormat KDateComboBox::displayFormat() const
435 {
436  return d->m_displayFormat;
437 }
438 
439 void KDateComboBox::setDisplayFormat(KLocale::DateFormat format)
440 {
441  if (format != d->m_displayFormat) {
442  d->m_displayFormat = format;
443  d->initDateWidget();
444  d->updateDateWidget();
445  }
446 }
447 
448 QMap<QDate, QString> KDateComboBox::dateMap() const
449 {
450  return d->m_dateMap;
451 }
452 
453 void KDateComboBox::setDateMap(QMap<QDate, QString> dateMap)
454 {
455  if (dateMap != d->m_dateMap) {
456  d->m_dateMap.clear();
457  d->m_dateMap = dateMap;
458  d->initDateWidget();
459  }
460 }
461 
462 bool KDateComboBox::eventFilter(QObject *object, QEvent *event)
463 {
464  return KComboBox::eventFilter(object, event);
465 }
466 
467 void KDateComboBox::keyPressEvent(QKeyEvent *keyEvent)
468 {
469  QDate temp;
470  switch (keyEvent->key()) {
471  case Qt::Key_Down:
472  temp = d->m_date.addDays(-1).date();
473  break;
474  case Qt::Key_Up:
475  temp = d->m_date.addDays(1).date();
476  break;
477  case Qt::Key_PageDown:
478  temp = d->m_date.addMonths(-1).date();
479  break;
480  case Qt::Key_PageUp:
481  temp = d->m_date.addMonths(1).date();
482  break;
483  default:
484  KComboBox::keyPressEvent(keyEvent);
485  return;
486  }
487  if (temp.isValid() && temp >= d->m_minDate && temp <= d->m_maxDate) {
488  d->enterDate(temp);
489  }
490 }
491 
492 void KDateComboBox::focusOutEvent(QFocusEvent *event)
493 {
494  d->parseDate();
495  d->warnDate();
496  KComboBox::focusOutEvent(event);
497 }
498 
499 void KDateComboBox::showPopup()
500 {
501  if (!isEditable() ||
502  !d->m_dateMenu ||
503  (d->m_options &KDateComboBox::SelectDate) != KDateComboBox::SelectDate) {
504  return;
505  }
506 
507  d->m_datePicker->blockSignals(true);
508  d->m_datePicker->setDate(d->m_date.date());
509  d->m_datePicker->blockSignals(false);
510 
511  const QRect desk = KGlobalSettings::desktopGeometry(this);
512 
513  QPoint popupPoint = mapToGlobal(QPoint(0, 0));
514 
515  const int dateFrameHeight = d->m_dateMenu->sizeHint().height();
516  if (popupPoint.y() + height() + dateFrameHeight > desk.bottom()) {
517  popupPoint.setY(popupPoint.y() - dateFrameHeight);
518  } else {
519  popupPoint.setY(popupPoint.y() + height());
520  }
521 
522  const int dateFrameWidth = d->m_dateMenu->sizeHint().width();
523  if (popupPoint.x() + dateFrameWidth > desk.right()) {
524  popupPoint.setX(desk.right() - dateFrameWidth);
525  }
526 
527  if (popupPoint.x() < desk.left()) {
528  popupPoint.setX(desk.left());
529  }
530 
531  if (popupPoint.y() < desk.top()) {
532  popupPoint.setY(desk.top());
533  }
534 
535  d->m_dateMenu->popup(popupPoint);
536 }
537 
538 void KDateComboBox::hidePopup()
539 {
540  KComboBox::hidePopup();
541 }
542 
543 void KDateComboBox::mousePressEvent(QMouseEvent *event)
544 {
545  KComboBox::mousePressEvent(event);
546 }
547 
548 void KDateComboBox::wheelEvent(QWheelEvent *event)
549 {
550  KComboBox::wheelEvent(event);
551 }
552 
553 void KDateComboBox::focusInEvent(QFocusEvent *event)
554 {
555  KComboBox::focusInEvent(event);
556 }
557 
558 void KDateComboBox::resizeEvent(QResizeEvent *event)
559 {
560  KComboBox::resizeEvent(event);
561 }
562 
563 #include "kdatecombobox.moc"
This file is part of the KDE documentation.
Documentation copyright © 1996-2014 The KDE developers.
Generated on Thu Sep 25 2014 04:19:51 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.11.5 API Reference

Skip menu "kdelibs-4.11.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