File indexing completed on 2024-04-14 14:20:18

0001 /*  This file is part of the KDE libraries
0002     Copyright (C) 2001 Waldo Bastian (bastian@kde.org)
0003     Copyright 2007, 2010 John Layt <john@layt.net>
0004 
0005     This library is free software; you can redistribute it and/or
0006     modify it under the terms of the GNU Library General Public
0007     License version 2 as published by the Free Software Foundation.
0008 
0009     This library is distributed in the hope that it will be useful,
0010     but WITHOUT ANY WARRANTY; without even the implied warranty of
0011     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0012     Library General Public License for more details.
0013 
0014     You should have received a copy of the GNU Library General Public License
0015     along with this library; see the file COPYING.LIB.  If not, write to
0016     the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0017     Boston, MA 02110-1301, USA.
0018 */
0019 
0020 #include "kdatewidget.h"
0021 
0022 #include <QDate>
0023 #include <QLayout>
0024 #include <QLineEdit>
0025 #include <QDoubleSpinBox>
0026 
0027 #include <kcombobox.h>
0028 
0029 #include "kcalendarsystem.h"
0030 #include "klocalizeddate.h"
0031 
0032 class KDateWidgetSpinBox : public QSpinBox
0033 {
0034 public:
0035     KDateWidgetSpinBox(int min, int max, QWidget *parent) : QSpinBox(parent)
0036     {
0037         setRange(qMin(min, max), qMax(min, max));
0038         setSingleStep(1);
0039         lineEdit()->setAlignment(Qt::AlignRight);
0040     }
0041 };
0042 
0043 class Q_DECL_HIDDEN KDateWidget::KDateWidgetPrivate
0044 {
0045 public:
0046     KDateWidgetSpinBox *m_day;
0047     KComboBox *m_month;
0048     KDateWidgetSpinBox *m_year;
0049     KLocalizedDate m_date;
0050     // Need to keep a QDate copy as the "const QDate &date() const;" method returns a reference
0051     // and returning m_date.date() creates a temporary leading to crashes.  Doh!
0052     QDate m_refDate;
0053 };
0054 
0055 KDateWidget::KDateWidget(QWidget *parent) : QWidget(parent), d(new KDateWidgetPrivate)
0056 {
0057     initWidget(QDate::currentDate());
0058 }
0059 
0060 KDateWidget::KDateWidget(const QDate &date, QWidget *parent)
0061     : QWidget(parent), d(new KDateWidgetPrivate)
0062 {
0063     initWidget(date);
0064 }
0065 
0066 void KDateWidget::initWidget(const QDate &date)
0067 {
0068     QHBoxLayout *layout = new QHBoxLayout(this);
0069     layout->setContentsMargins(0, 0, 0, 0);
0070     const int spacingHint = style()->pixelMetric(QStyle::PM_DefaultLayoutSpacing);
0071     layout->setSpacing(spacingHint);
0072 
0073     d->m_day = new KDateWidgetSpinBox(1, 31, this);
0074     d->m_month = new KComboBox(this);
0075     d->m_year = new KDateWidgetSpinBox(calendar()->year(calendar()->earliestValidDate()),
0076                                        calendar()->year(calendar()->latestValidDate()), this);
0077 
0078     layout->addWidget(d->m_day);
0079     layout->addWidget(d->m_month);
0080     layout->addWidget(d->m_year);
0081 
0082     connect(d->m_day, SIGNAL(valueChanged(int)), this, SLOT(slotDateChanged()));
0083     connect(d->m_month, SIGNAL(activated(int)), this, SLOT(slotDateChanged()));
0084     connect(d->m_year, SIGNAL(valueChanged(int)), this, SLOT(slotDateChanged()));
0085 
0086     setFocusProxy(d->m_day);
0087     setFocusPolicy(Qt::StrongFocus);
0088 
0089     if (calendar()->isValid(date)) {
0090         setDate(date);
0091     } else {
0092         setDate(QDate::currentDate());
0093     }
0094 }
0095 
0096 KDateWidget::~KDateWidget()
0097 {
0098     delete d;
0099 }
0100 
0101 bool KDateWidget::setDate(const QDate &date)
0102 {
0103     if (calendar()->isValid(date)) {
0104         bool dayBlocked = d->m_day->blockSignals(true);
0105         bool monthBlocked = d->m_month->blockSignals(true);
0106         bool yearBlocked = d->m_year->blockSignals(true);
0107 
0108         d->m_date.setDate(date);
0109         d->m_refDate = date;
0110 
0111         d->m_day->setMaximum(d->m_date.daysInMonth());
0112         d->m_day->setValue(d->m_date.day());
0113 
0114         d->m_month->clear();
0115         d->m_month->setMaxVisibleItems(d->m_date.monthsInYear());
0116         for (int m = 1; m <= d->m_date.monthsInYear(); ++m) {
0117             d->m_month->addItem(calendar()->monthName(m, d->m_date.year()));
0118         }
0119         d->m_month->setCurrentIndex(d->m_date.month() - 1);
0120 
0121         d->m_year->setValue(d->m_date.year());
0122 
0123         d->m_day->blockSignals(dayBlocked);
0124         d->m_month->blockSignals(monthBlocked);
0125         d->m_year->blockSignals(yearBlocked);
0126 
0127         emit changed(d->m_refDate);
0128         return true;
0129     }
0130     return false;
0131 }
0132 
0133 const QDate &KDateWidget::date() const
0134 {
0135     return d->m_refDate;
0136 }
0137 
0138 void KDateWidget::slotDateChanged()
0139 {
0140     KLocalizedDate date;
0141     int y, m, day;
0142 
0143     y = d->m_year->value();
0144     y = qMin(qMax(y, calendar()->year(calendar()->earliestValidDate())),
0145              calendar()->year(calendar()->latestValidDate()));
0146 
0147     date.setDate(y, 1, 1);
0148     m = d->m_month->currentIndex() + 1;
0149     m = qMin(qMax(m, 1), date.monthsInYear());
0150 
0151     date.setDate(y, m, 1);
0152     day = d->m_day->value();
0153     day = qMin(qMax(day, 1), date.daysInMonth());
0154 
0155     date.setDate(y, m, day);
0156     setDate(date.date());
0157 }
0158 
0159 const KCalendarSystem *KDateWidget::calendar() const
0160 {
0161     return  d->m_date.calendar();
0162 }
0163 
0164 bool KDateWidget::setCalendar(KCalendarSystem *newCalendar)
0165 {
0166     QDate oldDate = date();
0167     d->m_date = KLocalizedDate(oldDate, newCalendar);
0168     return setDate(oldDate);
0169 }
0170 
0171 bool KDateWidget::setCalendarSystem(KLocale::CalendarSystem newCalendarSystem)
0172 {
0173     d->m_date.setCalendarSystem(newCalendarSystem);
0174     return true;
0175 }
0176 
0177 #include "moc_kdatewidget.cpp"