summaryrefslogtreecommitdiffstats
path: root/src/gui/widgets/qcalendarwidget.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/gui/widgets/qcalendarwidget.cpp')
-rw-r--r--src/gui/widgets/qcalendarwidget.cpp3104
1 files changed, 3104 insertions, 0 deletions
diff --git a/src/gui/widgets/qcalendarwidget.cpp b/src/gui/widgets/qcalendarwidget.cpp
new file mode 100644
index 0000000000..d6a6f14e3f
--- /dev/null
+++ b/src/gui/widgets/qcalendarwidget.cpp
@@ -0,0 +1,3104 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qcalendarwidget.h"
+
+#ifndef QT_NO_CALENDARWIDGET
+
+#include <qabstractitemmodel.h>
+#include <qitemdelegate.h>
+#include <qdatetime.h>
+#include <qtableview.h>
+#include <qlayout.h>
+#include <qevent.h>
+#include <qtextformat.h>
+#include <qheaderview.h>
+#include <private/qwidget_p.h>
+#include <qpushbutton.h>
+#include <qtoolbutton.h>
+#include <qlabel.h>
+#include <qspinbox.h>
+#include <qmenu.h>
+#include <qapplication.h>
+#include <qbasictimer.h>
+#include <qstylepainter.h>
+#include <private/qcalendartextnavigator_p.h>
+
+QT_BEGIN_NAMESPACE
+
+enum {
+ RowCount = 6,
+ ColumnCount = 7,
+ HeaderColumn = 0,
+ HeaderRow = 0,
+ MinimumDayOffset = 1
+};
+
+class QCalendarDateSectionValidator
+{
+public:
+
+ enum Section {
+ NextSection,
+ ThisSection,
+ PrevSection
+ };
+
+ QCalendarDateSectionValidator() {}
+ virtual ~QCalendarDateSectionValidator() {}
+ virtual Section handleKey(int key) = 0;
+ virtual QDate applyToDate(const QDate &date) const = 0;
+ virtual void setDate(const QDate &date) = 0;
+ virtual QString text() const = 0;
+ virtual QString text(const QDate &date, int repeat) const = 0;
+
+ QLocale m_locale;
+
+protected:
+ QString highlightString(const QString &str, int pos) const;
+private:
+};
+
+QString QCalendarDateSectionValidator::highlightString(const QString &str, int pos) const
+{
+ if (pos == 0)
+ return QLatin1String("<b>") + str + QLatin1String("</b>");
+ int startPos = str.length() - pos;
+ return str.mid(0, startPos) + QLatin1String("<b>") + str.mid(startPos, pos) + QLatin1String("</b>");
+
+}
+
+class QCalendarDayValidator : public QCalendarDateSectionValidator
+{
+
+public:
+ QCalendarDayValidator();
+ virtual Section handleKey(int key);
+ virtual QDate applyToDate(const QDate &date) const;
+ virtual void setDate(const QDate &date);
+ virtual QString text() const;
+ virtual QString text(const QDate &date, int repeat) const;
+private:
+ int m_pos;
+ int m_day;
+ int m_oldDay;
+};
+
+QCalendarDayValidator::QCalendarDayValidator()
+ : QCalendarDateSectionValidator(), m_pos(0), m_day(1), m_oldDay(1)
+{
+}
+
+QCalendarDateSectionValidator::Section QCalendarDayValidator::handleKey(int key)
+{
+ if (key == Qt::Key_Right || key == Qt::Key_Left) {
+ m_pos = 0;
+ return QCalendarDateSectionValidator::ThisSection;
+ } else if (key == Qt::Key_Up) {
+ m_pos = 0;
+ ++m_day;
+ if (m_day > 31)
+ m_day = 1;
+ return QCalendarDateSectionValidator::ThisSection;
+ } else if (key == Qt::Key_Down) {
+ m_pos = 0;
+ --m_day;
+ if (m_day < 1)
+ m_day = 31;
+ return QCalendarDateSectionValidator::ThisSection;
+ } else if (key == Qt::Key_Back || key == Qt::Key_Backspace) {
+ --m_pos;
+ if (m_pos < 0)
+ m_pos = 1;
+
+ if (m_pos == 0)
+ m_day = m_oldDay;
+ else
+ m_day = m_day / 10;
+ //m_day = m_oldDay / 10 * 10 + m_day / 10;
+
+ if (m_pos == 0)
+ return QCalendarDateSectionValidator::PrevSection;
+ return QCalendarDateSectionValidator::ThisSection;
+ }
+ if (key < Qt::Key_0 || key > Qt::Key_9)
+ return QCalendarDateSectionValidator::ThisSection;
+ int pressedKey = key - Qt::Key_0;
+ if (m_pos == 0)
+ m_day = pressedKey;
+ else
+ m_day = m_day % 10 * 10 + pressedKey;
+ if (m_day > 31)
+ m_day = 31;
+ ++m_pos;
+ if (m_pos > 1) {
+ m_pos = 0;
+ return QCalendarDateSectionValidator::NextSection;
+ }
+ return QCalendarDateSectionValidator::ThisSection;
+}
+
+QDate QCalendarDayValidator::applyToDate(const QDate &date) const
+{
+ int day = m_day;
+ if (day < 1)
+ day = 1;
+ else if (day > 31)
+ day = 31;
+ if (day > date.daysInMonth())
+ day = date.daysInMonth();
+ return QDate(date.year(), date.month(), day);
+}
+
+void QCalendarDayValidator::setDate(const QDate &date)
+{
+ m_day = m_oldDay = date.day();
+ m_pos = 0;
+}
+
+QString QCalendarDayValidator::text() const
+{
+ QString str;
+ if (m_day / 10 == 0)
+ str += QLatin1Char('0');
+ str += QString::number(m_day);
+ return highlightString(str, m_pos);
+}
+
+QString QCalendarDayValidator::text(const QDate &date, int repeat) const
+{
+ if (repeat <= 1) {
+ return QString::number(date.day());
+ } else if (repeat == 2) {
+ QString str;
+ if (date.day() / 10 == 0)
+ str += QLatin1Char('0');
+ return str + QString::number(date.day());
+ } else if (repeat == 3) {
+ return m_locale.dayName(date.dayOfWeek(), QLocale::ShortFormat);
+ } else if (repeat >= 4) {
+ return m_locale.dayName(date.dayOfWeek(), QLocale::LongFormat);
+ }
+ return QString();
+}
+
+//////////////////////////////////
+
+class QCalendarMonthValidator : public QCalendarDateSectionValidator
+{
+
+public:
+ QCalendarMonthValidator();
+ virtual Section handleKey(int key);
+ virtual QDate applyToDate(const QDate &date) const;
+ virtual void setDate(const QDate &date);
+ virtual QString text() const;
+ virtual QString text(const QDate &date, int repeat) const;
+private:
+ int m_pos;
+ int m_month;
+ int m_oldMonth;
+};
+
+QCalendarMonthValidator::QCalendarMonthValidator()
+ : QCalendarDateSectionValidator(), m_pos(0), m_month(1), m_oldMonth(1)
+{
+}
+
+QCalendarDateSectionValidator::Section QCalendarMonthValidator::handleKey(int key)
+{
+ if (key == Qt::Key_Right || key == Qt::Key_Left) {
+ m_pos = 0;
+ return QCalendarDateSectionValidator::ThisSection;
+ } else if (key == Qt::Key_Up) {
+ m_pos = 0;
+ ++m_month;
+ if (m_month > 12)
+ m_month = 1;
+ return QCalendarDateSectionValidator::ThisSection;
+ } else if (key == Qt::Key_Down) {
+ m_pos = 0;
+ --m_month;
+ if (m_month < 1)
+ m_month = 12;
+ return QCalendarDateSectionValidator::ThisSection;
+ } else if (key == Qt::Key_Back || key == Qt::Key_Backspace) {
+ --m_pos;
+ if (m_pos < 0)
+ m_pos = 1;
+
+ if (m_pos == 0)
+ m_month = m_oldMonth;
+ else
+ m_month = m_month / 10;
+ //m_month = m_oldMonth / 10 * 10 + m_month / 10;
+
+ if (m_pos == 0)
+ return QCalendarDateSectionValidator::PrevSection;
+ return QCalendarDateSectionValidator::ThisSection;
+ }
+ if (key < Qt::Key_0 || key > Qt::Key_9)
+ return QCalendarDateSectionValidator::ThisSection;
+ int pressedKey = key - Qt::Key_0;
+ if (m_pos == 0)
+ m_month = pressedKey;
+ else
+ m_month = m_month % 10 * 10 + pressedKey;
+ if (m_month > 12)
+ m_month = 12;
+ ++m_pos;
+ if (m_pos > 1) {
+ m_pos = 0;
+ return QCalendarDateSectionValidator::NextSection;
+ }
+ return QCalendarDateSectionValidator::ThisSection;
+}
+
+QDate QCalendarMonthValidator::applyToDate(const QDate &date) const
+{
+ int month = m_month;
+ if (month < 1)
+ month = 1;
+ else if (month > 12)
+ month = 12;
+ QDate newDate(date.year(), m_month, 1);
+ int day = date.day();
+ if (day > newDate.daysInMonth())
+ day = newDate.daysInMonth();
+ return QDate(date.year(), month, day);
+}
+
+void QCalendarMonthValidator::setDate(const QDate &date)
+{
+ m_month = m_oldMonth = date.month();
+ m_pos = 0;
+}
+
+QString QCalendarMonthValidator::text() const
+{
+ QString str;
+ if (m_month / 10 == 0)
+ str += QLatin1Char('0');
+ str += QString::number(m_month);
+ return highlightString(str, m_pos);
+}
+
+QString QCalendarMonthValidator::text(const QDate &date, int repeat) const
+{
+ if (repeat <= 1) {
+ return QString::number(date.month());
+ } else if (repeat == 2) {
+ QString str;
+ if (date.month() / 10 == 0)
+ str += QLatin1Char('0');
+ return str + QString::number(date.month());
+ } else if (repeat == 3) {
+ return m_locale.standaloneMonthName(date.month(), QLocale::ShortFormat);
+ } else /*if (repeat >= 4)*/ {
+ return m_locale.standaloneMonthName(date.month(), QLocale::LongFormat);
+ }
+}
+
+//////////////////////////////////
+
+class QCalendarYearValidator : public QCalendarDateSectionValidator
+{
+
+public:
+ QCalendarYearValidator();
+ virtual Section handleKey(int key);
+ virtual QDate applyToDate(const QDate &date) const;
+ virtual void setDate(const QDate &date);
+ virtual QString text() const;
+ virtual QString text(const QDate &date, int repeat) const;
+private:
+ int pow10(int n);
+ int m_pos;
+ int m_year;
+ int m_oldYear;
+};
+
+QCalendarYearValidator::QCalendarYearValidator()
+ : QCalendarDateSectionValidator(), m_pos(0), m_year(2000), m_oldYear(2000)
+{
+}
+
+int QCalendarYearValidator::pow10(int n)
+{
+ int power = 1;
+ for (int i = 0; i < n; i++)
+ power *= 10;
+ return power;
+}
+
+QCalendarDateSectionValidator::Section QCalendarYearValidator::handleKey(int key)
+{
+ if (key == Qt::Key_Right || key == Qt::Key_Left) {
+ m_pos = 0;
+ return QCalendarDateSectionValidator::ThisSection;
+ } else if (key == Qt::Key_Up) {
+ m_pos = 0;
+ ++m_year;
+ return QCalendarDateSectionValidator::ThisSection;
+ } else if (key == Qt::Key_Down) {
+ m_pos = 0;
+ --m_year;
+ return QCalendarDateSectionValidator::ThisSection;
+ } else if (key == Qt::Key_Back || key == Qt::Key_Backspace) {
+ --m_pos;
+ if (m_pos < 0)
+ m_pos = 3;
+
+ int pow = pow10(m_pos);
+ m_year = m_oldYear / pow * pow + m_year % (pow * 10) / 10;
+
+ if (m_pos == 0)
+ return QCalendarDateSectionValidator::PrevSection;
+ return QCalendarDateSectionValidator::ThisSection;
+ }
+ if (key < Qt::Key_0 || key > Qt::Key_9)
+ return QCalendarDateSectionValidator::ThisSection;
+ int pressedKey = key - Qt::Key_0;
+ int pow = pow10(m_pos);
+ m_year = m_year / (pow * 10) * (pow * 10) + m_year % pow * 10 + pressedKey;
+ ++m_pos;
+ if (m_pos > 3) {
+ m_pos = 0;
+ return QCalendarDateSectionValidator::NextSection;
+ }
+ return QCalendarDateSectionValidator::ThisSection;
+}
+
+QDate QCalendarYearValidator::applyToDate(const QDate &date) const
+{
+ int year = m_year;
+ if (year < 1)
+ year = 1;
+ QDate newDate(year, date.month(), 1);
+ int day = date.day();
+ if (day > newDate.daysInMonth())
+ day = newDate.daysInMonth();
+ return QDate(year, date.month(), day);
+}
+
+void QCalendarYearValidator::setDate(const QDate &date)
+{
+ m_year = m_oldYear = date.year();
+ m_pos = 0;
+}
+
+QString QCalendarYearValidator::text() const
+{
+ QString str;
+ int pow = 10;
+ for (int i = 0; i < 3; i++) {
+ if (m_year / pow == 0)
+ str += QLatin1Char('0');
+ pow *= 10;
+ }
+ str += QString::number(m_year);
+ return highlightString(str, m_pos);
+}
+
+QString QCalendarYearValidator::text(const QDate &date, int repeat) const
+{
+ if (repeat < 4) {
+ QString str;
+ int year = date.year() % 100;
+ if (year / 10 == 0)
+ str = QLatin1Char('0');
+ return str + QString::number(year);
+ }
+ return QString::number(date.year());
+}
+
+///////////////////////////////////
+
+class QCalendarDateValidator
+{
+public:
+ QCalendarDateValidator();
+ ~QCalendarDateValidator();
+
+ void handleKeyEvent(QKeyEvent *keyEvent);
+ QString currentText() const;
+ QDate currentDate() const { return m_currentDate; }
+ void setFormat(const QString &format);
+ void setInitialDate(const QDate &date);
+
+ void setLocale(const QLocale &locale);
+
+private:
+
+ struct SectionToken {
+ SectionToken(QCalendarDateSectionValidator *val, int rep) : validator(val), repeat(rep) {}
+ QCalendarDateSectionValidator *validator;
+ int repeat;
+ };
+
+ void toNextToken();
+ void toPreviousToken();
+ void applyToDate();
+
+ int countRepeat(const QString &str, int index) const;
+ void clear();
+
+ QStringList m_separators;
+ QList<SectionToken *> m_tokens;
+ QCalendarDateSectionValidator *m_yearValidator;
+ QCalendarDateSectionValidator *m_monthValidator;
+ QCalendarDateSectionValidator *m_dayValidator;
+
+ SectionToken *m_currentToken;
+
+ QDate m_initialDate;
+ QDate m_currentDate;
+
+ QCalendarDateSectionValidator::Section m_lastSectionMove;
+};
+
+QCalendarDateValidator::QCalendarDateValidator()
+ : m_currentToken(0), m_lastSectionMove(QCalendarDateSectionValidator::ThisSection)
+{
+ m_initialDate = m_currentDate = QDate::currentDate();
+ m_yearValidator = new QCalendarYearValidator();
+ m_monthValidator = new QCalendarMonthValidator();
+ m_dayValidator = new QCalendarDayValidator();
+}
+
+void QCalendarDateValidator::setLocale(const QLocale &locale)
+{
+ m_yearValidator->m_locale = locale;
+ m_monthValidator->m_locale = locale;
+ m_dayValidator->m_locale = locale;
+}
+
+QCalendarDateValidator::~QCalendarDateValidator()
+{
+ delete m_yearValidator;
+ delete m_monthValidator;
+ delete m_dayValidator;
+ clear();
+}
+
+// from qdatetime.cpp
+int QCalendarDateValidator::countRepeat(const QString &str, int index) const
+{
+ Q_ASSERT(index >= 0 && index < str.size());
+ int count = 1;
+ const QChar ch = str.at(index);
+ while (index + count < str.size() && str.at(index + count) == ch)
+ ++count;
+ return count;
+}
+
+void QCalendarDateValidator::setInitialDate(const QDate &date)
+{
+ m_yearValidator->setDate(date);
+ m_monthValidator->setDate(date);
+ m_dayValidator->setDate(date);
+ m_initialDate = date;
+ m_currentDate = date;
+ m_lastSectionMove = QCalendarDateSectionValidator::ThisSection;
+}
+
+QString QCalendarDateValidator::currentText() const
+{
+ QString str;
+ QStringListIterator itSep(m_separators);
+ QListIterator<SectionToken *> itTok(m_tokens);
+ while (itSep.hasNext()) {
+ str += itSep.next();
+ if (itTok.hasNext()) {
+ SectionToken *token = itTok.next();
+ QCalendarDateSectionValidator *validator = token->validator;
+ if (m_currentToken == token)
+ str += validator->text();
+ else
+ str += validator->text(m_currentDate, token->repeat);
+ }
+ }
+ return str;
+}
+
+void QCalendarDateValidator::clear()
+{
+ QListIterator<SectionToken *> it(m_tokens);
+ while (it.hasNext())
+ delete it.next();
+
+ m_tokens.clear();
+ m_separators.clear();
+
+ m_currentToken = 0;
+}
+
+void QCalendarDateValidator::setFormat(const QString &format)
+{
+ clear();
+
+ int pos = 0;
+ const QLatin1Char quote('\'');
+ bool quoting = false;
+ QString separator;
+ while (pos < format.size()) {
+ QString mid = format.mid(pos);
+ int offset = 1;
+
+ if (mid.startsWith(quote)) {
+ quoting = !quoting;
+ } else {
+ const QChar nextChar = format.at(pos);
+ if (quoting) {
+ separator += nextChar;
+ } else {
+ SectionToken *token = 0;
+ if (nextChar == QLatin1Char('d')) {
+ offset = qMin(4, countRepeat(format, pos));
+ token = new SectionToken(m_dayValidator, offset);
+ } else if (nextChar == QLatin1Char('M')) {
+ offset = qMin(4, countRepeat(format, pos));
+ token = new SectionToken(m_monthValidator, offset);
+ } else if (nextChar == QLatin1Char('y')) {
+ offset = qMin(4, countRepeat(format, pos));
+ token = new SectionToken(m_yearValidator, offset);
+ } else {
+ separator += nextChar;
+ }
+ if (token) {
+ m_tokens.append(token);
+ m_separators.append(separator);
+ separator = QString();
+ if (!m_currentToken)
+ m_currentToken = token;
+
+ }
+ }
+ }
+ pos += offset;
+ }
+ m_separators += separator;
+}
+
+void QCalendarDateValidator::applyToDate()
+{
+ m_currentDate = m_yearValidator->applyToDate(m_currentDate);
+ m_currentDate = m_monthValidator->applyToDate(m_currentDate);
+ m_currentDate = m_dayValidator->applyToDate(m_currentDate);
+}
+
+void QCalendarDateValidator::toNextToken()
+{
+ const int idx = m_tokens.indexOf(m_currentToken);
+ if (idx == -1)
+ return;
+ if (idx + 1 >= m_tokens.count())
+ m_currentToken = m_tokens.first();
+ else
+ m_currentToken = m_tokens.at(idx + 1);
+}
+
+void QCalendarDateValidator::toPreviousToken()
+{
+ const int idx = m_tokens.indexOf(m_currentToken);
+ if (idx == -1)
+ return;
+ if (idx - 1 < 0)
+ m_currentToken = m_tokens.last();
+ else
+ m_currentToken = m_tokens.at(idx - 1);
+}
+
+void QCalendarDateValidator::handleKeyEvent(QKeyEvent *keyEvent)
+{
+ if (!m_currentToken)
+ return;
+
+ int key = keyEvent->key();
+ if (m_lastSectionMove == QCalendarDateSectionValidator::NextSection) {
+ if (key == Qt::Key_Back || key == Qt::Key_Backspace)
+ toPreviousToken();
+ }
+ if (key == Qt::Key_Right)
+ toNextToken();
+ else if (key == Qt::Key_Left)
+ toPreviousToken();
+
+ m_lastSectionMove = m_currentToken->validator->handleKey(key);
+
+ applyToDate();
+ if (m_lastSectionMove == QCalendarDateSectionValidator::NextSection)
+ toNextToken();
+ else if (m_lastSectionMove == QCalendarDateSectionValidator::PrevSection)
+ toPreviousToken();
+}
+
+QWidget *QCalendarTextNavigator::widget() const
+{
+ return m_widget;
+}
+
+void QCalendarTextNavigator::setWidget(QWidget *widget)
+{
+ m_widget = widget;
+}
+
+QDate QCalendarTextNavigator::date() const
+{
+ return m_date;
+}
+
+void QCalendarTextNavigator::setDate(const QDate &date)
+{
+ m_date = date;
+}
+
+void QCalendarTextNavigator::updateDateLabel()
+{
+ if (!m_widget)
+ return;
+
+ m_acceptTimer.start(m_editDelay, this);
+
+ m_dateText->setText(m_dateValidator->currentText());
+
+ QSize s = m_dateFrame->sizeHint();
+ QRect r = m_widget->geometry(); // later, just the table section
+ QRect newRect((r.width() - s.width()) / 2, (r.height() - s.height()) / 2, s.width(), s.height());
+ m_dateFrame->setGeometry(newRect);
+ // need to set palette after geometry update as phonestyle sets transparency
+ // effect in move event.
+ QPalette p = m_dateFrame->palette();
+ p.setBrush(QPalette::Window, m_dateFrame->window()->palette().brush(QPalette::Window));
+ m_dateFrame->setPalette(p);
+
+ m_dateFrame->raise();
+ m_dateFrame->show();
+}
+
+void QCalendarTextNavigator::applyDate()
+{
+ QDate date = m_dateValidator->currentDate();
+ if (m_date == date)
+ return;
+
+ m_date = date;
+ emit dateChanged(date);
+}
+
+void QCalendarTextNavigator::createDateLabel()
+{
+ if (m_dateFrame)
+ return;
+ m_dateFrame = new QFrame(m_widget);
+ QVBoxLayout *vl = new QVBoxLayout;
+ m_dateText = new QLabel;
+ vl->addWidget(m_dateText);
+ m_dateFrame->setLayout(vl);
+ m_dateFrame->setFrameShadow(QFrame::Plain);
+ m_dateFrame->setFrameShape(QFrame::Box);
+ m_dateValidator = new QCalendarDateValidator();
+ m_dateValidator->setLocale(m_widget->locale());
+ m_dateValidator->setFormat(m_widget->locale().dateFormat(QLocale::ShortFormat));
+ m_dateValidator->setInitialDate(m_date);
+
+ m_dateFrame->setAutoFillBackground(true);
+ m_dateFrame->setBackgroundRole(QPalette::Window);
+}
+
+void QCalendarTextNavigator::removeDateLabel()
+{
+ if (!m_dateFrame)
+ return;
+ m_acceptTimer.stop();
+ m_dateFrame->hide();
+ m_dateFrame->deleteLater();
+ delete m_dateValidator;
+ m_dateFrame = 0;
+ m_dateText = 0;
+ m_dateValidator = 0;
+}
+
+bool QCalendarTextNavigator::eventFilter(QObject *o, QEvent *e)
+{
+ if (m_widget) {
+ if (e->type() == QEvent::KeyPress || e->type() == QEvent::KeyRelease) {
+ QKeyEvent* ke = (QKeyEvent*)e;
+ if ((ke->text().length() > 0 && ke->text()[0].isPrint()) || m_dateFrame) {
+ if (ke->key() == Qt::Key_Return || ke->key() == Qt::Key_Enter || ke->key() == Qt::Key_Select) {
+ applyDate();
+ emit editingFinished();
+ removeDateLabel();
+ } else if (ke->key() == Qt::Key_Escape) {
+ removeDateLabel();
+ } else if (e->type() == QEvent::KeyPress) {
+ createDateLabel();
+ m_dateValidator->handleKeyEvent(ke);
+ updateDateLabel();
+ }
+ ke->accept();
+ return true;
+ }
+ // If we are navigating let the user finish his date in old locate.
+ // If we change our mind and want it to update immediately simply uncomment below
+ /*
+ } else if (e->type() == QEvent::LocaleChange) {
+ if (m_dateValidator) {
+ m_dateValidator->setLocale(m_widget->locale());
+ m_dateValidator->setFormat(m_widget->locale().dateFormat(QLocale::ShortFormat));
+ updateDateLabel();
+ }
+ */
+ }
+ }
+ return QObject::eventFilter(o,e);
+}
+
+void QCalendarTextNavigator::timerEvent(QTimerEvent *e)
+{
+ if (e->timerId() == m_acceptTimer.timerId()) {
+ applyDate();
+ removeDateLabel();
+ }
+}
+
+int QCalendarTextNavigator::dateEditAcceptDelay() const
+{
+ return m_editDelay;
+}
+
+void QCalendarTextNavigator::setDateEditAcceptDelay(int delay)
+{
+ m_editDelay = delay;
+}
+
+class QCalendarView;
+
+class QCalendarModel : public QAbstractTableModel
+{
+ Q_OBJECT
+public:
+ QCalendarModel(QObject *parent = 0);
+
+ int rowCount(const QModelIndex &) const
+ { return RowCount + m_firstRow; }
+ int columnCount(const QModelIndex &) const
+ { return ColumnCount + m_firstColumn; }
+ QVariant data(const QModelIndex &index, int role) const;
+ Qt::ItemFlags flags(const QModelIndex &index) const;
+
+ bool insertRows(int row, int count, const QModelIndex &parent = QModelIndex())
+ {
+ beginInsertRows(parent, row, row + count - 1);
+ endInsertRows();
+ return true;
+ }
+ bool insertColumns(int column, int count, const QModelIndex &parent = QModelIndex())
+ {
+ beginInsertColumns(parent, column, column + count - 1);
+ endInsertColumns();
+ return true;
+ }
+ bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex())
+ {
+ beginRemoveRows(parent, row, row + count - 1);
+ endRemoveRows();
+ return true;
+ }
+ bool removeColumns(int column, int count, const QModelIndex &parent = QModelIndex())
+ {
+ beginRemoveColumns(parent, column, column + count - 1);
+ endRemoveColumns();
+ return true;
+ }
+
+ void showMonth(int year, int month);
+ void setDate(const QDate &d);
+
+ void setMinimumDate(const QDate &date);
+ void setMaximumDate(const QDate &date);
+
+ void setRange(const QDate &min, const QDate &max);
+
+ void setHorizontalHeaderFormat(QCalendarWidget::HorizontalHeaderFormat format);
+
+ void setFirstColumnDay(Qt::DayOfWeek dayOfWeek);
+ Qt::DayOfWeek firstColumnDay() const;
+
+ bool weekNumbersShown() const;
+ void setWeekNumbersShown(bool show);
+
+ QTextCharFormat formatForCell(int row, int col) const;
+ Qt::DayOfWeek dayOfWeekForColumn(int section) const;
+ int columnForDayOfWeek(Qt::DayOfWeek day) const;
+ QDate dateForCell(int row, int column) const;
+ void cellForDate(const QDate &date, int *row, int *column) const;
+ QString dayName(Qt::DayOfWeek day) const;
+
+ void setView(QCalendarView *view)
+ { m_view = view; }
+
+ void internalUpdate();
+ QDate referenceDate() const;
+ int columnForFirstOfMonth(const QDate &date) const;
+
+ int m_firstColumn;
+ int m_firstRow;
+ QDate m_date;
+ QDate m_minimumDate;
+ QDate m_maximumDate;
+ int m_shownYear;
+ int m_shownMonth;
+ Qt::DayOfWeek m_firstDay;
+ QCalendarWidget::HorizontalHeaderFormat m_horizontalHeaderFormat;
+ bool m_weekNumbersShown;
+ QMap<Qt::DayOfWeek, QTextCharFormat> m_dayFormats;
+ QMap<QDate, QTextCharFormat> m_dateFormats;
+ QTextCharFormat m_headerFormat;
+ QCalendarView *m_view;
+};
+
+class QCalendarView : public QTableView
+{
+ Q_OBJECT
+public:
+ QCalendarView(QWidget *parent = 0);
+
+ void internalUpdate() { updateGeometries(); }
+ void setReadOnly(bool enable);
+ virtual void keyboardSearch(const QString & search) { Q_UNUSED(search) }
+
+signals:
+ void showDate(const QDate &date);
+ void changeDate(const QDate &date, bool changeMonth);
+ void clicked(const QDate &date);
+ void editingFinished();
+protected:
+ QModelIndex moveCursor(CursorAction cursorAction, Qt::KeyboardModifiers modifiers);
+ void mouseDoubleClickEvent(QMouseEvent *event);
+ void mousePressEvent(QMouseEvent *event);
+ void mouseMoveEvent(QMouseEvent *event);
+ void mouseReleaseEvent(QMouseEvent *event);
+#ifndef QT_NO_WHEELEVENT
+ void wheelEvent(QWheelEvent *event);
+#endif
+ void keyPressEvent(QKeyEvent *event);
+ bool event(QEvent *event);
+
+ QDate handleMouseEvent(QMouseEvent *event);
+public:
+ bool readOnly;
+private:
+ bool validDateClicked;
+#ifdef QT_KEYPAD_NAVIGATION
+ QDate origDate;
+#endif
+};
+
+QCalendarModel::QCalendarModel(QObject *parent)
+ : QAbstractTableModel(parent)
+{
+ m_date = QDate::currentDate();
+ m_minimumDate = QDate::fromJulianDay(1);
+ m_maximumDate = QDate(7999, 12, 31);
+ m_shownYear = m_date.year();
+ m_shownMonth = m_date.month();
+ m_firstDay = Qt::Sunday;
+ m_horizontalHeaderFormat = QCalendarWidget::ShortDayNames;
+ m_weekNumbersShown = true;
+ m_firstColumn = 1;
+ m_firstRow = 1;
+ m_view = 0;
+}
+
+Qt::DayOfWeek QCalendarModel::dayOfWeekForColumn(int column) const
+{
+ int col = column - m_firstColumn;
+ if (col < 0 || col > 6)
+ return Qt::Sunday;
+ int day = m_firstDay + col;
+ if (day > 7)
+ day -= 7;
+ return Qt::DayOfWeek(day);
+}
+
+int QCalendarModel::columnForDayOfWeek(Qt::DayOfWeek day) const
+{
+ if (day < 1 || day > 7)
+ return -1;
+ int column = (int)day - (int)m_firstDay;
+ if (column < 0)
+ column += 7;
+ return column + m_firstColumn;
+}
+
+/*
+This simple algorithm tries to generate a valid date from the month shown.
+Some months don't contain a first day (e.g. Jan of -4713 year,
+so QDate (-4713, 1, 1) would be invalid). In that case we try to generate
+another valid date for that month. Later, returned date's day is the number of cells
+calendar widget will reserve for days before referenceDate. (E.g. if returned date's
+day is 16, that day will be placed in 3rd or 4th row, not in the 1st or 2nd row).
+Depending on referenceData we can change behaviour of Oct 1582. If referenceDate is 1st
+of Oct we render 1 Oct in 1st or 2nd row. If referenceDate is 17 of Oct we show always 16
+dates before 17 of Oct, and since this month contains the hole 5-14 Oct, the first of Oct
+will be rendered in 2nd or 3rd row, showing more dates from previous month.
+*/
+QDate QCalendarModel::referenceDate() const
+{
+ int refDay = 1;
+ while (refDay <= 31) {
+ QDate refDate(m_shownYear, m_shownMonth, refDay);
+ if (refDate.isValid())
+ return refDate;
+ refDay += 1;
+ }
+ return QDate();
+}
+
+int QCalendarModel::columnForFirstOfMonth(const QDate &date) const
+{
+ return (columnForDayOfWeek(static_cast<Qt::DayOfWeek>(date.dayOfWeek())) - (date.day() % 7) + 8) % 7;
+}
+
+QDate QCalendarModel::dateForCell(int row, int column) const
+{
+ if (row < m_firstRow || row > m_firstRow + RowCount - 1 ||
+ column < m_firstColumn || column > m_firstColumn + ColumnCount - 1)
+ return QDate();
+ const QDate refDate = referenceDate();
+ if (!refDate.isValid())
+ return QDate();
+
+ const int columnForFirstOfShownMonth = columnForFirstOfMonth(refDate);
+ if (columnForFirstOfShownMonth - m_firstColumn < MinimumDayOffset)
+ row -= 1;
+
+ const int requestedDay = 7 * (row - m_firstRow) + column - columnForFirstOfShownMonth - refDate.day() + 1;
+ return refDate.addDays(requestedDay);
+}
+
+void QCalendarModel::cellForDate(const QDate &date, int *row, int *column) const
+{
+ if (!row && !column)
+ return;
+
+ if (row)
+ *row = -1;
+ if (column)
+ *column = -1;
+
+ const QDate refDate = referenceDate();
+ if (!refDate.isValid())
+ return;
+
+ const int columnForFirstOfShownMonth = columnForFirstOfMonth(refDate);
+ const int requestedPosition = refDate.daysTo(date) - m_firstColumn + columnForFirstOfShownMonth + refDate.day() - 1;
+
+ int c = requestedPosition % 7;
+ int r = requestedPosition / 7;
+ if (c < 0) {
+ c += 7;
+ r -= 1;
+ }
+
+ if (columnForFirstOfShownMonth - m_firstColumn < MinimumDayOffset)
+ r += 1;
+
+ if (r < 0 || r > RowCount - 1 || c < 0 || c > ColumnCount - 1)
+ return;
+
+ if (row)
+ *row = r + m_firstRow;
+ if (column)
+ *column = c + m_firstColumn;
+}
+
+QString QCalendarModel::dayName(Qt::DayOfWeek day) const
+{
+ switch (m_horizontalHeaderFormat) {
+ case QCalendarWidget::SingleLetterDayNames: {
+ QString standaloneDayName = m_view->locale().standaloneDayName(day, QLocale::NarrowFormat);
+ if (standaloneDayName == m_view->locale().dayName(day, QLocale::NarrowFormat))
+ return standaloneDayName.left(1);
+ return standaloneDayName;
+ }
+ case QCalendarWidget::ShortDayNames:
+ return m_view->locale().dayName(day, QLocale::ShortFormat);
+ case QCalendarWidget::LongDayNames:
+ return m_view->locale().dayName(day, QLocale::LongFormat);
+ default:
+ break;
+ }
+ return QString();
+}
+
+QTextCharFormat QCalendarModel::formatForCell(int row, int col) const
+{
+ QPalette pal;
+ QPalette::ColorGroup cg = QPalette::Active;
+ if (m_view) {
+ pal = m_view->palette();
+ if (!m_view->isEnabled())
+ cg = QPalette::Disabled;
+ else if (!m_view->isActiveWindow())
+ cg = QPalette::Inactive;
+ }
+
+ QTextCharFormat format;
+ format.setFont(m_view->font());
+ bool header = (m_weekNumbersShown && col == HeaderColumn)
+ || (m_horizontalHeaderFormat != QCalendarWidget::NoHorizontalHeader && row == HeaderRow);
+ format.setBackground(pal.brush(cg, header ? QPalette::AlternateBase : QPalette::Base));
+ format.setForeground(pal.brush(cg, QPalette::Text));
+ if (header) {
+ format.merge(m_headerFormat);
+ }
+
+ if (col >= m_firstColumn && col < m_firstColumn + ColumnCount) {
+ Qt::DayOfWeek dayOfWeek = dayOfWeekForColumn(col);
+ if (m_dayFormats.contains(dayOfWeek))
+ format.merge(m_dayFormats.value(dayOfWeek));
+ }
+
+ if (!header) {
+ QDate date = dateForCell(row, col);
+ format.merge(m_dateFormats.value(date));
+ if(date < m_minimumDate || date > m_maximumDate)
+ format.setBackground(pal.brush(cg, QPalette::Window));
+ if (m_shownMonth != date.month())
+ format.setForeground(pal.brush(QPalette::Disabled, QPalette::Text));
+ }
+ return format;
+}
+
+QVariant QCalendarModel::data(const QModelIndex &index, int role) const
+{
+ if (role == Qt::TextAlignmentRole)
+ return (int) Qt::AlignCenter;
+
+ int row = index.row();
+ int column = index.column();
+
+ if(role == Qt::DisplayRole) {
+ if (m_weekNumbersShown && column == HeaderColumn
+ && row >= m_firstRow && row < m_firstRow + RowCount) {
+ QDate date = dateForCell(row, columnForDayOfWeek(Qt::Monday));
+ if (date.isValid())
+ return date.weekNumber();
+ }
+ if (m_horizontalHeaderFormat != QCalendarWidget::NoHorizontalHeader && row == HeaderRow
+ && column >= m_firstColumn && column < m_firstColumn + ColumnCount)
+ return dayName(dayOfWeekForColumn(column));
+ QDate date = dateForCell(row, column);
+ if (date.isValid())
+ return date.day();
+ return QString();
+ }
+
+ QTextCharFormat fmt = formatForCell(row, column);
+ if (role == Qt::BackgroundColorRole)
+ return fmt.background().color();
+ if (role == Qt::TextColorRole)
+ return fmt.foreground().color();
+ if (role == Qt::FontRole)
+ return fmt.font();
+ if (role == Qt::ToolTipRole)
+ return fmt.toolTip();
+ return QVariant();
+}
+
+Qt::ItemFlags QCalendarModel::flags(const QModelIndex &index) const
+{
+ QDate date = dateForCell(index.row(), index.column());
+ if (!date.isValid())
+ return QAbstractTableModel::flags(index);
+ if (date < m_minimumDate)
+ return 0;
+ if (date > m_maximumDate)
+ return 0;
+ return QAbstractTableModel::flags(index);
+}
+
+void QCalendarModel::setDate(const QDate &d)
+{
+ m_date = d;
+ if (m_date < m_minimumDate)
+ m_date = m_minimumDate;
+ else if (m_date > m_maximumDate)
+ m_date = m_maximumDate;
+}
+
+void QCalendarModel::showMonth(int year, int month)
+{
+ if (m_shownYear == year && m_shownMonth == month)
+ return;
+
+ m_shownYear = year;
+ m_shownMonth = month;
+
+ internalUpdate();
+}
+
+void QCalendarModel::setMinimumDate(const QDate &d)
+{
+ if (!d.isValid() || d == m_minimumDate)
+ return;
+
+ m_minimumDate = d;
+ if (m_maximumDate < m_minimumDate)
+ m_maximumDate = m_minimumDate;
+ if (m_date < m_minimumDate)
+ m_date = m_minimumDate;
+ internalUpdate();
+}
+
+void QCalendarModel::setMaximumDate(const QDate &d)
+{
+ if (!d.isValid() || d == m_maximumDate)
+ return;
+
+ m_maximumDate = d;
+ if (m_minimumDate > m_maximumDate)
+ m_minimumDate = m_maximumDate;
+ if (m_date > m_maximumDate)
+ m_date = m_maximumDate;
+ internalUpdate();
+}
+
+void QCalendarModel::setRange(const QDate &min, const QDate &max)
+{
+ m_minimumDate = min;
+ m_maximumDate = max;
+ if (m_minimumDate > m_maximumDate)
+ qSwap(m_minimumDate, m_maximumDate);
+ if (m_date < m_minimumDate)
+ m_date = m_minimumDate;
+ if (m_date > m_maximumDate)
+ m_date = m_maximumDate;
+ internalUpdate();
+}
+
+void QCalendarModel::internalUpdate()
+{
+ QModelIndex begin = index(0, 0);
+ QModelIndex end = index(m_firstRow + RowCount - 1, m_firstColumn + ColumnCount - 1);
+ emit dataChanged(begin, end);
+ emit headerDataChanged(Qt::Vertical, 0, m_firstRow + RowCount - 1);
+ emit headerDataChanged(Qt::Horizontal, 0, m_firstColumn + ColumnCount - 1);
+}
+
+void QCalendarModel::setHorizontalHeaderFormat(QCalendarWidget::HorizontalHeaderFormat format)
+{
+ if (m_horizontalHeaderFormat == format)
+ return;
+
+ int oldFormat = m_horizontalHeaderFormat;
+ m_horizontalHeaderFormat = format;
+ if (oldFormat == QCalendarWidget::NoHorizontalHeader) {
+ m_firstRow = 1;
+ insertRow(0);
+ } else if (m_horizontalHeaderFormat == QCalendarWidget::NoHorizontalHeader) {
+ m_firstRow = 0;
+ removeRow(0);
+ }
+ internalUpdate();
+}
+
+void QCalendarModel::setFirstColumnDay(Qt::DayOfWeek dayOfWeek)
+{
+ if (m_firstDay == dayOfWeek)
+ return;
+
+ m_firstDay = dayOfWeek;
+ internalUpdate();
+}
+
+Qt::DayOfWeek QCalendarModel::firstColumnDay() const
+{
+ return m_firstDay;
+}
+
+bool QCalendarModel::weekNumbersShown() const
+{
+ return m_weekNumbersShown;
+}
+
+void QCalendarModel::setWeekNumbersShown(bool show)
+{
+ if (m_weekNumbersShown == show)
+ return;
+
+ m_weekNumbersShown = show;
+ if (show) {
+ m_firstColumn = 1;
+ insertColumn(0);
+ } else {
+ m_firstColumn = 0;
+ removeColumn(0);
+ }
+ internalUpdate();
+}
+
+QCalendarView::QCalendarView(QWidget *parent)
+ : QTableView(parent),
+ readOnly(false),
+ validDateClicked(false)
+{
+ setTabKeyNavigation(false);
+ setShowGrid(false);
+ verticalHeader()->setVisible(false);
+ horizontalHeader()->setVisible(false);
+ setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+ setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+}
+
+QModelIndex QCalendarView::moveCursor(CursorAction cursorAction, Qt::KeyboardModifiers modifiers)
+{
+ QCalendarModel *calendarModel = qobject_cast<QCalendarModel *>(model());
+ if (!calendarModel)
+ return QTableView::moveCursor(cursorAction, modifiers);
+
+ if (readOnly)
+ return currentIndex();
+
+ QModelIndex index = currentIndex();
+ QDate currentDate = static_cast<QCalendarModel*>(model())->dateForCell(index.row(), index.column());
+ switch (cursorAction) {
+ case QAbstractItemView::MoveUp:
+ currentDate = currentDate.addDays(-7);
+ break;
+ case QAbstractItemView::MoveDown:
+ currentDate = currentDate.addDays(7);
+ break;
+ case QAbstractItemView::MoveLeft:
+ currentDate = currentDate.addDays(isRightToLeft() ? 1 : -1);
+ break;
+ case QAbstractItemView::MoveRight:
+ currentDate = currentDate.addDays(isRightToLeft() ? -1 : 1);
+ break;
+ case QAbstractItemView::MoveHome:
+ currentDate = QDate(currentDate.year(), currentDate.month(), 1);
+ break;
+ case QAbstractItemView::MoveEnd:
+ currentDate = QDate(currentDate.year(), currentDate.month(), currentDate.daysInMonth());
+ break;
+ case QAbstractItemView::MovePageUp:
+ currentDate = currentDate.addMonths(-1);
+ break;
+ case QAbstractItemView::MovePageDown:
+ currentDate = currentDate.addMonths(1);
+ break;
+ case QAbstractItemView::MoveNext:
+ case QAbstractItemView::MovePrevious:
+ return currentIndex();
+ default:
+ break;
+ }
+ emit changeDate(currentDate, true);
+ return currentIndex();
+}
+
+void QCalendarView::keyPressEvent(QKeyEvent *event)
+{
+#ifdef QT_KEYPAD_NAVIGATION
+ if (event->key() == Qt::Key_Select) {
+ if (QApplication::keypadNavigationEnabled()) {
+ if (!hasEditFocus()) {
+ setEditFocus(true);
+ return;
+ }
+ }
+ } else if (event->key() == Qt::Key_Back) {
+ if (QApplication::keypadNavigationEnabled() && hasEditFocus()) {
+ if (qobject_cast<QCalendarModel *>(model())) {
+ emit changeDate(origDate, true); //changes selection back to origDate, but doesn't activate
+ setEditFocus(false);
+ return;
+ }
+ }
+ }
+#endif
+
+ if (!readOnly) {
+ switch (event->key()) {
+ case Qt::Key_Return:
+ case Qt::Key_Enter:
+ case Qt::Key_Select:
+ emit editingFinished();
+ return;
+ default:
+ break;
+ }
+ }
+ QTableView::keyPressEvent(event);
+}
+
+#ifndef QT_NO_WHEELEVENT
+void QCalendarView::wheelEvent(QWheelEvent *event)
+{
+ const int numDegrees = event->delta() / 8;
+ const int numSteps = numDegrees / 15;
+ const QModelIndex index = currentIndex();
+ QDate currentDate = static_cast<QCalendarModel*>(model())->dateForCell(index.row(), index.column());
+ currentDate = currentDate.addMonths(-numSteps);
+ emit showDate(currentDate);
+}
+#endif
+
+bool QCalendarView::event(QEvent *event)
+{
+#ifdef QT_KEYPAD_NAVIGATION
+ if (event->type() == QEvent::FocusIn) {
+ if (QCalendarModel *calendarModel = qobject_cast<QCalendarModel *>(model())) {
+ origDate = calendarModel->m_date;
+ }
+ }
+#endif
+
+ return QTableView::event(event);
+}
+
+QDate QCalendarView::handleMouseEvent(QMouseEvent *event)
+{
+ QCalendarModel *calendarModel = qobject_cast<QCalendarModel *>(model());
+ if (!calendarModel)
+ return QDate();
+
+ QPoint pos = event->pos();
+ QModelIndex index = indexAt(pos);
+ QDate date = calendarModel->dateForCell(index.row(), index.column());
+ if (date.isValid() && date >= calendarModel->m_minimumDate
+ && date <= calendarModel->m_maximumDate) {
+ return date;
+ }
+ return QDate();
+}
+
+void QCalendarView::mouseDoubleClickEvent(QMouseEvent *event)
+{
+ QCalendarModel *calendarModel = qobject_cast<QCalendarModel *>(model());
+ if (!calendarModel) {
+ QTableView::mouseDoubleClickEvent(event);
+ return;
+ }
+
+ if (readOnly)
+ return;
+
+ QDate date = handleMouseEvent(event);
+ validDateClicked = false;
+ if (date == calendarModel->m_date && !style()->styleHint(QStyle::SH_ItemView_ActivateItemOnSingleClick)) {
+ emit editingFinished();
+ }
+}
+
+void QCalendarView::mousePressEvent(QMouseEvent *event)
+{
+ QCalendarModel *calendarModel = qobject_cast<QCalendarModel *>(model());
+ if (!calendarModel) {
+ QTableView::mousePressEvent(event);
+ return;
+ }
+
+ if (readOnly)
+ return;
+
+ if (event->button() != Qt::LeftButton)
+ return;
+
+ QDate date = handleMouseEvent(event);
+ if (date.isValid()) {
+ validDateClicked = true;
+ int row = -1, col = -1;
+ static_cast<QCalendarModel *>(model())->cellForDate(date, &row, &col);
+ if (row != -1 && col != -1) {
+ selectionModel()->setCurrentIndex(model()->index(row, col), QItemSelectionModel::NoUpdate);
+ }
+ } else {
+ validDateClicked = false;
+ event->ignore();
+ }
+}
+
+void QCalendarView::mouseMoveEvent(QMouseEvent *event)
+{
+ QCalendarModel *calendarModel = qobject_cast<QCalendarModel *>(model());
+ if (!calendarModel) {
+ QTableView::mouseMoveEvent(event);
+ return;
+ }
+
+ if (readOnly)
+ return;
+
+ if (validDateClicked) {
+ QDate date = handleMouseEvent(event);
+ if (date.isValid()) {
+ int row = -1, col = -1;
+ static_cast<QCalendarModel *>(model())->cellForDate(date, &row, &col);
+ if (row != -1 && col != -1) {
+ selectionModel()->setCurrentIndex(model()->index(row, col), QItemSelectionModel::NoUpdate);
+ }
+ }
+ } else {
+ event->ignore();
+ }
+}
+
+void QCalendarView::mouseReleaseEvent(QMouseEvent *event)
+{
+ QCalendarModel *calendarModel = qobject_cast<QCalendarModel *>(model());
+ if (!calendarModel) {
+ QTableView::mouseReleaseEvent(event);
+ return;
+ }
+
+ if (event->button() != Qt::LeftButton)
+ return;
+
+ if (readOnly)
+ return;
+
+ if (validDateClicked) {
+ QDate date = handleMouseEvent(event);
+ if (date.isValid()) {
+ emit changeDate(date, true);
+ emit clicked(date);
+ if (style()->styleHint(QStyle::SH_ItemView_ActivateItemOnSingleClick))
+ emit editingFinished();
+ }
+ validDateClicked = false;
+ } else {
+ event->ignore();
+ }
+}
+
+class QCalendarDelegate : public QItemDelegate
+{
+ Q_OBJECT
+public:
+ QCalendarDelegate(QCalendarWidgetPrivate *w, QObject *parent = 0)
+ : QItemDelegate(parent), calendarWidgetPrivate(w)
+ { }
+ virtual void paint(QPainter *painter, const QStyleOptionViewItem &option,
+ const QModelIndex &index) const;
+ void paintCell(QPainter *painter, const QRect &rect, const QDate &date) const;
+
+private:
+ QCalendarWidgetPrivate *calendarWidgetPrivate;
+ mutable QStyleOptionViewItemV4 storedOption;
+};
+
+//Private tool button class
+class QCalToolButton: public QToolButton
+{
+public:
+ QCalToolButton(QWidget * parent)
+ : QToolButton(parent)
+ { }
+protected:
+ void paintEvent(QPaintEvent *e)
+ {
+ Q_UNUSED(e)
+
+#ifndef Q_WS_MAC
+ QStyleOptionToolButton opt;
+ initStyleOption(&opt);
+
+ if (opt.state & QStyle::State_MouseOver || isDown()) {
+ //act as normal button
+ setPalette(QPalette());
+ } else {
+ //set the highlight color for button text
+ QPalette toolPalette = palette();
+ toolPalette.setColor(QPalette::ButtonText, toolPalette.color(QPalette::HighlightedText));
+ setPalette(toolPalette);
+ }
+#endif
+ QToolButton::paintEvent(e);
+ }
+};
+
+class QPrevNextCalButton : public QToolButton
+{
+ Q_OBJECT
+public:
+ QPrevNextCalButton(QWidget *parent) : QToolButton(parent) {}
+protected:
+ void paintEvent(QPaintEvent *) {
+ QStylePainter painter(this);
+ QStyleOptionToolButton opt;
+ initStyleOption(&opt);
+ opt.state &= ~QStyle::State_HasFocus;
+ painter.drawComplexControl(QStyle::CC_ToolButton, opt);
+ }
+};
+
+class QCalendarWidgetPrivate : public QWidgetPrivate
+{
+ Q_DECLARE_PUBLIC(QCalendarWidget)
+public:
+ QCalendarWidgetPrivate();
+
+ void showMonth(int year, int month);
+ void update();
+ void paintCell(QPainter *painter, const QRect &rect, const QDate &date) const;
+
+ void _q_slotShowDate(const QDate &date);
+ void _q_slotChangeDate(const QDate &date);
+ void _q_slotChangeDate(const QDate &date, bool changeMonth);
+ void _q_editingFinished();
+ void _q_monthChanged(QAction*);
+ void _q_prevMonthClicked();
+ void _q_nextMonthClicked();
+ void _q_yearEditingFinished();
+ void _q_yearClicked();
+
+ void createNavigationBar(QWidget *widget);
+ void updateButtonIcons();
+ void updateMonthMenu();
+ void updateMonthMenuNames();
+ void updateNavigationBar();
+ void updateCurrentPage(const QDate &newDate);
+ inline QDate getCurrentDate();
+ void setNavigatorEnabled(bool enable);
+
+ QCalendarModel *m_model;
+ QCalendarView *m_view;
+ QCalendarDelegate *m_delegate;
+ QItemSelectionModel *m_selection;
+ QCalendarTextNavigator *m_navigator;
+ bool m_dateEditEnabled;
+
+ QToolButton *nextMonth;
+ QToolButton *prevMonth;
+ QCalToolButton *monthButton;
+ QMenu *monthMenu;
+ QMap<int, QAction *> monthToAction;
+ QCalToolButton *yearButton;
+ QSpinBox *yearEdit;
+ QWidget *navBarBackground;
+ QSpacerItem *spaceHolder;
+
+ bool navBarVisible;
+ mutable QSize cachedSizeHint;
+ Qt::FocusPolicy oldFocusPolicy;
+};
+
+void QCalendarDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option,
+ const QModelIndex &index) const
+{
+ QDate date = calendarWidgetPrivate->m_model->dateForCell(index.row(), index.column());
+ if (date.isValid()) {
+ storedOption = option;
+ QRect rect = option.rect;
+ calendarWidgetPrivate->paintCell(painter, rect, date);
+ } else {
+ QItemDelegate::paint(painter, option, index);
+ }
+}
+
+void QCalendarDelegate::paintCell(QPainter *painter, const QRect &rect, const QDate &date) const
+{
+ storedOption.rect = rect;
+ int row = -1;
+ int col = -1;
+ calendarWidgetPrivate->m_model->cellForDate(date, &row, &col);
+ QModelIndex idx = calendarWidgetPrivate->m_model->index(row, col);
+ QItemDelegate::paint(painter, storedOption, idx);
+}
+
+QCalendarWidgetPrivate::QCalendarWidgetPrivate()
+ : QWidgetPrivate()
+{
+ m_model = 0;
+ m_view = 0;
+ m_delegate = 0;
+ m_selection = 0;
+ m_navigator = 0;
+ m_dateEditEnabled = false;
+ navBarVisible = true;
+ oldFocusPolicy = Qt::StrongFocus;
+}
+
+void QCalendarWidgetPrivate::setNavigatorEnabled(bool enable)
+{
+ Q_Q(QCalendarWidget);
+
+ bool navigatorEnabled = (m_navigator->widget() != 0);
+ if (enable == navigatorEnabled)
+ return;
+
+ if (enable) {
+ m_navigator->setWidget(q);
+ q->connect(m_navigator, SIGNAL(dateChanged(QDate)),
+ q, SLOT(_q_slotChangeDate(QDate)));
+ q->connect(m_navigator, SIGNAL(editingFinished()),
+ q, SLOT(_q_editingFinished()));
+ m_view->installEventFilter(m_navigator);
+ } else {
+ m_navigator->setWidget(0);
+ q->disconnect(m_navigator, SIGNAL(dateChanged(QDate)),
+ q, SLOT(_q_slotChangeDate(QDate)));
+ q->disconnect(m_navigator, SIGNAL(editingFinished()),
+ q, SLOT(_q_editingFinished()));
+ m_view->removeEventFilter(m_navigator);
+ }
+}
+
+void QCalendarWidgetPrivate::createNavigationBar(QWidget *widget)
+{
+ Q_Q(QCalendarWidget);
+ navBarBackground = new QWidget(widget);
+ navBarBackground->setObjectName(QLatin1String("qt_calendar_navigationbar"));
+ navBarBackground->setAutoFillBackground(true);
+ navBarBackground->setBackgroundRole(QPalette::Highlight);
+
+ prevMonth = new QPrevNextCalButton(navBarBackground);
+ nextMonth = new QPrevNextCalButton(navBarBackground);
+ prevMonth->setAutoRaise(true);
+ nextMonth->setAutoRaise(true);
+ prevMonth->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Minimum);
+ nextMonth->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Minimum);
+ nextMonth->setAutoRaise(true);
+ updateButtonIcons();
+ prevMonth->setAutoRepeat(true);
+ nextMonth->setAutoRepeat(true);
+
+ monthButton = new QCalToolButton(navBarBackground);
+ monthButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Minimum);
+ monthButton->setAutoRaise(true);
+ monthButton->setPopupMode(QToolButton::InstantPopup);
+ monthMenu = new QMenu(monthButton);
+ for (int i = 1; i <= 12; i++) {
+ QString monthName(q->locale().standaloneMonthName(i, QLocale::LongFormat));
+ QAction *act = monthMenu->addAction(monthName);
+ act->setData(i);
+ monthToAction[i] = act;
+ }
+ monthButton->setMenu(monthMenu);
+ yearButton = new QCalToolButton(navBarBackground);
+ yearButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Minimum);
+ yearButton->setAutoRaise(true);
+ yearEdit = new QSpinBox(navBarBackground);
+
+ QFont font = q->font();
+ font.setBold(true);
+ monthButton->setFont(font);
+ yearButton->setFont(font);
+ yearEdit->setFrame(false);
+ yearEdit->setMinimum(m_model->m_minimumDate.year());
+ yearEdit->setMaximum(m_model->m_maximumDate.year());
+ yearEdit->hide();
+ spaceHolder = new QSpacerItem(0,0);
+
+ QHBoxLayout *headerLayout = new QHBoxLayout;
+ headerLayout->setMargin(0);
+ headerLayout->setSpacing(0);
+ headerLayout->addWidget(prevMonth);
+ headerLayout->insertStretch(headerLayout->count());
+ headerLayout->addWidget(monthButton);
+ headerLayout->addItem(spaceHolder);
+ headerLayout->addWidget(yearButton);
+ headerLayout->insertStretch(headerLayout->count());
+ headerLayout->addWidget(nextMonth);
+ navBarBackground->setLayout(headerLayout);
+
+ yearEdit->setFocusPolicy(Qt::StrongFocus);
+ prevMonth->setFocusPolicy(Qt::NoFocus);
+ nextMonth->setFocusPolicy(Qt::NoFocus);
+ yearButton->setFocusPolicy(Qt::NoFocus);
+ monthButton->setFocusPolicy(Qt::NoFocus);
+
+ //set names for the header controls.
+ prevMonth->setObjectName(QLatin1String("qt_calendar_prevmonth"));
+ nextMonth->setObjectName(QLatin1String("qt_calendar_nextmonth"));
+ monthButton->setObjectName(QLatin1String("qt_calendar_monthbutton"));
+ yearButton->setObjectName(QLatin1String("qt_calendar_yearbutton"));
+ yearEdit->setObjectName(QLatin1String("qt_calendar_yearedit"));
+
+ updateMonthMenu();
+ showMonth(m_model->m_date.year(), m_model->m_date.month());
+}
+
+void QCalendarWidgetPrivate::updateButtonIcons()
+{
+ Q_Q(QCalendarWidget);
+ prevMonth->setIcon(q->style()->standardIcon(q->isRightToLeft() ? QStyle::SP_ArrowRight : QStyle::SP_ArrowLeft, 0, q));
+ nextMonth->setIcon(q->style()->standardIcon(q->isRightToLeft() ? QStyle::SP_ArrowLeft : QStyle::SP_ArrowRight, 0, q));
+}
+
+void QCalendarWidgetPrivate::updateMonthMenu()
+{
+ int beg = 1, end = 12;
+ bool prevEnabled = true;
+ bool nextEnabled = true;
+ if (m_model->m_shownYear == m_model->m_minimumDate.year()) {
+ beg = m_model->m_minimumDate.month();
+ if (m_model->m_shownMonth == m_model->m_minimumDate.month())
+ prevEnabled = false;
+ }
+ if (m_model->m_shownYear == m_model->m_maximumDate.year()) {
+ end = m_model->m_maximumDate.month();
+ if (m_model->m_shownMonth == m_model->m_maximumDate.month())
+ nextEnabled = false;
+ }
+ prevMonth->setEnabled(prevEnabled);
+ nextMonth->setEnabled(nextEnabled);
+ for (int i = 1; i <= 12; i++) {
+ bool monthEnabled = true;
+ if (i < beg || i > end)
+ monthEnabled = false;
+ monthToAction[i]->setEnabled(monthEnabled);
+ }
+}
+
+void QCalendarWidgetPrivate::updateMonthMenuNames()
+{
+ Q_Q(QCalendarWidget);
+
+ for (int i = 1; i <= 12; i++) {
+ QString monthName(q->locale().standaloneMonthName(i, QLocale::LongFormat));
+ monthToAction[i]->setText(monthName);
+ }
+}
+
+void QCalendarWidgetPrivate::updateCurrentPage(const QDate &date)
+{
+ Q_Q(QCalendarWidget);
+
+ QDate newDate = date;
+ QDate minDate = q->minimumDate();
+ QDate maxDate = q->maximumDate();
+ if (minDate.isValid()&& minDate.daysTo(newDate) < 0)
+ newDate = minDate;
+ if (maxDate.isValid()&& maxDate.daysTo(newDate) > 0)
+ newDate = maxDate;
+ showMonth(newDate.year(), newDate.month());
+ int row = -1, col = -1;
+ m_model->cellForDate(newDate, &row, &col);
+ if (row != -1 && col != -1)
+ {
+ m_view->selectionModel()->setCurrentIndex(m_model->index(row, col),
+ QItemSelectionModel::NoUpdate);
+ }
+}
+
+void QCalendarWidgetPrivate::_q_monthChanged(QAction *act)
+{
+ monthButton->setText(act->text());
+ QDate currentDate = getCurrentDate();
+ QDate newDate = currentDate.addMonths(act->data().toInt()-currentDate.month());
+ updateCurrentPage(newDate);
+}
+
+QDate QCalendarWidgetPrivate::getCurrentDate()
+{
+ QModelIndex index = m_view->currentIndex();
+ return m_model->dateForCell(index.row(), index.column());
+}
+
+void QCalendarWidgetPrivate::_q_prevMonthClicked()
+{
+ QDate currentDate = getCurrentDate().addMonths(-1);
+ updateCurrentPage(currentDate);
+}
+
+void QCalendarWidgetPrivate::_q_nextMonthClicked()
+{
+ QDate currentDate = getCurrentDate().addMonths(1);
+ updateCurrentPage(currentDate);
+}
+
+void QCalendarWidgetPrivate::_q_yearEditingFinished()
+{
+ Q_Q(QCalendarWidget);
+ yearButton->setText(yearEdit->text());
+ yearEdit->hide();
+ q->setFocusPolicy(oldFocusPolicy);
+ qApp->removeEventFilter(q);
+ spaceHolder->changeSize(0, 0);
+ yearButton->show();
+ QDate currentDate = getCurrentDate();
+ currentDate = currentDate.addYears(yearEdit->text().toInt() - currentDate.year());
+ updateCurrentPage(currentDate);
+}
+
+void QCalendarWidgetPrivate::_q_yearClicked()
+{
+ Q_Q(QCalendarWidget);
+ //show the spinbox on top of the button
+ yearEdit->setGeometry(yearButton->x(), yearButton->y(),
+ yearEdit->sizeHint().width(), yearButton->height());
+ spaceHolder->changeSize(yearButton->width(), 0);
+ yearButton->hide();
+ oldFocusPolicy = q->focusPolicy();
+ q->setFocusPolicy(Qt::NoFocus);
+ yearEdit->show();
+ qApp->installEventFilter(q);
+ yearEdit->raise();
+ yearEdit->selectAll();
+ yearEdit->setFocus(Qt::MouseFocusReason);
+}
+
+void QCalendarWidgetPrivate::showMonth(int year, int month)
+{
+ if (m_model->m_shownYear == year && m_model->m_shownMonth == month)
+ return;
+ Q_Q(QCalendarWidget);
+ m_model->showMonth(year, month);
+ updateNavigationBar();
+ emit q->currentPageChanged(year, month);
+ m_view->internalUpdate();
+ cachedSizeHint = QSize();
+ update();
+ updateMonthMenu();
+}
+
+void QCalendarWidgetPrivate::updateNavigationBar()
+{
+ Q_Q(QCalendarWidget);
+
+ QString monthName = q->locale().standaloneMonthName(m_model->m_shownMonth, QLocale::LongFormat);
+
+ monthButton->setText(monthName);
+ yearButton->setText(QString::number(m_model->m_shownYear));
+ yearEdit->setValue(m_model->m_shownYear);
+}
+
+void QCalendarWidgetPrivate::update()
+{
+ QDate currentDate = m_model->m_date;
+ int row, column;
+ m_model->cellForDate(currentDate, &row, &column);
+ QModelIndex idx;
+ m_selection->clear();
+ if (row != -1 && column != -1) {
+ idx = m_model->index(row, column);
+ m_selection->setCurrentIndex(idx, QItemSelectionModel::SelectCurrent);
+ }
+}
+
+void QCalendarWidgetPrivate::paintCell(QPainter *painter, const QRect &rect, const QDate &date) const
+{
+ Q_Q(const QCalendarWidget);
+ q->paintCell(painter, rect, date);
+}
+
+void QCalendarWidgetPrivate::_q_slotShowDate(const QDate &date)
+{
+ updateCurrentPage(date);
+}
+
+void QCalendarWidgetPrivate::_q_slotChangeDate(const QDate &date)
+{
+ _q_slotChangeDate(date, true);
+}
+
+void QCalendarWidgetPrivate::_q_slotChangeDate(const QDate &date, bool changeMonth)
+{
+ QDate oldDate = m_model->m_date;
+ m_model->setDate(date);
+ QDate newDate = m_model->m_date;
+ if (changeMonth)
+ showMonth(newDate.year(), newDate.month());
+ if (oldDate != newDate) {
+ update();
+ Q_Q(QCalendarWidget);
+ m_navigator->setDate(newDate);
+ emit q->selectionChanged();
+ }
+}
+
+void QCalendarWidgetPrivate::_q_editingFinished()
+{
+ Q_Q(QCalendarWidget);
+ emit q->activated(m_model->m_date);
+}
+
+/*!
+ \class QCalendarWidget
+ \brief The QCalendarWidget class provides a monthly based
+ calendar widget allowing the user to select a date.
+ \since 4.2
+
+ \ingroup advanced
+
+ \image cleanlooks-calendarwidget.png
+
+ The widget is initialized with the current month and year, but
+ QCalendarWidget provides several public slots to change the year
+ and month that is shown.
+
+ By default, today's date is selected, and the user can select a
+ date using both mouse and keyboard. The currently selected date
+ can be retrieved using the selectedDate() function. It is
+ possible to constrain the user selection to a given date range by
+ setting the minimumDate and maximumDate properties.
+ Alternatively, both properties can be set in one go using the
+ setDateRange() convenience slot. Set the \l selectionMode
+ property to NoSelection to prohibit the user from selecting at
+ all. Note that a date also can be selected programmatically using
+ the setSelectedDate() slot.
+
+ The currently displayed month and year can be retrieved using the
+ monthShown() and yearShown() functions, respectively.
+
+ A newly created calendar widget uses abbreviated day names, and
+ both Saturdays and Sundays are marked in red. The calendar grid is
+ not visible. The week numbers are displayed, and the first column
+ day is Sunday.
+
+ The notation of the days can be altered to a single letter
+ abbreviations ("M" for "Monday") by setting the
+ horizontalHeaderFormat property to
+ QCalendarWidget::SingleLetterDayNames. Setting the same property
+ to QCalendarWidget::LongDayNames makes the header display the
+ complete day names. The week numbers can be removed by setting
+ the verticalHeaderFormat property to
+ QCalendarWidget::NoVerticalHeader. The calendar grid can be
+ turned on by setting the gridVisible property to true using the
+ setGridVisible() function:
+
+ \table
+ \row \o
+ \image qcalendarwidget-grid.png
+ \row \o
+ \snippet doc/src/snippets/code/src_gui_widgets_qcalendarwidget.cpp 0
+ \endtable
+
+ Finally, the day in the first column can be altered using the
+ setFirstDayOfWeek() function.
+
+ The QCalendarWidget class also provides three signals,
+ selectionChanged(), activated() and currentPageChanged() making it
+ possible to respond to user interaction.
+
+ The rendering of the headers, weekdays or single days can be
+ largely customized by setting QTextCharFormat's for some special
+ weekday, a special date or for the rendering of the headers.
+
+ Only a subset of the properties in QTextCharFormat are used by the
+ calendar widget. Currently, the foreground, background and font
+ properties are used to determine the rendering of individual cells
+ in the widget.
+
+ \sa QDate, QDateEdit, QTextCharFormat
+*/
+
+/*!
+ \enum QCalendarWidget::SelectionMode
+
+ This enum describes the types of selection offered to the user for
+ selecting dates in the calendar.
+
+ \value NoSelection Dates cannot be selected.
+ \value SingleSelection Single dates can be selected.
+
+ \sa selectionMode
+*/
+
+/*!
+ Constructs a calendar widget with the given \a parent.
+
+ The widget is initialized with the current month and year, and the
+ currently selected date is today.
+
+ \sa setCurrentPage()
+*/
+QCalendarWidget::QCalendarWidget(QWidget *parent)
+ : QWidget(*new QCalendarWidgetPrivate, parent, 0)
+{
+ Q_D(QCalendarWidget);
+
+ setAutoFillBackground(true);
+ setBackgroundRole(QPalette::Window);
+
+ QVBoxLayout *layoutV = new QVBoxLayout(this);
+ layoutV->setMargin(0);
+ d->m_model = new QCalendarModel(this);
+ QTextCharFormat fmt;
+ fmt.setForeground(QBrush(Qt::red));
+ d->m_model->m_dayFormats.insert(Qt::Saturday, fmt);
+ d->m_model->m_dayFormats.insert(Qt::Sunday, fmt);
+ d->m_view = new QCalendarView(this);
+ d->m_view->setObjectName(QLatin1String("qt_calendar_calendarview"));
+ d->m_view->setModel(d->m_model);
+ d->m_model->setView(d->m_view);
+ d->m_view->setSelectionBehavior(QAbstractItemView::SelectItems);
+ d->m_view->setSelectionMode(QAbstractItemView::SingleSelection);
+ d->m_view->horizontalHeader()->setResizeMode(QHeaderView::Stretch);
+ d->m_view->horizontalHeader()->setClickable(false);
+ d->m_view->verticalHeader()->setResizeMode(QHeaderView::Stretch);
+ d->m_view->verticalHeader()->setClickable(false);
+ d->m_selection = d->m_view->selectionModel();
+ d->createNavigationBar(this);
+ d->m_view->setFrameStyle(QFrame::NoFrame);
+ d->m_delegate = new QCalendarDelegate(d, this);
+ d->m_view->setItemDelegate(d->m_delegate);
+ d->update();
+ d->updateNavigationBar();
+ setFocusPolicy(Qt::StrongFocus);
+ setFocusProxy(d->m_view);
+ setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
+
+ connect(d->m_view, SIGNAL(showDate(QDate)),
+ this, SLOT(_q_slotShowDate(QDate)));
+ connect(d->m_view, SIGNAL(changeDate(QDate,bool)),
+ this, SLOT(_q_slotChangeDate(QDate,bool)));
+ connect(d->m_view, SIGNAL(clicked(QDate)),
+ this, SIGNAL(clicked(QDate)));
+ connect(d->m_view, SIGNAL(editingFinished()),
+ this, SLOT(_q_editingFinished()));
+
+ connect(d->prevMonth, SIGNAL(clicked(bool)),
+ this, SLOT(_q_prevMonthClicked()));
+ connect(d->nextMonth, SIGNAL(clicked(bool)),
+ this, SLOT(_q_nextMonthClicked()));
+ connect(d->yearButton, SIGNAL(clicked(bool)),
+ this, SLOT(_q_yearClicked()));
+ connect(d->monthMenu, SIGNAL(triggered(QAction*)),
+ this, SLOT(_q_monthChanged(QAction*)));
+ connect(d->yearEdit, SIGNAL(editingFinished()),
+ this, SLOT(_q_yearEditingFinished()));
+
+ layoutV->setMargin(0);
+ layoutV->setSpacing(0);
+ layoutV->addWidget(d->navBarBackground);
+ layoutV->addWidget(d->m_view);
+
+ d->m_navigator = new QCalendarTextNavigator(this);
+ setDateEditEnabled(true);
+}
+
+/*!
+ Destroys the calendar widget.
+*/
+QCalendarWidget::~QCalendarWidget()
+{
+}
+
+/*!
+ \reimp
+*/
+QSize QCalendarWidget::sizeHint() const
+{
+ return minimumSizeHint();
+}
+
+/*!
+ \reimp
+*/
+QSize QCalendarWidget::minimumSizeHint() const
+{
+ Q_D(const QCalendarWidget);
+ if (d->cachedSizeHint.isValid())
+ return d->cachedSizeHint;
+
+ ensurePolished();
+
+ int w = 0;
+ int h = 0;
+
+ int end = 53;
+ int rows = 7;
+ int cols = 8;
+
+ const int marginH = (style()->pixelMetric(QStyle::PM_FocusFrameHMargin) + 1) * 2;
+
+ if (horizontalHeaderFormat() == QCalendarWidget::NoHorizontalHeader) {
+ rows = 6;
+ } else {
+ for (int i = 1; i <= 7; i++) {
+ QFontMetrics fm(d->m_model->formatForCell(0, i).font());
+ w = qMax(w, fm.width(d->m_model->dayName(d->m_model->dayOfWeekForColumn(i))) + marginH);
+ h = qMax(h, fm.height());
+ }
+ }
+
+ if (verticalHeaderFormat() == QCalendarWidget::NoVerticalHeader) {
+ cols = 7;
+ } else {
+ for (int i = 1; i <= 6; i++) {
+ QFontMetrics fm(d->m_model->formatForCell(i, 0).font());
+ for (int j = 1; j < end; j++)
+ w = qMax(w, fm.width(QString::number(j)) + marginH);
+ h = qMax(h, fm.height());
+ }
+ }
+
+ QFontMetrics fm(d->m_model->formatForCell(1, 1).font());
+ for (int i = 1; i <= end; i++) {
+ w = qMax(w, fm.width(QString::number(i)) + marginH);
+ h = qMax(h, fm.height());
+ }
+
+ if (d->m_view->showGrid()) {
+ // hardcoded in tableview
+ w += 1;
+ h += 1;
+ }
+
+ w += 1; // default column span
+
+ h = qMax(h, d->m_view->verticalHeader()->minimumSectionSize());
+ w = qMax(w, d->m_view->horizontalHeader()->minimumSectionSize());
+
+ //add the size of the header.
+ QSize headerSize(0, 0);
+ if (d->navBarVisible) {
+ int headerH = d->navBarBackground->sizeHint().height();
+ int headerW = 0;
+
+ headerW += d->prevMonth->sizeHint().width();
+ headerW += d->nextMonth->sizeHint().width();
+
+ QFontMetrics fm = d->monthButton->fontMetrics();
+ int monthW = 0;
+ for (int i = 1; i < 12; i++) {
+ QString monthName = locale().standaloneMonthName(i, QLocale::LongFormat);
+ monthW = qMax(monthW, fm.boundingRect(monthName).width());
+ }
+ const int buttonDecoMargin = d->monthButton->sizeHint().width() - fm.boundingRect(d->monthButton->text()).width();
+ headerW += monthW + buttonDecoMargin;
+
+ fm = d->yearButton->fontMetrics();
+ headerW += fm.boundingRect(QLatin1String("5555")).width() + buttonDecoMargin;
+
+ headerSize = QSize(headerW, headerH);
+ }
+ w *= cols;
+ w = qMax(headerSize.width(), w);
+ h = (h * rows) + headerSize.height();
+ d->cachedSizeHint = QSize(w, h);
+ return d->cachedSizeHint;
+}
+
+/*!
+ Paints the cell specified by the given \a date, using the given \a painter and \a rect.
+*/
+
+void QCalendarWidget::paintCell(QPainter *painter, const QRect &rect, const QDate &date) const
+{
+ Q_D(const QCalendarWidget);
+ d->m_delegate->paintCell(painter, rect, date);
+}
+
+/*!
+ \property QCalendarWidget::selectedDate
+ \brief the currently selected date.
+
+ The selected date must be within the date range specified by the
+ minimumDate and maximumDate properties. By default, the selected
+ date is the current date.
+
+ \sa setDateRange()
+*/
+
+QDate QCalendarWidget::selectedDate() const
+{
+ Q_D(const QCalendarWidget);
+ return d->m_model->m_date;
+}
+
+void QCalendarWidget::setSelectedDate(const QDate &date)
+{
+ Q_D(QCalendarWidget);
+ if (d->m_model->m_date == date && date == d->getCurrentDate())
+ return;
+
+ if (!date.isValid())
+ return;
+
+ d->m_model->setDate(date);
+ d->update();
+ QDate newDate = d->m_model->m_date;
+ d->showMonth(newDate.year(), newDate.month());
+ emit selectionChanged();
+}
+
+/*!
+ Returns the year of the currently displayed month. Months are
+ numbered from 1 to 12.
+
+ \sa monthShown(), setCurrentPage()
+*/
+
+int QCalendarWidget::yearShown() const
+{
+ Q_D(const QCalendarWidget);
+ return d->m_model->m_shownYear;
+}
+
+/*!
+ Returns the currently displayed month. Months are numbered from 1 to
+ 12.
+
+ \sa yearShown(), setCurrentPage()
+*/
+
+int QCalendarWidget::monthShown() const
+{
+ Q_D(const QCalendarWidget);
+ return d->m_model->m_shownMonth;
+}
+
+/*!
+ Displays the given \a month of the given \a year without changing
+ the selected date. Use the setSelectedDate() function to alter the
+ selected date.
+
+ The currently displayed month and year can be retrieved using the
+ monthShown() and yearShown() functions respectively.
+
+ \sa yearShown(), monthShown(), showPreviousMonth(), showNextMonth(),
+ showPreviousYear(), showNextYear()
+*/
+
+void QCalendarWidget::setCurrentPage(int year, int month)
+{
+ Q_D(QCalendarWidget);
+ QDate currentDate = d->getCurrentDate();
+ int day = currentDate.day();
+ int daysInMonths = QDate(year, month, 1).daysInMonth();
+ if (day > daysInMonths)
+ day = daysInMonths;
+
+ d->showMonth(year, month);
+
+ QDate newDate(year, month, day);
+ int row = -1, col = -1;
+ d->m_model->cellForDate(newDate, &row, &col);
+ if (row != -1 && col != -1) {
+ d->m_view->selectionModel()->setCurrentIndex(d->m_model->index(row, col),
+ QItemSelectionModel::NoUpdate);
+ }
+}
+
+/*!
+ Shows the next month relative to the currently displayed
+ month. Note that the selected date is not changed.
+
+ \sa showPreviousMonth(), setCurrentPage(), setSelectedDate()
+*/
+
+void QCalendarWidget::showNextMonth()
+{
+ int year = yearShown();
+ int month = monthShown();
+ if (month == 12) {
+ ++year;
+ month = 1;
+ } else {
+ ++month;
+ }
+ setCurrentPage(year, month);
+}
+
+/*!
+ Shows the previous month relative to the currently displayed
+ month. Note that the selected date is not changed.
+
+ \sa showNextMonth(), setCurrentPage(), setSelectedDate()
+*/
+
+void QCalendarWidget::showPreviousMonth()
+{
+ int year = yearShown();
+ int month = monthShown();
+ if (month == 1) {
+ --year;
+ month = 12;
+ } else {
+ --month;
+ }
+ setCurrentPage(year, month);
+}
+
+/*!
+ Shows the currently displayed month in the \e next year relative
+ to the currently displayed year. Note that the selected date is
+ not changed.
+
+ \sa showPreviousYear(), setCurrentPage(), setSelectedDate()
+*/
+
+void QCalendarWidget::showNextYear()
+{
+ int year = yearShown();
+ int month = monthShown();
+ ++year;
+ setCurrentPage(year, month);
+}
+
+/*!
+ Shows the currently displayed month in the \e previous year
+ relative to the currently displayed year. Note that the selected
+ date is not changed.
+
+ \sa showNextYear(), setCurrentPage(), setSelectedDate()
+*/
+
+void QCalendarWidget::showPreviousYear()
+{
+ int year = yearShown();
+ int month = monthShown();
+ --year;
+ setCurrentPage(year, month);
+}
+
+/*!
+ Shows the month of the selected date.
+
+ \sa selectedDate(), setCurrentPage()
+*/
+void QCalendarWidget::showSelectedDate()
+{
+ QDate currentDate = selectedDate();
+ setCurrentPage(currentDate.year(), currentDate.month());
+}
+
+/*!
+ Shows the month of the today's date.
+
+ \sa selectedDate(), setCurrentPage()
+*/
+void QCalendarWidget::showToday()
+{
+ QDate currentDate = QDate::currentDate();
+ setCurrentPage(currentDate.year(), currentDate.month());
+}
+
+/*!
+ \property QCalendarWidget::minimumDate
+ \brief the minimum date of the currently specified date range.
+
+ The user will not be able to select a date that is before the
+ currently set minimum date.
+
+ \table
+ \row
+ \o \image qcalendarwidget-minimum.png
+ \row
+ \o
+ \snippet doc/src/snippets/code/src_gui_widgets_qcalendarwidget.cpp 1
+ \endtable
+
+ By default, the minimum date is the earliest date that the QDate
+ class can handle.
+
+ When setting a minimum date, the maximumDate and selectedDate
+ properties are adjusted if the selection range becomes invalid. If
+ the provided date is not a valid QDate object, the
+ setMinimumDate() function does nothing.
+
+ \sa setDateRange()
+*/
+
+QDate QCalendarWidget::minimumDate() const
+{
+ Q_D(const QCalendarWidget);
+ return d->m_model->m_minimumDate;
+}
+
+void QCalendarWidget::setMinimumDate(const QDate &date)
+{
+ Q_D(QCalendarWidget);
+ if (!date.isValid() || d->m_model->m_minimumDate == date)
+ return;
+
+ QDate oldDate = d->m_model->m_date;
+ d->m_model->setMinimumDate(date);
+ d->yearEdit->setMinimum(d->m_model->m_minimumDate.year());
+ d->updateMonthMenu();
+ QDate newDate = d->m_model->m_date;
+ if (oldDate != newDate) {
+ d->update();
+ d->showMonth(newDate.year(), newDate.month());
+ d->m_navigator->setDate(newDate);
+ emit selectionChanged();
+ }
+}
+
+/*!
+ \property QCalendarWidget::maximumDate
+ \brief the maximum date of the currently specified date range.
+
+ The user will not be able to select a date which is after the
+ currently set maximum date.
+
+ \table
+ \row
+ \o \image qcalendarwidget-maximum.png
+ \row
+ \o
+ \snippet doc/src/snippets/code/src_gui_widgets_qcalendarwidget.cpp 2
+ \endtable
+
+ By default, the maximum date is the last day the QDate class can
+ handle.
+
+ When setting a maximum date, the minimumDate and selectedDate
+ properties are adjusted if the selection range becomes invalid. If
+ the provided date is not a valid QDate object, the
+ setMaximumDate() function does nothing.
+
+ \sa setDateRange()
+*/
+
+QDate QCalendarWidget::maximumDate() const
+{
+ Q_D(const QCalendarWidget);
+ return d->m_model->m_maximumDate;
+}
+
+void QCalendarWidget::setMaximumDate(const QDate &date)
+{
+ Q_D(QCalendarWidget);
+ if (!date.isValid() || d->m_model->m_maximumDate == date)
+ return;
+
+ QDate oldDate = d->m_model->m_date;
+ d->m_model->setMaximumDate(date);
+ d->yearEdit->setMaximum(d->m_model->m_maximumDate.year());
+ d->updateMonthMenu();
+ QDate newDate = d->m_model->m_date;
+ if (oldDate != newDate) {
+ d->update();
+ d->showMonth(newDate.year(), newDate.month());
+ d->m_navigator->setDate(newDate);
+ emit selectionChanged();
+ }
+}
+
+/*!
+ Defines a date range by setting the minimumDate and maximumDate
+ properties.
+
+ The date range restricts the user selection, i.e. the user can
+ only select dates within the specified date range. Note that
+
+ \snippet doc/src/snippets/code/src_gui_widgets_qcalendarwidget.cpp 3
+
+ is analogous to
+
+ \snippet doc/src/snippets/code/src_gui_widgets_qcalendarwidget.cpp 4
+
+ If either the \a min or \a max parameters are not valid QDate
+ objects, this function does nothing.
+
+ \sa setMinimumDate(), setMaximumDate()
+*/
+
+void QCalendarWidget::setDateRange(const QDate &min, const QDate &max)
+{
+ Q_D(QCalendarWidget);
+ if (d->m_model->m_minimumDate == min && d->m_model->m_maximumDate == max)
+ return;
+ if (!min.isValid() || !max.isValid())
+ return;
+
+ QDate oldDate = d->m_model->m_date;
+ d->m_model->setRange(min, max);
+ d->yearEdit->setMinimum(d->m_model->m_minimumDate.year());
+ d->yearEdit->setMaximum(d->m_model->m_maximumDate.year());
+ d->updateMonthMenu();
+ QDate newDate = d->m_model->m_date;
+ if (oldDate != newDate) {
+ d->update();
+ d->showMonth(newDate.year(), newDate.month());
+ d->m_navigator->setDate(newDate);
+ emit selectionChanged();
+ }
+}
+
+
+/*! \enum QCalendarWidget::HorizontalHeaderFormat
+
+ This enum type defines the various formats the horizontal header can display.
+
+ \value SingleLetterDayNames The header displays a single letter abbreviation for day names (e.g. M for Monday).
+ \value ShortDayNames The header displays a short abbreviation for day names (e.g. Mon for Monday).
+ \value LongDayNames The header displays complete day names (e.g. Monday).
+ \value NoHorizontalHeader The header is hidden.
+
+ \sa horizontalHeaderFormat(), VerticalHeaderFormat
+*/
+
+/*!
+ \property QCalendarWidget::horizontalHeaderFormat
+ \brief the format of the horizontal header.
+
+ The default value is QCalendarWidget::ShortDayNames.
+*/
+
+void QCalendarWidget::setHorizontalHeaderFormat(QCalendarWidget::HorizontalHeaderFormat format)
+{
+ Q_D(QCalendarWidget);
+ if (d->m_model->m_horizontalHeaderFormat == format)
+ return;
+
+ d->m_model->setHorizontalHeaderFormat(format);
+ d->cachedSizeHint = QSize();
+ d->m_view->viewport()->update();
+ d->m_view->updateGeometry();
+}
+
+QCalendarWidget::HorizontalHeaderFormat QCalendarWidget::horizontalHeaderFormat() const
+{
+ Q_D(const QCalendarWidget);
+ return d->m_model->m_horizontalHeaderFormat;
+}
+
+
+/*!
+ \enum QCalendarWidget::VerticalHeaderFormat
+
+ This enum type defines the various formats the vertical header can display.
+
+ \value ISOWeekNumbers The header displays ISO week numbers as described by \l QDate::weekNumber().
+ \value NoVerticalHeader The header is hidden.
+
+ \sa verticalHeaderFormat(), HorizontalHeaderFormat
+*/
+
+/*!
+ \property QCalendarWidget::verticalHeaderFormat
+ \brief the format of the vertical header.
+
+ The default value is QCalendarWidget::ISOWeekNumber.
+*/
+
+QCalendarWidget::VerticalHeaderFormat QCalendarWidget::verticalHeaderFormat() const
+{
+ Q_D(const QCalendarWidget);
+ bool shown = d->m_model->weekNumbersShown();
+ if (shown)
+ return QCalendarWidget::ISOWeekNumbers;
+ return QCalendarWidget::NoVerticalHeader;
+}
+
+void QCalendarWidget::setVerticalHeaderFormat(QCalendarWidget::VerticalHeaderFormat format)
+{
+ Q_D(QCalendarWidget);
+ bool show = false;
+ if (format == QCalendarWidget::ISOWeekNumbers)
+ show = true;
+ if (d->m_model->weekNumbersShown() == show)
+ return;
+ d->m_model->setWeekNumbersShown(show);
+ d->cachedSizeHint = QSize();
+ d->m_view->viewport()->update();
+ d->m_view->updateGeometry();
+}
+
+/*!
+ \property QCalendarWidget::gridVisible
+ \brief whether the table grid is displayed.
+
+ \table
+ \row
+ \o \inlineimage qcalendarwidget-grid.png
+ \row
+ \o
+ \snippet doc/src/snippets/code/src_gui_widgets_qcalendarwidget.cpp 5
+ \endtable
+
+ The default value is false.
+*/
+
+bool QCalendarWidget::isGridVisible() const
+{
+ Q_D(const QCalendarWidget);
+ return d->m_view->showGrid();
+}
+
+void QCalendarWidget::setGridVisible(bool show)
+{
+ Q_D(QCalendarWidget);
+ d->m_view->setShowGrid(show);
+ d->cachedSizeHint = QSize();
+ d->m_view->viewport()->update();
+ d->m_view->updateGeometry();
+}
+
+/*!
+ \property QCalendarWidget::selectionMode
+ \brief the type of selection the user can make in the calendar
+
+ When this property is set to SingleSelection, the user can select a date
+ within the minimum and maximum allowed dates, using either the mouse or
+ the keyboard.
+
+ When the property is set to NoSelection, the user will be unable to select
+ dates, but they can still be selected programmatically. Note that the date
+ that is selected when the property is set to NoSelection will still be
+ the selected date of the calendar.
+
+ The default value is SingleSelection.
+*/
+
+QCalendarWidget::SelectionMode QCalendarWidget::selectionMode() const
+{
+ Q_D(const QCalendarWidget);
+ return d->m_view->readOnly ? QCalendarWidget::NoSelection : QCalendarWidget::SingleSelection;
+}
+
+void QCalendarWidget::setSelectionMode(SelectionMode mode)
+{
+ Q_D(QCalendarWidget);
+ d->m_view->readOnly = (mode == QCalendarWidget::NoSelection);
+ d->setNavigatorEnabled(isDateEditEnabled() && (selectionMode() != QCalendarWidget::NoSelection));
+ d->update();
+}
+
+/*!
+ \property QCalendarWidget::firstDayOfWeek
+ \brief a value identifying the day displayed in the first column.
+
+ By default, the day displayed in the first column is Sunday
+*/
+
+void QCalendarWidget::setFirstDayOfWeek(Qt::DayOfWeek dayOfWeek)
+{
+ Q_D(QCalendarWidget);
+ if ((Qt::DayOfWeek)d->m_model->firstColumnDay() == dayOfWeek)
+ return;
+
+ d->m_model->setFirstColumnDay(dayOfWeek);
+ d->update();
+}
+
+Qt::DayOfWeek QCalendarWidget::firstDayOfWeek() const
+{
+ Q_D(const QCalendarWidget);
+ return (Qt::DayOfWeek)d->m_model->firstColumnDay();
+}
+
+/*!
+ Returns the text char format for rendering the header.
+*/
+QTextCharFormat QCalendarWidget::headerTextFormat() const
+{
+ Q_D(const QCalendarWidget);
+ return d->m_model->m_headerFormat;
+}
+
+/*!
+ Sets the text char format for rendering the header to \a format.
+ If you also set a weekday text format, this format's foreground and
+ background color will take precedence over the header's format.
+ The other formatting information will still be decided by
+ the header's format.
+*/
+void QCalendarWidget::setHeaderTextFormat(const QTextCharFormat &format)
+{
+ Q_D(QCalendarWidget);
+ d->m_model->m_headerFormat = format;
+ d->cachedSizeHint = QSize();
+ d->m_view->viewport()->update();
+ d->m_view->updateGeometry();
+}
+
+/*!
+ Returns the text char format for rendering of day in the week \a dayOfWeek.
+
+ \sa headerTextFormat()
+*/
+QTextCharFormat QCalendarWidget::weekdayTextFormat(Qt::DayOfWeek dayOfWeek) const
+{
+ Q_D(const QCalendarWidget);
+ return d->m_model->m_dayFormats.value(dayOfWeek);
+}
+
+/*!
+ Sets the text char format for rendering of day in the week \a dayOfWeek to \a format.
+ The format will take precedence over the header format in case of foreground
+ and background color. Other text formatting information is taken from the headers format.
+
+ \sa setHeaderTextFormat()
+*/
+void QCalendarWidget::setWeekdayTextFormat(Qt::DayOfWeek dayOfWeek, const QTextCharFormat &format)
+{
+ Q_D(QCalendarWidget);
+ d->m_model->m_dayFormats[dayOfWeek] = format;
+ d->cachedSizeHint = QSize();
+ d->m_view->viewport()->update();
+ d->m_view->updateGeometry();
+}
+
+/*!
+ Returns a QMap from QDate to QTextCharFormat showing all dates
+ that use a special format that alters their rendering.
+*/
+QMap<QDate, QTextCharFormat> QCalendarWidget::dateTextFormat() const
+{
+ Q_D(const QCalendarWidget);
+ return d->m_model->m_dateFormats;
+}
+
+/*!
+ Returns a QTextCharFormat for \a date. The char format can be be
+ empty if the date is not renderd specially.
+*/
+QTextCharFormat QCalendarWidget::dateTextFormat(const QDate &date) const
+{
+ Q_D(const QCalendarWidget);
+ return d->m_model->m_dateFormats.value(date);
+}
+
+/*!
+ Sets the format used to render the given \a date to that specified by \a format.
+
+ If \a date is null, all date formats are cleared.
+*/
+void QCalendarWidget::setDateTextFormat(const QDate &date, const QTextCharFormat &format)
+{
+ Q_D(QCalendarWidget);
+ if (date.isNull())
+ d->m_model->m_dateFormats.clear();
+ else
+ d->m_model->m_dateFormats[date] = format;
+ d->m_view->viewport()->update();
+ d->m_view->updateGeometry();
+}
+
+/*!
+ \property QCalendarWidget::dateEditEnabled
+ \brief whether the date edit popup is enabled
+ \since 4.3
+
+ If this property is enabled, pressing a non-modifier key will cause a
+ date edit to popup if the calendar widget has focus, allowing the user
+ to specify a date in the form specified by the current locale.
+
+ By default, this property is enabled.
+
+ The date edit is simpler in appearance than QDateEdit, but allows the
+ user to navigate between fields using the left and right cursor keys,
+ increment and decrement individual fields using the up and down cursor
+ keys, and enter values directly using the number keys.
+
+ \sa QCalendarWidget::dateEditAcceptDelay
+*/
+bool QCalendarWidget::isDateEditEnabled() const
+{
+ Q_D(const QCalendarWidget);
+ return d->m_dateEditEnabled;
+}
+
+void QCalendarWidget::setDateEditEnabled(bool enable)
+{
+ Q_D(QCalendarWidget);
+ if (isDateEditEnabled() == enable)
+ return;
+
+ d->m_dateEditEnabled = enable;
+
+ d->setNavigatorEnabled(enable && (selectionMode() != QCalendarWidget::NoSelection));
+}
+
+/*!
+ \property QCalendarWidget::dateEditAcceptDelay
+ \brief the time an inactive date edit is shown before its contents are accepted
+ \since 4.3
+
+ If the calendar widget's \l{dateEditEnabled}{date edit is enabled}, this
+ property specifies the amount of time (in millseconds) that the date edit
+ remains open after the most recent user input. Once this time has elapsed,
+ the date specified in the date edit is accepted and the popup is closed.
+
+ By default, the delay is defined to be 1500 milliseconds (1.5 seconds).
+*/
+int QCalendarWidget::dateEditAcceptDelay() const
+{
+ Q_D(const QCalendarWidget);
+ return d->m_navigator->dateEditAcceptDelay();
+}
+
+void QCalendarWidget::setDateEditAcceptDelay(int delay)
+{
+ Q_D(QCalendarWidget);
+ d->m_navigator->setDateEditAcceptDelay(delay);
+}
+
+/*!
+ \since 4.4
+
+ Updates the cell specified by the given \a date unless updates
+ are disabled or the cell is hidden.
+
+ \sa updateCells(), yearShown(), monthShown()
+*/
+void QCalendarWidget::updateCell(const QDate &date)
+{
+ if (!date.isValid()) {
+ qWarning("QCalendarWidget::updateCell: Invalid date");
+ return;
+ }
+
+ if (!isVisible())
+ return;
+
+ Q_D(QCalendarWidget);
+ int row, column;
+ d->m_model->cellForDate(date, &row, &column);
+ if (row == -1 || column == -1)
+ return;
+
+ QModelIndex modelIndex = d->m_model->index(row, column);
+ if (!modelIndex.isValid())
+ return;
+
+ d->m_view->viewport()->update(d->m_view->visualRect(modelIndex));
+}
+
+/*!
+ \since 4.4
+
+ Updates all visible cells unless updates are disabled.
+
+ \sa updateCell()
+*/
+void QCalendarWidget::updateCells()
+{
+ Q_D(QCalendarWidget);
+ if (isVisible())
+ d->m_view->viewport()->update();
+}
+
+/*!
+ \fn void QCalendarWidget::selectionChanged()
+
+ This signal is emitted when the currently selected date is
+ changed.
+
+ The currently selected date can be changed by the user using the
+ mouse or keyboard, or by the programmer using setSelectedDate().
+
+ \sa selectedDate()
+*/
+
+/*!
+ \fn void QCalendarWidget::currentPageChanged(int year, int month)
+
+ This signal is emitted when the currently shown month is changed.
+ The new \a year and \a month are passed as parameters.
+
+ \sa setCurrentPage()
+*/
+
+/*!
+ \fn void QCalendarWidget::activated(const QDate &date)
+
+ This signal is emitted whenever the user presses the Return or
+ Enter key or double-clicks a \a date in the calendar
+ widget.
+*/
+
+/*!
+ \fn void QCalendarWidget::clicked(const QDate &date)
+
+ This signal is emitted when a mouse button is clicked. The date
+ the mouse was clicked on is specified by \a date. The signal is
+ only emitted when clicked on a valid date, e.g., dates are not
+ outside the minimumDate() and maximumDate(). If the selection mode
+ is NoSelection, this signal will not be emitted.
+
+*/
+
+/*!
+ \property QCalendarWidget::headerVisible
+ \brief whether the navigation bar is shown or not
+
+ \obsolete
+
+ Use navigationBarVisible() instead.
+
+ By default, this property is true.
+*/
+
+/*!
+ \obsolete
+
+ Use setNavigationBarVisible() instead.
+*/
+bool QCalendarWidget::isHeaderVisible() const
+{
+ Q_D(const QCalendarWidget);
+ return d->navBarVisible;
+}
+
+/*!
+ \obsolete
+
+ Use setNavigationBarVisible() instead.
+
+*/
+void QCalendarWidget::setHeaderVisible(bool visible)
+{
+ setNavigationBarVisible(visible);
+}
+
+/*!
+ \property QCalendarWidget::navigationBarVisible
+ \brief whether the navigation bar is shown or not
+
+ \since 4.3
+
+ When this property is true (the default), the next month,
+ previous month, month selection, year selection controls are
+ shown on top.
+
+ When the property is set to false, these controls are hidden.
+*/
+
+void QCalendarWidget::setNavigationBarVisible(bool visible)
+{
+ Q_D(QCalendarWidget);
+ d->navBarVisible = visible;
+ d->cachedSizeHint = QSize();
+ d->navBarBackground->setVisible(visible);
+ updateGeometry();
+}
+
+/*!
+ \reimp
+*/
+bool QCalendarWidget::event(QEvent *event)
+{
+ Q_D(QCalendarWidget);
+ switch (event->type()) {
+ case QEvent::LayoutDirectionChange:
+ d->updateButtonIcons();
+ case QEvent::LocaleChange:
+ d->cachedSizeHint = QSize();
+ d->updateMonthMenuNames();
+ d->updateNavigationBar();
+ d->m_view->updateGeometry();
+ break;
+ case QEvent::FontChange:
+ case QEvent::ApplicationFontChange:
+ d->cachedSizeHint = QSize();
+ d->m_view->updateGeometry();
+ break;
+ case QEvent::StyleChange:
+ d->cachedSizeHint = QSize();
+ d->m_view->updateGeometry();
+ default:
+ break;
+ }
+ return QWidget::event(event);
+}
+
+/*!
+ \reimp
+*/
+bool QCalendarWidget::eventFilter(QObject *watched, QEvent *event)
+{
+ Q_D(QCalendarWidget);
+ if (event->type() == QEvent::MouseButtonPress && d->yearEdit->hasFocus()) {
+ QWidget *tlw = window();
+ QWidget *widget = static_cast<QWidget*>(watched);
+ //as we have a event filter on the whole application we first make sure that the top level widget
+ //of both this and the watched widget are the same to decide if we should finish the year edition.
+ if (widget->window() == tlw) {
+ QPoint mousePos = widget->mapTo(tlw, static_cast<QMouseEvent *>(event)->pos());
+ QRect geom = QRect(d->yearEdit->mapTo(tlw, QPoint(0, 0)), d->yearEdit->size());
+ if (!geom.contains(mousePos)) {
+ event->accept();
+ d->_q_yearEditingFinished();
+ setFocus();
+ return true;
+ }
+ }
+ }
+ return QWidget::eventFilter(watched, event);
+}
+
+/*!
+ \reimp
+*/
+void QCalendarWidget::mousePressEvent(QMouseEvent *event)
+{
+ setAttribute(Qt::WA_NoMouseReplay);
+ QWidget::mousePressEvent(event);
+ setFocus();
+}
+
+/*!
+ \reimp
+*/
+void QCalendarWidget::resizeEvent(QResizeEvent * event)
+{
+ Q_D(QCalendarWidget);
+
+ // XXX Should really use a QWidgetStack for yearEdit and yearButton,
+ // XXX here we hide the year edit when the layout is likely to break
+ // XXX the manual positioning of the yearEdit over the yearButton.
+ if(d->yearEdit->isVisible() && event->size().width() != event->oldSize().width())
+ d->_q_yearEditingFinished();
+
+ QWidget::resizeEvent(event);
+}
+
+/*!
+ \reimp
+*/
+void QCalendarWidget::keyPressEvent(QKeyEvent * event)
+{
+ Q_D(QCalendarWidget);
+ if(d->yearEdit->isVisible()&& event->key() == Qt::Key_Escape)
+ {
+ d->yearEdit->setValue(yearShown());
+ d->_q_yearEditingFinished();
+ return;
+ }
+ QWidget::keyPressEvent(event);
+}
+
+QT_END_NAMESPACE
+
+#include "qcalendarwidget.moc"
+#include "moc_qcalendarwidget.cpp"
+
+#endif //QT_NO_CALENDARWIDGET