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

KDEUI

kdatecombobox.cpp
Go to the documentation of this file.
00001 /*
00002     Copyright 2011 John Layt <john@layt.net>
00003 
00004     This library is free software; you can redistribute it and/or
00005     modify it under the terms of the GNU Library General Public
00006     License as published by the Free Software Foundation; either
00007     version 2 of the License, or (at your option) any later version.
00008 
00009     This library is distributed in the hope that it will be useful,
00010     but WITHOUT ANY WARRANTY; without even the implied warranty of
00011     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012     Library General Public License for more details.
00013 
00014     You should have received a copy of the GNU Library General Public License
00015     along with this library; see the file COPYING.LIB.  If not, write to
00016     the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00017     Boston, MA 02110-1301, USA.
00018 */
00019 
00020 #include "kdatecombobox.h"
00021 
00022 #include <QtGui/QAbstractItemView>
00023 #include <QtGui/QApplication>
00024 #include <QtGui/QKeyEvent>
00025 #include <QtGui/QMenu>
00026 #include <QtGui/QLineEdit>
00027 #include <QtGui/QWidgetAction>
00028 #include <QtCore/QVector>
00029 
00030 #include "kdebug.h"
00031 #include "klocale.h"
00032 #include "klocalizeddate.h"
00033 #include "kcombobox.h"
00034 #include "kdatepicker.h"
00035 #include "kmessagebox.h"
00036 
00037 class KDateComboBoxPrivate
00038 {
00039 public:
00040 
00041     KDateComboBoxPrivate(KDateComboBox *q);
00042     virtual ~KDateComboBoxPrivate();
00043 
00044     QDate defaultMinDate();
00045     QDate defaultMaxDate();
00046 
00047     QString formatDate(const QDate &date);
00048 
00049     void initDateWidget();
00050     void addMenuAction(const QString &text, const QDate &date);
00051     void enableMenuDates();
00052     void updateDateWidget();
00053 
00054 // Q_PRIVATE_SLOTs
00055     void clickDate();
00056     void selectDate(QAction *action);
00057     void editDate(const QString &text);
00058     void enterDate(const QDate &date);
00059     void parseDate();
00060     void warnDate();
00061 
00062     KDateComboBox *const q;
00063     QMenu *m_dateMenu;
00064     QVector<QAction*> m_actions;
00065     KDatePicker *m_datePicker;
00066     QWidgetAction *m_datePickerAction;
00067 
00068     KLocalizedDate m_date;
00069     KDateComboBox::Options m_options;
00070     QDate m_minDate;
00071     QDate m_maxDate;
00072     QString m_minWarnMsg;
00073     QString m_maxWarnMsg;
00074     bool m_warningShown;
00075     KLocale::DateFormat m_displayFormat;
00076     QMap<QDate, QString> m_dateMap;
00077 };
00078 
00079 KDateComboBoxPrivate::KDateComboBoxPrivate(KDateComboBox *q)
00080                      :q(q),
00081                       m_dateMenu(new QMenu(q)),
00082                       m_datePicker(new KDatePicker(q)),
00083                       m_datePickerAction(new QWidgetAction(q)),
00084                       m_displayFormat(KLocale::ShortDate)
00085 {
00086     m_options = KDateComboBox::EditDate | KDateComboBox::SelectDate | KDateComboBox::DatePicker | KDateComboBox::DateKeywords;
00087     m_date.setDate(QDate::currentDate());
00088     m_minDate = defaultMinDate();
00089     m_maxDate = defaultMaxDate();
00090     m_datePicker->setCloseButton(false);
00091     m_datePickerAction->setObjectName(QLatin1String("DatePicker"));
00092     m_datePickerAction->setDefaultWidget(m_datePicker);
00093 }
00094 
00095 KDateComboBoxPrivate::~KDateComboBoxPrivate()
00096 {
00097 }
00098 
00099 QDate KDateComboBoxPrivate::defaultMinDate()
00100 {
00101     return m_date.calendar()->earliestValidDate();
00102 }
00103 
00104 QDate KDateComboBoxPrivate::defaultMaxDate()
00105 {
00106     return m_date.calendar()->latestValidDate();
00107 }
00108 
00109 QString KDateComboBoxPrivate::formatDate(const QDate &date)
00110 {
00111     return m_date.calendar()->formatDate(date, m_displayFormat);
00112 }
00113 
00114 void KDateComboBoxPrivate::initDateWidget()
00115 {
00116     q->blockSignals(true);
00117     q->clear();
00118 
00119     // If EditTime then set the line edit
00120     q->lineEdit()->setReadOnly((m_options &KDateComboBox::EditDate) != KDateComboBox::EditDate);
00121 
00122     // If SelectTime then make list items visible
00123     if ((m_options &KDateComboBox::SelectDate) == KDateComboBox::SelectDate ||
00124         (m_options &KDateComboBox::DatePicker) == KDateComboBox::DatePicker ||
00125         (m_options &KDateComboBox::DatePicker) == KDateComboBox::DateKeywords) {
00126         q->setMaxVisibleItems(1);
00127     } else {
00128         q->setMaxVisibleItems(0);
00129     }
00130 
00131     q->setSizeAdjustPolicy(QComboBox::AdjustToContents);
00132     q->addItem(m_date.formatDate(m_displayFormat));
00133     q->setCurrentIndex(0);
00134     q->setSizeAdjustPolicy(QComboBox::AdjustToContentsOnFirstShow);
00135     q->blockSignals(false);
00136 
00137     m_dateMenu->clear();
00138     m_actions.clear();
00139 
00140     if ((m_options & KDateComboBox::SelectDate) == KDateComboBox::SelectDate) {
00141 
00142         if ((m_options & KDateComboBox::DatePicker) == KDateComboBox::DatePicker) {
00143             m_dateMenu->addAction(m_datePickerAction);
00144             m_dateMenu->addSeparator();
00145         }
00146 
00147         if ((m_options & KDateComboBox::DateKeywords) == KDateComboBox::DateKeywords) {
00148             if (m_dateMap.isEmpty()) {
00149                 addMenuAction(i18nc("@option next year",  "Next Year" ), m_date.addYears(1).date());
00150                 addMenuAction(i18nc("@option next month", "Next Month"), m_date.addMonths(1).date());
00151                 addMenuAction(i18nc("@option next week",  "Next Week" ), m_date.addDays(m_date.daysInWeek()).date());
00152                 addMenuAction(i18nc("@option tomorrow",   "Tomorrow"  ), m_date.addDays(1).date());
00153                 addMenuAction(i18nc("@option today",      "Today"     ), m_date.date());
00154                 addMenuAction(i18nc("@option yesterday",  "Yesterday" ), m_date.addDays(-1).date());
00155                 addMenuAction(i18nc("@option last week",  "Last Week" ), m_date.addDays(-m_date.daysInWeek()).date());
00156                 addMenuAction(i18nc("@option last month", "Last Month"), m_date.addMonths(-1).date());
00157                 addMenuAction(i18nc("@option last year",  "Last Year" ), m_date.addYears(-1).date());
00158                 m_dateMenu->addSeparator();
00159                 addMenuAction(i18nc("@option do not specify a date", "No Date"), QDate());
00160             } else {
00161                 QMapIterator<QDate, QString> i(m_dateMap);
00162                 while (i.hasNext()) {
00163                     i.next();
00164                     if (i.value().isEmpty()) {
00165                         addMenuAction(formatDate(i.key()), i.key());
00166                     } else if (i.value().toLower() == QLatin1String("separator")) {
00167                         m_dateMenu->addSeparator();
00168                     } else {
00169                         addMenuAction(i.value(), i.key());
00170                     }
00171                 }
00172             }
00173             enableMenuDates();
00174         }
00175     }
00176 }
00177 
00178 void KDateComboBoxPrivate::addMenuAction(const QString &text, const QDate &date)
00179 {
00180     QAction *action = new QAction(m_dateMenu);
00181     action->setText(text);
00182     action->setData(date);
00183     m_dateMenu->addAction(action);
00184     m_actions << action;
00185 }
00186 
00187 void KDateComboBoxPrivate::enableMenuDates()
00188 {
00189     // Hide menu dates if they are outside the date range
00190     for (int i = 0; i < m_actions.count(); ++i) {
00191         QDate date = m_actions[i]->data().toDate();
00192         m_actions[i]->setVisible(!date.isValid() || (date >= m_minDate && date <= m_maxDate));
00193     }
00194 }
00195 
00196 void KDateComboBoxPrivate::updateDateWidget()
00197 {
00198     q->blockSignals(true);
00199     m_datePicker->blockSignals(true);
00200     m_datePicker->setDate(m_date.date());
00201     int pos = q->lineEdit()->cursorPosition();
00202     q->setItemText(0, m_date.formatDate(m_displayFormat));
00203     q->lineEdit()->setText(m_date.formatDate(m_displayFormat));
00204     q->lineEdit()->setCursorPosition(pos);
00205     m_datePicker->blockSignals(false);
00206     q->blockSignals(false);
00207 }
00208 
00209 void KDateComboBoxPrivate::selectDate(QAction *action)
00210 {
00211     if (action->objectName() != QLatin1String("DatePicker")) {
00212         enterDate(action->data().toDate());
00213     }
00214 }
00215 
00216 void KDateComboBoxPrivate::clickDate()
00217 {
00218     enterDate(m_datePicker->date());
00219 }
00220 
00221 void KDateComboBoxPrivate::editDate(const QString &text)
00222 {
00223     m_warningShown = false;
00224     emit q->dateEdited(m_date.readDate(text).date());
00225 }
00226 
00227 void KDateComboBoxPrivate::parseDate()
00228 {
00229     m_date.setDate(m_date.readDate(q->lineEdit()->text()).date());
00230 }
00231 
00232 void KDateComboBoxPrivate::enterDate(const QDate &date)
00233 {
00234     q->setDate(date);
00235     // Re-add the combo box item in order to retain the correct widget width
00236     q->blockSignals(true);
00237     q->clear();
00238     q->setSizeAdjustPolicy(QComboBox::AdjustToContents);
00239     q->addItem(m_date.formatDate(m_displayFormat));
00240     q->setCurrentIndex(0);
00241     q->setSizeAdjustPolicy(QComboBox::AdjustToContentsOnFirstShow);
00242     q->blockSignals(false);
00243 
00244     m_dateMenu->hide();
00245     warnDate();
00246     emit q->dateEntered(m_date.date());
00247 }
00248 
00249 void KDateComboBoxPrivate::warnDate()
00250 {
00251     if (!m_warningShown && !q->isValid() &&
00252         (m_options &KDateComboBox::WarnOnInvalid) == KDateComboBox::WarnOnInvalid) {
00253         QString warnMsg;
00254         if (!m_date.date().isValid()) {
00255             warnMsg = i18nc("@info", "The date you entered is invalid");
00256         } else if (m_date.date() < m_minDate) {
00257             if (m_minWarnMsg.isEmpty()) {
00258                 warnMsg = i18nc("@info", "Date cannot be earlier than %1", formatDate(m_minDate));
00259             } else {
00260                 warnMsg = m_minWarnMsg;
00261                 warnMsg.replace("%1", formatDate(m_minDate));
00262             }
00263         } else if (m_date.date() > m_maxDate) {
00264             if (m_maxWarnMsg.isEmpty()) {
00265                 warnMsg = i18nc("@info", "Date cannot be later than %1", formatDate(m_maxDate));
00266             } else {
00267                 warnMsg = m_maxWarnMsg;
00268                 warnMsg.replace("%1", formatDate(m_maxDate));
00269             }
00270         }
00271         m_warningShown = true;
00272         KMessageBox::sorry(q, warnMsg);
00273     }
00274 }
00275 
00276 
00277 KDateComboBox::KDateComboBox(QWidget *parent)
00278               :KComboBox(parent),
00279                d(new KDateComboBoxPrivate(this))
00280 {
00281     setEditable(true);
00282     setMaxVisibleItems(1);
00283     setInsertPolicy(QComboBox::NoInsert);
00284     d->m_datePicker->installEventFilter(this);
00285     d->initDateWidget();
00286     d->updateDateWidget();
00287 
00288     connect(d->m_dateMenu,         SIGNAL(triggered(QAction*)),
00289             this,                  SLOT(selectDate(QAction*)));
00290     connect(this,                  SIGNAL(editTextChanged(QString)),
00291             this,                  SLOT(editDate(QString)));
00292     connect(d->m_datePicker,       SIGNAL(dateEntered(QDate)),
00293             this,                  SLOT(enterDate(QDate)));
00294     connect(d->m_datePicker,       SIGNAL(tableClicked()),
00295             this,                  SLOT(clickDate()));
00296 }
00297 
00298 KDateComboBox::~KDateComboBox()
00299 {
00300     delete d;
00301 }
00302 
00303 QDate KDateComboBox::date() const
00304 {
00305     d->parseDate();
00306     return d->m_date.date();
00307 }
00308 
00309 void KDateComboBox::setDate(const QDate &date)
00310 {
00311     if (date == d->m_date.date()) {
00312         return;
00313     }
00314 
00315     assignDate(date);
00316     d->updateDateWidget();
00317     emit dateChanged(d->m_date.date());
00318 }
00319 
00320 void KDateComboBox::assignDate(const QDate &date)
00321 {
00322     d->m_date = date;
00323 }
00324 
00325 KLocale::CalendarSystem KDateComboBox::calendarSystem() const
00326 {
00327     return d->m_date.calendarSystem();
00328 }
00329 
00330 void KDateComboBox::setCalendarSystem(KLocale::CalendarSystem calendarSystem)
00331 {
00332     if (calendarSystem != d->m_date.calendarSystem()) {
00333         assignCalendarSystem(calendarSystem);
00334     }
00335 }
00336 
00337 void KDateComboBox::assignCalendarSystem(KLocale::CalendarSystem calendarSystem)
00338 {
00339     d->m_date.setCalendarSystem(calendarSystem);
00340 }
00341 
00342 const KCalendarSystem *KDateComboBox::calendar() const
00343 {
00344     return d->m_date.calendar();
00345 }
00346 
00347 void KDateComboBox::setCalendar(KCalendarSystem *calendar)
00348 {
00349     d->m_date = KLocalizedDate(d->m_date.date(), calendar);
00350 }
00351 
00352 bool KDateComboBox::isValid() const
00353 {
00354     d->parseDate();
00355     return d->m_date.isValid() &&
00356            d->m_date >= d->m_minDate &&
00357            d->m_date <= d->m_maxDate;
00358 }
00359 
00360 bool KDateComboBox::isNull() const
00361 {
00362     return lineEdit()->text().isEmpty();
00363 }
00364 
00365 KDateComboBox::Options KDateComboBox::options() const
00366 {
00367     return d->m_options;
00368 }
00369 
00370 void KDateComboBox::setOptions(Options options)
00371 {
00372     if (options != d->m_options) {
00373         d->m_options = options;
00374         d->initDateWidget();
00375         d->updateDateWidget();
00376     }
00377 }
00378 
00379 QDate KDateComboBox::minimumDate() const
00380 {
00381     return d->m_minDate;
00382 }
00383 
00384 void KDateComboBox::setMinimumDate(const QDate &minDate, const QString &minWarnMsg)
00385 {
00386     setDateRange(minDate, d->m_maxDate, minWarnMsg, d->m_maxWarnMsg);
00387 }
00388 
00389 void KDateComboBox::resetMinimumDate()
00390 {
00391     setDateRange(d->defaultMinDate(), d->m_maxDate, QString(), d->m_maxWarnMsg);
00392 }
00393 
00394 QDate KDateComboBox::maximumDate() const
00395 {
00396     return d->m_maxDate;
00397 }
00398 
00399 void KDateComboBox::setMaximumDate(const QDate &maxDate, const QString &maxWarnMsg)
00400 {
00401     setDateRange(d->m_minDate, maxDate, d->m_minWarnMsg, maxWarnMsg);
00402 }
00403 
00404 void KDateComboBox::resetMaximumDate()
00405 {
00406     setDateRange(d->m_minDate, d->defaultMaxDate(), d->m_minWarnMsg, QString());
00407 }
00408 
00409 void KDateComboBox::setDateRange(const QDate &minDate,
00410                                  const QDate &maxDate,
00411                                  const QString &minWarnMsg,
00412                                  const QString &maxWarnMsg)
00413 {
00414     if (!minDate.isValid() || !maxDate.isValid() || minDate > maxDate) {
00415         return;
00416     }
00417 
00418     if (minDate != d->m_minDate || maxDate != d->m_maxDate ||
00419         minWarnMsg != d->m_minWarnMsg || maxWarnMsg != d->m_maxWarnMsg) {
00420         d->m_minDate = minDate;
00421         d->m_maxDate = maxDate;
00422         d->m_minWarnMsg = minWarnMsg;
00423         d->m_maxWarnMsg = maxWarnMsg;
00424     }
00425     d->enableMenuDates();
00426 }
00427 
00428 void KDateComboBox::resetDateRange()
00429 {
00430     setDateRange(d->defaultMinDate(), d->defaultMaxDate(), QString(), QString());
00431 }
00432 
00433 KLocale::DateFormat KDateComboBox::displayFormat() const
00434 {
00435     return d->m_displayFormat;
00436 }
00437 
00438 void KDateComboBox::setDisplayFormat(KLocale::DateFormat format)
00439 {
00440     if (format != d->m_displayFormat) {
00441         d->m_displayFormat = format;
00442         d->initDateWidget();
00443         d->updateDateWidget();
00444     }
00445 }
00446 
00447 QMap<QDate, QString> KDateComboBox::dateMap() const
00448 {
00449     return d->m_dateMap;
00450 }
00451 
00452 void KDateComboBox::setDateMap(QMap<QDate, QString> dateMap)
00453 {
00454     if (dateMap != d->m_dateMap) {
00455         d->m_dateMap.clear();
00456         d->m_dateMap = dateMap;
00457         d->initDateWidget();
00458     }
00459 }
00460 
00461 bool KDateComboBox::eventFilter(QObject *object, QEvent *event)
00462 {
00463     return KComboBox::eventFilter(object, event);
00464 }
00465 
00466 void KDateComboBox::keyPressEvent(QKeyEvent *keyEvent)
00467 {
00468     QDate temp;
00469     switch (keyEvent->key()) {
00470     case Qt::Key_Down:
00471         temp = d->m_date.addDays(-1).date();
00472         break;
00473     case Qt::Key_Up:
00474         temp = d->m_date.addDays(1).date();
00475         break;
00476     case Qt::Key_PageDown:
00477         temp = d->m_date.addMonths(-1).date();
00478         break;
00479     case Qt::Key_PageUp:
00480         temp = d->m_date.addMonths(1).date();
00481         break;
00482     default:
00483         KComboBox::keyPressEvent(keyEvent);
00484         return;
00485     }
00486     if (temp.isValid() && temp >= d->m_minDate && temp <= d->m_maxDate) {
00487         d->enterDate(temp);
00488     }
00489 }
00490 
00491 void KDateComboBox::focusOutEvent(QFocusEvent *event)
00492 {
00493     d->parseDate();
00494     d->warnDate();
00495     KComboBox::focusOutEvent(event);
00496 }
00497 
00498 void KDateComboBox::showPopup()
00499 {
00500     if (!isEditable() ||
00501         !d->m_dateMenu ||
00502         (d->m_options &KDateComboBox::SelectDate) != KDateComboBox::SelectDate) {
00503         return;
00504     }
00505 
00506     d->m_datePicker->blockSignals(true);
00507     d->m_datePicker->setDate(d->m_date.date());
00508     d->m_datePicker->blockSignals(false);
00509 
00510     const QRect desk = KGlobalSettings::desktopGeometry(this);
00511 
00512     QPoint popupPoint = mapToGlobal(QPoint(0, 0));
00513 
00514     const int dateFrameHeight = d->m_dateMenu->sizeHint().height();
00515     if (popupPoint.y() + height() + dateFrameHeight > desk.bottom()) {
00516         popupPoint.setY(popupPoint.y() - dateFrameHeight);
00517     } else {
00518         popupPoint.setY(popupPoint.y() + height());
00519     }
00520 
00521     const int dateFrameWidth = d->m_dateMenu->sizeHint().width();
00522     if (popupPoint.x() + dateFrameWidth > desk.right()) {
00523         popupPoint.setX(desk.right() - dateFrameWidth);
00524     }
00525 
00526     if (popupPoint.x() < desk.left()) {
00527         popupPoint.setX(desk.left());
00528     }
00529 
00530     if (popupPoint.y() < desk.top()) {
00531         popupPoint.setY(desk.top());
00532     }
00533 
00534     d->m_dateMenu->popup(popupPoint);
00535 }
00536 
00537 void KDateComboBox::hidePopup()
00538 {
00539     KComboBox::hidePopup();
00540 }
00541 
00542 void KDateComboBox::mousePressEvent(QMouseEvent *event)
00543 {
00544     KComboBox::mousePressEvent(event);
00545 }
00546 
00547 void KDateComboBox::wheelEvent(QWheelEvent *event)
00548 {
00549     KComboBox::wheelEvent(event);
00550 }
00551 
00552 void KDateComboBox::focusInEvent(QFocusEvent *event)
00553 {
00554     KComboBox::focusInEvent(event);
00555 }
00556 
00557 void KDateComboBox::resizeEvent(QResizeEvent *event)
00558 {
00559     KComboBox::resizeEvent(event);
00560 }
00561 
00562 #include "kdatecombobox.moc"
This file is part of the KDE documentation.
Documentation copyright © 1996-2012 The KDE developers.
Generated on Thu May 10 2012 20:53:02 by doxygen 1.8.0 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.8.3 API Reference

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