src/gui/widgets/qcalendarwidget.cpp
changeset 0 1918ee327afb
child 3 41300fa6a67c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/gui/widgets/qcalendarwidget.cpp	Mon Jan 11 14:00:40 2010 +0000
@@ -0,0 +1,3090 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 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);
+    d->showMonth(year, month);
+}
+
+/*!
+    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