src/gui/widgets/qcalendarwidget.cpp
changeset 0 1918ee327afb
child 3 41300fa6a67c
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the QtGui module of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 #include "qcalendarwidget.h"
       
    43 
       
    44 #ifndef QT_NO_CALENDARWIDGET
       
    45 
       
    46 #include <qabstractitemmodel.h>
       
    47 #include <qitemdelegate.h>
       
    48 #include <qdatetime.h>
       
    49 #include <qtableview.h>
       
    50 #include <qlayout.h>
       
    51 #include <qevent.h>
       
    52 #include <qtextformat.h>
       
    53 #include <qheaderview.h>
       
    54 #include <private/qwidget_p.h>
       
    55 #include <qpushbutton.h>
       
    56 #include <qtoolbutton.h>
       
    57 #include <qlabel.h>
       
    58 #include <qspinbox.h>
       
    59 #include <qmenu.h>
       
    60 #include <qapplication.h>
       
    61 #include <qbasictimer.h>
       
    62 #include <qstylepainter.h>
       
    63 #include <private/qcalendartextnavigator_p.h>
       
    64 
       
    65 QT_BEGIN_NAMESPACE
       
    66 
       
    67 enum {
       
    68     RowCount = 6,
       
    69     ColumnCount = 7,
       
    70     HeaderColumn = 0,
       
    71     HeaderRow = 0,
       
    72     MinimumDayOffset = 1
       
    73 };
       
    74 
       
    75 class QCalendarDateSectionValidator
       
    76 {
       
    77 public:
       
    78 
       
    79     enum Section {
       
    80         NextSection,
       
    81         ThisSection,
       
    82         PrevSection
       
    83     };
       
    84 
       
    85     QCalendarDateSectionValidator() {}
       
    86     virtual ~QCalendarDateSectionValidator() {}
       
    87     virtual Section handleKey(int key) = 0;
       
    88     virtual QDate applyToDate(const QDate &date) const = 0;
       
    89     virtual void setDate(const QDate &date) = 0;
       
    90     virtual QString text() const = 0;
       
    91     virtual QString text(const QDate &date, int repeat) const = 0;
       
    92 
       
    93     QLocale m_locale;
       
    94 
       
    95 protected:
       
    96     QString highlightString(const QString &str, int pos) const;
       
    97 private:
       
    98 };
       
    99 
       
   100 QString QCalendarDateSectionValidator::highlightString(const QString &str, int pos) const
       
   101 {
       
   102     if (pos == 0)
       
   103         return QLatin1String("<b>") + str + QLatin1String("</b>");
       
   104     int startPos = str.length() - pos;
       
   105     return str.mid(0, startPos) + QLatin1String("<b>") + str.mid(startPos, pos) + QLatin1String("</b>");
       
   106 
       
   107 }
       
   108 
       
   109 class QCalendarDayValidator : public QCalendarDateSectionValidator
       
   110 {
       
   111 
       
   112 public:
       
   113     QCalendarDayValidator();
       
   114     virtual Section handleKey(int key);
       
   115     virtual QDate applyToDate(const QDate &date) const;
       
   116     virtual void setDate(const QDate &date);
       
   117     virtual QString text() const;
       
   118     virtual QString text(const QDate &date, int repeat) const;
       
   119 private:
       
   120     int m_pos;
       
   121     int m_day;
       
   122     int m_oldDay;
       
   123 };
       
   124 
       
   125 QCalendarDayValidator::QCalendarDayValidator()
       
   126     : QCalendarDateSectionValidator(), m_pos(0), m_day(1), m_oldDay(1)
       
   127 {
       
   128 }
       
   129 
       
   130 QCalendarDateSectionValidator::Section QCalendarDayValidator::handleKey(int key)
       
   131 {
       
   132     if (key == Qt::Key_Right || key == Qt::Key_Left) {
       
   133         m_pos = 0;
       
   134         return QCalendarDateSectionValidator::ThisSection;
       
   135     } else if (key == Qt::Key_Up) {
       
   136         m_pos = 0;
       
   137         ++m_day;
       
   138         if (m_day > 31)
       
   139             m_day = 1;
       
   140         return QCalendarDateSectionValidator::ThisSection;
       
   141     } else if (key == Qt::Key_Down) {
       
   142         m_pos = 0;
       
   143         --m_day;
       
   144         if (m_day < 1)
       
   145             m_day = 31;
       
   146         return QCalendarDateSectionValidator::ThisSection;
       
   147     } else if (key == Qt::Key_Back || key == Qt::Key_Backspace) {
       
   148         --m_pos;
       
   149         if (m_pos < 0)
       
   150             m_pos = 1;
       
   151 
       
   152         if (m_pos == 0)
       
   153             m_day = m_oldDay;
       
   154         else
       
   155             m_day = m_day / 10;
       
   156             //m_day = m_oldDay / 10 * 10 + m_day / 10;
       
   157 
       
   158         if (m_pos == 0)
       
   159             return QCalendarDateSectionValidator::PrevSection;
       
   160         return QCalendarDateSectionValidator::ThisSection;
       
   161     }
       
   162     if (key < Qt::Key_0 || key > Qt::Key_9)
       
   163         return QCalendarDateSectionValidator::ThisSection;
       
   164     int pressedKey = key - Qt::Key_0;
       
   165     if (m_pos == 0)
       
   166         m_day = pressedKey;
       
   167     else
       
   168         m_day = m_day % 10 * 10 + pressedKey;
       
   169     if (m_day > 31)
       
   170         m_day = 31;
       
   171     ++m_pos;
       
   172     if (m_pos > 1) {
       
   173         m_pos = 0;
       
   174         return QCalendarDateSectionValidator::NextSection;
       
   175     }
       
   176     return QCalendarDateSectionValidator::ThisSection;
       
   177 }
       
   178 
       
   179 QDate QCalendarDayValidator::applyToDate(const QDate &date) const
       
   180 {
       
   181     int day = m_day;
       
   182     if (day < 1)
       
   183         day = 1;
       
   184     else if (day > 31)
       
   185         day = 31;
       
   186     if (day > date.daysInMonth())
       
   187         day = date.daysInMonth();
       
   188     return QDate(date.year(), date.month(), day);
       
   189 }
       
   190 
       
   191 void QCalendarDayValidator::setDate(const QDate &date)
       
   192 {
       
   193     m_day = m_oldDay = date.day();
       
   194     m_pos = 0;
       
   195 }
       
   196 
       
   197 QString QCalendarDayValidator::text() const
       
   198 {
       
   199     QString str;
       
   200     if (m_day / 10 == 0)
       
   201         str += QLatin1Char('0');
       
   202     str += QString::number(m_day);
       
   203     return highlightString(str, m_pos);
       
   204 }
       
   205 
       
   206 QString QCalendarDayValidator::text(const QDate &date, int repeat) const
       
   207 {
       
   208     if (repeat <= 1) {
       
   209         return QString::number(date.day());
       
   210     } else if (repeat == 2) {
       
   211         QString str;
       
   212         if (date.day() / 10 == 0)
       
   213             str += QLatin1Char('0');
       
   214         return str + QString::number(date.day());
       
   215     } else if (repeat == 3) {
       
   216         return m_locale.dayName(date.dayOfWeek(), QLocale::ShortFormat);
       
   217     } else if (repeat >= 4) {
       
   218         return m_locale.dayName(date.dayOfWeek(), QLocale::LongFormat);
       
   219     }
       
   220     return QString();
       
   221 }
       
   222 
       
   223 //////////////////////////////////
       
   224 
       
   225 class QCalendarMonthValidator : public QCalendarDateSectionValidator
       
   226 {
       
   227 
       
   228 public:
       
   229     QCalendarMonthValidator();
       
   230     virtual Section handleKey(int key);
       
   231     virtual QDate applyToDate(const QDate &date) const;
       
   232     virtual void setDate(const QDate &date);
       
   233     virtual QString text() const;
       
   234     virtual QString text(const QDate &date, int repeat) const;
       
   235 private:
       
   236     int m_pos;
       
   237     int m_month;
       
   238     int m_oldMonth;
       
   239 };
       
   240 
       
   241 QCalendarMonthValidator::QCalendarMonthValidator()
       
   242     : QCalendarDateSectionValidator(), m_pos(0), m_month(1), m_oldMonth(1)
       
   243 {
       
   244 }
       
   245 
       
   246 QCalendarDateSectionValidator::Section QCalendarMonthValidator::handleKey(int key)
       
   247 {
       
   248     if (key == Qt::Key_Right || key == Qt::Key_Left) {
       
   249         m_pos = 0;
       
   250         return QCalendarDateSectionValidator::ThisSection;
       
   251     } else if (key == Qt::Key_Up) {
       
   252         m_pos = 0;
       
   253         ++m_month;
       
   254         if (m_month > 12)
       
   255             m_month = 1;
       
   256         return QCalendarDateSectionValidator::ThisSection;
       
   257     } else if (key == Qt::Key_Down) {
       
   258         m_pos = 0;
       
   259         --m_month;
       
   260         if (m_month < 1)
       
   261             m_month = 12;
       
   262         return QCalendarDateSectionValidator::ThisSection;
       
   263     } else if (key == Qt::Key_Back || key == Qt::Key_Backspace) {
       
   264         --m_pos;
       
   265         if (m_pos < 0)
       
   266             m_pos = 1;
       
   267 
       
   268         if (m_pos == 0)
       
   269             m_month = m_oldMonth;
       
   270         else
       
   271             m_month = m_month / 10;
       
   272             //m_month = m_oldMonth / 10 * 10 + m_month / 10;
       
   273 
       
   274         if (m_pos == 0)
       
   275             return QCalendarDateSectionValidator::PrevSection;
       
   276         return QCalendarDateSectionValidator::ThisSection;
       
   277     }
       
   278     if (key < Qt::Key_0 || key > Qt::Key_9)
       
   279         return QCalendarDateSectionValidator::ThisSection;
       
   280     int pressedKey = key - Qt::Key_0;
       
   281     if (m_pos == 0)
       
   282         m_month = pressedKey;
       
   283     else
       
   284         m_month = m_month % 10 * 10 + pressedKey;
       
   285     if (m_month > 12)
       
   286         m_month = 12;
       
   287     ++m_pos;
       
   288     if (m_pos > 1) {
       
   289         m_pos = 0;
       
   290         return QCalendarDateSectionValidator::NextSection;
       
   291     }
       
   292     return QCalendarDateSectionValidator::ThisSection;
       
   293 }
       
   294 
       
   295 QDate QCalendarMonthValidator::applyToDate(const QDate &date) const
       
   296 {
       
   297     int month = m_month;
       
   298     if (month < 1)
       
   299         month = 1;
       
   300     else if (month > 12)
       
   301         month = 12;
       
   302     QDate newDate(date.year(), m_month, 1);
       
   303     int day = date.day();
       
   304     if (day > newDate.daysInMonth())
       
   305         day = newDate.daysInMonth();
       
   306     return QDate(date.year(), month, day);
       
   307 }
       
   308 
       
   309 void QCalendarMonthValidator::setDate(const QDate &date)
       
   310 {
       
   311     m_month = m_oldMonth = date.month();
       
   312     m_pos = 0;
       
   313 }
       
   314 
       
   315 QString QCalendarMonthValidator::text() const
       
   316 {
       
   317     QString str;
       
   318     if (m_month / 10 == 0)
       
   319         str += QLatin1Char('0');
       
   320     str += QString::number(m_month);
       
   321     return highlightString(str, m_pos);
       
   322 }
       
   323 
       
   324 QString QCalendarMonthValidator::text(const QDate &date, int repeat) const
       
   325 {
       
   326     if (repeat <= 1) {
       
   327         return QString::number(date.month());
       
   328     } else if (repeat == 2) {
       
   329         QString str;
       
   330         if (date.month() / 10 == 0)
       
   331             str += QLatin1Char('0');
       
   332         return str + QString::number(date.month());
       
   333     } else if (repeat == 3) {
       
   334         return m_locale.standaloneMonthName(date.month(), QLocale::ShortFormat);
       
   335     } else /*if (repeat >= 4)*/ {
       
   336         return m_locale.standaloneMonthName(date.month(), QLocale::LongFormat);
       
   337     }
       
   338 }
       
   339 
       
   340 //////////////////////////////////
       
   341 
       
   342 class QCalendarYearValidator : public QCalendarDateSectionValidator
       
   343 {
       
   344 
       
   345 public:
       
   346     QCalendarYearValidator();
       
   347     virtual Section handleKey(int key);
       
   348     virtual QDate applyToDate(const QDate &date) const;
       
   349     virtual void setDate(const QDate &date);
       
   350     virtual QString text() const;
       
   351     virtual QString text(const QDate &date, int repeat) const;
       
   352 private:
       
   353     int pow10(int n);
       
   354     int m_pos;
       
   355     int m_year;
       
   356     int m_oldYear;
       
   357 };
       
   358 
       
   359 QCalendarYearValidator::QCalendarYearValidator()
       
   360     : QCalendarDateSectionValidator(), m_pos(0), m_year(2000), m_oldYear(2000)
       
   361 {
       
   362 }
       
   363 
       
   364 int QCalendarYearValidator::pow10(int n)
       
   365 {
       
   366     int power = 1;
       
   367     for (int i = 0; i < n; i++)
       
   368         power *= 10;
       
   369     return power;
       
   370 }
       
   371 
       
   372 QCalendarDateSectionValidator::Section QCalendarYearValidator::handleKey(int key)
       
   373 {
       
   374     if (key == Qt::Key_Right || key == Qt::Key_Left) {
       
   375         m_pos = 0;
       
   376         return QCalendarDateSectionValidator::ThisSection;
       
   377     } else if (key == Qt::Key_Up) {
       
   378         m_pos = 0;
       
   379         ++m_year;
       
   380         return QCalendarDateSectionValidator::ThisSection;
       
   381     } else if (key == Qt::Key_Down) {
       
   382         m_pos = 0;
       
   383         --m_year;
       
   384         return QCalendarDateSectionValidator::ThisSection;
       
   385     } else if (key == Qt::Key_Back || key == Qt::Key_Backspace) {
       
   386         --m_pos;
       
   387         if (m_pos < 0)
       
   388             m_pos = 3;
       
   389 
       
   390         int pow = pow10(m_pos);
       
   391         m_year = m_oldYear / pow * pow + m_year % (pow * 10) / 10;
       
   392 
       
   393         if (m_pos == 0)
       
   394             return QCalendarDateSectionValidator::PrevSection;
       
   395         return QCalendarDateSectionValidator::ThisSection;
       
   396     }
       
   397     if (key < Qt::Key_0 || key > Qt::Key_9)
       
   398         return QCalendarDateSectionValidator::ThisSection;
       
   399     int pressedKey = key - Qt::Key_0;
       
   400     int pow = pow10(m_pos);
       
   401     m_year = m_year / (pow * 10) * (pow * 10) + m_year % pow * 10 + pressedKey;
       
   402     ++m_pos;
       
   403     if (m_pos > 3) {
       
   404         m_pos = 0;
       
   405         return QCalendarDateSectionValidator::NextSection;
       
   406     }
       
   407     return QCalendarDateSectionValidator::ThisSection;
       
   408 }
       
   409 
       
   410 QDate QCalendarYearValidator::applyToDate(const QDate &date) const
       
   411 {
       
   412     int year = m_year;
       
   413     if (year < 1)
       
   414         year = 1;
       
   415     QDate newDate(year, date.month(), 1);
       
   416     int day = date.day();
       
   417     if (day > newDate.daysInMonth())
       
   418         day = newDate.daysInMonth();
       
   419     return QDate(year, date.month(), day);
       
   420 }
       
   421 
       
   422 void QCalendarYearValidator::setDate(const QDate &date)
       
   423 {
       
   424     m_year = m_oldYear = date.year();
       
   425     m_pos = 0;
       
   426 }
       
   427 
       
   428 QString QCalendarYearValidator::text() const
       
   429 {
       
   430     QString str;
       
   431     int pow = 10;
       
   432     for (int i = 0; i < 3; i++) {
       
   433         if (m_year / pow == 0)
       
   434             str += QLatin1Char('0');
       
   435         pow *= 10;
       
   436     }
       
   437     str += QString::number(m_year);
       
   438     return highlightString(str, m_pos);
       
   439 }
       
   440 
       
   441 QString QCalendarYearValidator::text(const QDate &date, int repeat) const
       
   442 {
       
   443     if (repeat < 4) {
       
   444         QString str;
       
   445         int year = date.year() % 100;
       
   446         if (year / 10 == 0)
       
   447             str = QLatin1Char('0');
       
   448         return str + QString::number(year);
       
   449     }
       
   450     return QString::number(date.year());
       
   451 }
       
   452 
       
   453 ///////////////////////////////////
       
   454 
       
   455 class QCalendarDateValidator
       
   456 {
       
   457 public:
       
   458     QCalendarDateValidator();
       
   459     ~QCalendarDateValidator();
       
   460 
       
   461     void handleKeyEvent(QKeyEvent *keyEvent);
       
   462     QString currentText() const;
       
   463     QDate currentDate() const { return m_currentDate; }
       
   464     void setFormat(const QString &format);
       
   465     void setInitialDate(const QDate &date);
       
   466 
       
   467     void setLocale(const QLocale &locale);
       
   468 
       
   469 private:
       
   470 
       
   471     struct SectionToken {
       
   472         SectionToken(QCalendarDateSectionValidator *val, int rep) : validator(val), repeat(rep) {}
       
   473         QCalendarDateSectionValidator *validator;
       
   474         int repeat;
       
   475     };
       
   476 
       
   477     void toNextToken();
       
   478     void toPreviousToken();
       
   479     void applyToDate();
       
   480 
       
   481     int countRepeat(const QString &str, int index) const;
       
   482     void clear();
       
   483 
       
   484     QStringList m_separators;
       
   485     QList<SectionToken *> m_tokens;
       
   486     QCalendarDateSectionValidator *m_yearValidator;
       
   487     QCalendarDateSectionValidator *m_monthValidator;
       
   488     QCalendarDateSectionValidator *m_dayValidator;
       
   489 
       
   490     SectionToken *m_currentToken;
       
   491 
       
   492     QDate m_initialDate;
       
   493     QDate m_currentDate;
       
   494 
       
   495     QCalendarDateSectionValidator::Section m_lastSectionMove;
       
   496 };
       
   497 
       
   498 QCalendarDateValidator::QCalendarDateValidator()
       
   499     : m_currentToken(0), m_lastSectionMove(QCalendarDateSectionValidator::ThisSection)
       
   500 {
       
   501     m_initialDate = m_currentDate = QDate::currentDate();
       
   502     m_yearValidator = new QCalendarYearValidator();
       
   503     m_monthValidator = new QCalendarMonthValidator();
       
   504     m_dayValidator = new QCalendarDayValidator();
       
   505 }
       
   506 
       
   507 void QCalendarDateValidator::setLocale(const QLocale &locale)
       
   508 {
       
   509     m_yearValidator->m_locale = locale;
       
   510     m_monthValidator->m_locale = locale;
       
   511     m_dayValidator->m_locale = locale;
       
   512 }
       
   513 
       
   514 QCalendarDateValidator::~QCalendarDateValidator()
       
   515 {
       
   516     delete m_yearValidator;
       
   517     delete m_monthValidator;
       
   518     delete m_dayValidator;
       
   519     clear();
       
   520 }
       
   521 
       
   522 // from qdatetime.cpp
       
   523 int QCalendarDateValidator::countRepeat(const QString &str, int index) const
       
   524 {
       
   525     Q_ASSERT(index >= 0 && index < str.size());
       
   526     int count = 1;
       
   527     const QChar ch = str.at(index);
       
   528     while (index + count < str.size() && str.at(index + count) == ch)
       
   529         ++count;
       
   530     return count;
       
   531 }
       
   532 
       
   533 void QCalendarDateValidator::setInitialDate(const QDate &date)
       
   534 {
       
   535     m_yearValidator->setDate(date);
       
   536     m_monthValidator->setDate(date);
       
   537     m_dayValidator->setDate(date);
       
   538     m_initialDate = date;
       
   539     m_currentDate = date;
       
   540     m_lastSectionMove = QCalendarDateSectionValidator::ThisSection;
       
   541 }
       
   542 
       
   543 QString QCalendarDateValidator::currentText() const
       
   544 {
       
   545     QString str;
       
   546     QStringListIterator itSep(m_separators);
       
   547     QListIterator<SectionToken *> itTok(m_tokens);
       
   548     while (itSep.hasNext()) {
       
   549         str += itSep.next();
       
   550         if (itTok.hasNext()) {
       
   551             SectionToken *token = itTok.next();
       
   552             QCalendarDateSectionValidator *validator = token->validator;
       
   553             if (m_currentToken == token)
       
   554                 str += validator->text();
       
   555             else
       
   556                 str += validator->text(m_currentDate, token->repeat);
       
   557         }
       
   558     }
       
   559     return str;
       
   560 }
       
   561 
       
   562 void QCalendarDateValidator::clear()
       
   563 {
       
   564     QListIterator<SectionToken *> it(m_tokens);
       
   565     while (it.hasNext())
       
   566         delete it.next();
       
   567 
       
   568     m_tokens.clear();
       
   569     m_separators.clear();
       
   570 
       
   571     m_currentToken = 0;
       
   572 }
       
   573 
       
   574 void QCalendarDateValidator::setFormat(const QString &format)
       
   575 {
       
   576     clear();
       
   577 
       
   578     int pos = 0;
       
   579     const QLatin1Char quote('\'');
       
   580     bool quoting = false;
       
   581     QString separator;
       
   582     while (pos < format.size()) {
       
   583         QString mid = format.mid(pos);
       
   584         int offset = 1;
       
   585 
       
   586         if (mid.startsWith(quote)) {
       
   587             quoting = !quoting;
       
   588         } else {
       
   589             const QChar nextChar = format.at(pos);
       
   590             if (quoting) {
       
   591                 separator += nextChar;
       
   592             } else {
       
   593                 SectionToken *token = 0;
       
   594                 if (nextChar == QLatin1Char('d')) {
       
   595                     offset = qMin(4, countRepeat(format, pos));
       
   596                     token = new SectionToken(m_dayValidator, offset);
       
   597                 } else if (nextChar == QLatin1Char('M')) {
       
   598                     offset = qMin(4, countRepeat(format, pos));
       
   599                     token = new SectionToken(m_monthValidator, offset);
       
   600                 } else if (nextChar == QLatin1Char('y')) {
       
   601                     offset = qMin(4, countRepeat(format, pos));
       
   602                     token = new SectionToken(m_yearValidator, offset);
       
   603                 } else {
       
   604                     separator += nextChar;
       
   605                 }
       
   606                 if (token) {
       
   607                     m_tokens.append(token);
       
   608                     m_separators.append(separator);
       
   609                     separator = QString();
       
   610                     if (!m_currentToken)
       
   611                         m_currentToken = token;
       
   612 
       
   613                 }
       
   614             }
       
   615         }
       
   616         pos += offset;
       
   617     }
       
   618     m_separators += separator;
       
   619 }
       
   620 
       
   621 void QCalendarDateValidator::applyToDate()
       
   622 {
       
   623     m_currentDate = m_yearValidator->applyToDate(m_currentDate);
       
   624     m_currentDate = m_monthValidator->applyToDate(m_currentDate);
       
   625     m_currentDate = m_dayValidator->applyToDate(m_currentDate);
       
   626 }
       
   627 
       
   628 void QCalendarDateValidator::toNextToken()
       
   629 {
       
   630     const int idx = m_tokens.indexOf(m_currentToken);
       
   631     if (idx == -1)
       
   632         return;
       
   633     if (idx + 1 >= m_tokens.count())
       
   634         m_currentToken = m_tokens.first();
       
   635     else
       
   636         m_currentToken = m_tokens.at(idx + 1);
       
   637 }
       
   638 
       
   639 void QCalendarDateValidator::toPreviousToken()
       
   640 {
       
   641     const int idx = m_tokens.indexOf(m_currentToken);
       
   642     if (idx == -1)
       
   643         return;
       
   644     if (idx - 1 < 0)
       
   645         m_currentToken = m_tokens.last();
       
   646     else
       
   647         m_currentToken = m_tokens.at(idx - 1);
       
   648 }
       
   649 
       
   650 void QCalendarDateValidator::handleKeyEvent(QKeyEvent *keyEvent)
       
   651 {
       
   652     if (!m_currentToken)
       
   653         return;
       
   654 
       
   655     int key = keyEvent->key();
       
   656     if (m_lastSectionMove == QCalendarDateSectionValidator::NextSection) {
       
   657         if (key == Qt::Key_Back || key == Qt::Key_Backspace)
       
   658             toPreviousToken();
       
   659     }
       
   660     if (key == Qt::Key_Right)
       
   661         toNextToken();
       
   662     else if (key == Qt::Key_Left)
       
   663         toPreviousToken();
       
   664 
       
   665     m_lastSectionMove = m_currentToken->validator->handleKey(key);
       
   666 
       
   667     applyToDate();
       
   668     if (m_lastSectionMove == QCalendarDateSectionValidator::NextSection)
       
   669         toNextToken();
       
   670     else if (m_lastSectionMove == QCalendarDateSectionValidator::PrevSection)
       
   671         toPreviousToken();
       
   672 }
       
   673 
       
   674 QWidget *QCalendarTextNavigator::widget() const
       
   675 {
       
   676     return m_widget;
       
   677 }
       
   678 
       
   679 void QCalendarTextNavigator::setWidget(QWidget *widget)
       
   680 {
       
   681     m_widget = widget;
       
   682 }
       
   683 
       
   684 QDate QCalendarTextNavigator::date() const
       
   685 {
       
   686     return m_date;
       
   687 }
       
   688 
       
   689 void QCalendarTextNavigator::setDate(const QDate &date)
       
   690 {
       
   691     m_date = date;
       
   692 }
       
   693 
       
   694 void QCalendarTextNavigator::updateDateLabel()
       
   695 {
       
   696     if (!m_widget)
       
   697         return;
       
   698 
       
   699     m_acceptTimer.start(m_editDelay, this);
       
   700 
       
   701     m_dateText->setText(m_dateValidator->currentText());
       
   702 
       
   703     QSize s = m_dateFrame->sizeHint();
       
   704     QRect r = m_widget->geometry(); // later, just the table section
       
   705     QRect newRect((r.width() - s.width()) / 2, (r.height() - s.height()) / 2, s.width(), s.height());
       
   706     m_dateFrame->setGeometry(newRect);
       
   707     // need to set palette after geometry update as phonestyle sets transparency
       
   708     // effect in move event.
       
   709     QPalette p = m_dateFrame->palette();
       
   710     p.setBrush(QPalette::Window, m_dateFrame->window()->palette().brush(QPalette::Window));
       
   711     m_dateFrame->setPalette(p);
       
   712 
       
   713     m_dateFrame->raise();
       
   714     m_dateFrame->show();
       
   715 }
       
   716 
       
   717 void QCalendarTextNavigator::applyDate()
       
   718 {
       
   719     QDate date = m_dateValidator->currentDate();
       
   720     if (m_date == date)
       
   721         return;
       
   722 
       
   723     m_date = date;
       
   724     emit dateChanged(date);
       
   725 }
       
   726 
       
   727 void QCalendarTextNavigator::createDateLabel()
       
   728 {
       
   729     if (m_dateFrame)
       
   730         return;
       
   731     m_dateFrame = new QFrame(m_widget);
       
   732     QVBoxLayout *vl = new QVBoxLayout;
       
   733     m_dateText = new QLabel;
       
   734     vl->addWidget(m_dateText);
       
   735     m_dateFrame->setLayout(vl);
       
   736     m_dateFrame->setFrameShadow(QFrame::Plain);
       
   737     m_dateFrame->setFrameShape(QFrame::Box);
       
   738     m_dateValidator = new QCalendarDateValidator();
       
   739     m_dateValidator->setLocale(m_widget->locale());
       
   740     m_dateValidator->setFormat(m_widget->locale().dateFormat(QLocale::ShortFormat));
       
   741     m_dateValidator->setInitialDate(m_date);
       
   742 
       
   743     m_dateFrame->setAutoFillBackground(true);
       
   744     m_dateFrame->setBackgroundRole(QPalette::Window);
       
   745 }
       
   746 
       
   747 void QCalendarTextNavigator::removeDateLabel()
       
   748 {
       
   749     if (!m_dateFrame)
       
   750         return;
       
   751     m_acceptTimer.stop();
       
   752     m_dateFrame->hide();
       
   753     m_dateFrame->deleteLater();
       
   754     delete m_dateValidator;
       
   755     m_dateFrame = 0;
       
   756     m_dateText = 0;
       
   757     m_dateValidator = 0;
       
   758 }
       
   759 
       
   760 bool QCalendarTextNavigator::eventFilter(QObject *o, QEvent *e)
       
   761 {
       
   762     if (m_widget) {
       
   763         if (e->type() == QEvent::KeyPress || e->type() == QEvent::KeyRelease) {
       
   764             QKeyEvent* ke = (QKeyEvent*)e;
       
   765             if ((ke->text().length() > 0 && ke->text()[0].isPrint()) || m_dateFrame) {
       
   766                 if (ke->key() == Qt::Key_Return || ke->key() == Qt::Key_Enter || ke->key() == Qt::Key_Select) {
       
   767                     applyDate();
       
   768                     emit editingFinished();
       
   769                     removeDateLabel();
       
   770                 } else if (ke->key() == Qt::Key_Escape) {
       
   771                     removeDateLabel();
       
   772                 } else if (e->type() == QEvent::KeyPress) {
       
   773                     createDateLabel();
       
   774                     m_dateValidator->handleKeyEvent(ke);
       
   775                     updateDateLabel();
       
   776                 }
       
   777                 ke->accept();
       
   778                 return true;
       
   779             }
       
   780             // If we are navigating let the user finish his date in old locate.
       
   781             // If we change our mind and want it to update immediately simply uncomment below
       
   782             /*
       
   783         } else if (e->type() == QEvent::LocaleChange) {
       
   784             if (m_dateValidator) {
       
   785                 m_dateValidator->setLocale(m_widget->locale());
       
   786                 m_dateValidator->setFormat(m_widget->locale().dateFormat(QLocale::ShortFormat));
       
   787                 updateDateLabel();
       
   788             }
       
   789             */
       
   790         }
       
   791     }
       
   792     return QObject::eventFilter(o,e);
       
   793 }
       
   794 
       
   795 void QCalendarTextNavigator::timerEvent(QTimerEvent *e)
       
   796 {
       
   797     if (e->timerId() == m_acceptTimer.timerId()) {
       
   798         applyDate();
       
   799         removeDateLabel();
       
   800     }
       
   801 }
       
   802 
       
   803 int QCalendarTextNavigator::dateEditAcceptDelay() const
       
   804 {
       
   805     return m_editDelay;
       
   806 }
       
   807 
       
   808 void QCalendarTextNavigator::setDateEditAcceptDelay(int delay)
       
   809 {
       
   810     m_editDelay = delay;
       
   811 }
       
   812 
       
   813 class QCalendarView;
       
   814 
       
   815 class QCalendarModel : public QAbstractTableModel
       
   816 {
       
   817     Q_OBJECT
       
   818 public:
       
   819     QCalendarModel(QObject *parent = 0);
       
   820 
       
   821     int rowCount(const QModelIndex &) const
       
   822         { return RowCount + m_firstRow; }
       
   823     int columnCount(const QModelIndex &) const
       
   824         { return ColumnCount + m_firstColumn; }
       
   825     QVariant data(const QModelIndex &index, int role) const;
       
   826     Qt::ItemFlags flags(const QModelIndex &index) const;
       
   827 
       
   828     bool insertRows(int row, int count, const QModelIndex &parent = QModelIndex())
       
   829     {
       
   830         beginInsertRows(parent, row, row + count - 1);
       
   831         endInsertRows();
       
   832         return true;
       
   833     }
       
   834     bool insertColumns(int column, int count, const QModelIndex &parent = QModelIndex())
       
   835     {
       
   836         beginInsertColumns(parent, column, column + count - 1);
       
   837         endInsertColumns();
       
   838         return true;
       
   839     }
       
   840     bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex())
       
   841     {
       
   842         beginRemoveRows(parent, row, row + count - 1);
       
   843         endRemoveRows();
       
   844         return true;
       
   845     }
       
   846     bool removeColumns(int column, int count, const QModelIndex &parent = QModelIndex())
       
   847     {
       
   848         beginRemoveColumns(parent, column, column + count - 1);
       
   849         endRemoveColumns();
       
   850         return true;
       
   851     }
       
   852 
       
   853     void showMonth(int year, int month);
       
   854     void setDate(const QDate &d);
       
   855 
       
   856     void setMinimumDate(const QDate &date);
       
   857     void setMaximumDate(const QDate &date);
       
   858 
       
   859     void setRange(const QDate &min, const QDate &max);
       
   860 
       
   861     void setHorizontalHeaderFormat(QCalendarWidget::HorizontalHeaderFormat format);
       
   862 
       
   863     void setFirstColumnDay(Qt::DayOfWeek dayOfWeek);
       
   864     Qt::DayOfWeek firstColumnDay() const;
       
   865 
       
   866     bool weekNumbersShown() const;
       
   867     void setWeekNumbersShown(bool show);
       
   868 
       
   869     QTextCharFormat formatForCell(int row, int col) const;
       
   870     Qt::DayOfWeek dayOfWeekForColumn(int section) const;
       
   871     int columnForDayOfWeek(Qt::DayOfWeek day) const;
       
   872     QDate dateForCell(int row, int column) const;
       
   873     void cellForDate(const QDate &date, int *row, int *column) const;
       
   874     QString dayName(Qt::DayOfWeek day) const;
       
   875 
       
   876     void setView(QCalendarView *view)
       
   877         { m_view = view; }
       
   878 
       
   879     void internalUpdate();
       
   880     QDate referenceDate() const;
       
   881     int columnForFirstOfMonth(const QDate &date) const;
       
   882 
       
   883     int m_firstColumn;
       
   884     int m_firstRow;
       
   885     QDate m_date;
       
   886     QDate m_minimumDate;
       
   887     QDate m_maximumDate;
       
   888     int m_shownYear;
       
   889     int m_shownMonth;
       
   890     Qt::DayOfWeek m_firstDay;
       
   891     QCalendarWidget::HorizontalHeaderFormat m_horizontalHeaderFormat;
       
   892     bool m_weekNumbersShown;
       
   893     QMap<Qt::DayOfWeek, QTextCharFormat> m_dayFormats;
       
   894     QMap<QDate, QTextCharFormat> m_dateFormats;
       
   895     QTextCharFormat m_headerFormat;
       
   896     QCalendarView *m_view;
       
   897 };
       
   898 
       
   899 class QCalendarView : public QTableView
       
   900 {
       
   901     Q_OBJECT
       
   902 public:
       
   903     QCalendarView(QWidget *parent = 0);
       
   904 
       
   905     void internalUpdate() { updateGeometries(); }
       
   906     void setReadOnly(bool enable);
       
   907     virtual void keyboardSearch(const QString & search) { Q_UNUSED(search) }
       
   908 
       
   909 signals:
       
   910     void showDate(const QDate &date);
       
   911     void changeDate(const QDate &date, bool changeMonth);
       
   912     void clicked(const QDate &date);
       
   913     void editingFinished();
       
   914 protected:
       
   915     QModelIndex moveCursor(CursorAction cursorAction, Qt::KeyboardModifiers modifiers);
       
   916     void mouseDoubleClickEvent(QMouseEvent *event);
       
   917     void mousePressEvent(QMouseEvent *event);
       
   918     void mouseMoveEvent(QMouseEvent *event);
       
   919     void mouseReleaseEvent(QMouseEvent *event);
       
   920 #ifndef QT_NO_WHEELEVENT
       
   921     void wheelEvent(QWheelEvent *event);
       
   922 #endif
       
   923     void keyPressEvent(QKeyEvent *event);
       
   924     bool event(QEvent *event);
       
   925 
       
   926     QDate handleMouseEvent(QMouseEvent *event);
       
   927 public:
       
   928     bool readOnly;
       
   929 private:
       
   930     bool validDateClicked;
       
   931 #ifdef QT_KEYPAD_NAVIGATION
       
   932     QDate origDate;
       
   933 #endif
       
   934 };
       
   935 
       
   936 QCalendarModel::QCalendarModel(QObject *parent)
       
   937     : QAbstractTableModel(parent)
       
   938 {
       
   939     m_date = QDate::currentDate();
       
   940     m_minimumDate = QDate::fromJulianDay(1);
       
   941     m_maximumDate = QDate(7999, 12, 31);
       
   942     m_shownYear = m_date.year();
       
   943     m_shownMonth = m_date.month();
       
   944     m_firstDay = Qt::Sunday;
       
   945     m_horizontalHeaderFormat = QCalendarWidget::ShortDayNames;
       
   946     m_weekNumbersShown = true;
       
   947     m_firstColumn = 1;
       
   948     m_firstRow = 1;
       
   949     m_view = 0;
       
   950 }
       
   951 
       
   952 Qt::DayOfWeek QCalendarModel::dayOfWeekForColumn(int column) const
       
   953 {
       
   954     int col = column - m_firstColumn;
       
   955     if (col < 0 || col > 6)
       
   956         return Qt::Sunday;
       
   957     int day = m_firstDay + col;
       
   958     if (day > 7)
       
   959         day -= 7;
       
   960     return Qt::DayOfWeek(day);
       
   961 }
       
   962 
       
   963 int QCalendarModel::columnForDayOfWeek(Qt::DayOfWeek day) const
       
   964 {
       
   965     if (day < 1 || day > 7)
       
   966         return -1;
       
   967     int column = (int)day - (int)m_firstDay;
       
   968     if (column < 0)
       
   969         column += 7;
       
   970     return column + m_firstColumn;
       
   971 }
       
   972 
       
   973 /*
       
   974 This simple algorithm tries to generate a valid date from the month shown.
       
   975 Some months don't contain a first day (e.g. Jan of -4713 year,
       
   976 so QDate (-4713, 1, 1) would be invalid). In that case we try to generate
       
   977 another valid date for that month. Later, returned date's day is the number of cells
       
   978 calendar widget will reserve for days before referenceDate. (E.g. if returned date's
       
   979 day is 16, that day will be placed in 3rd or 4th row, not in the 1st or 2nd row).
       
   980 Depending on referenceData we can change behaviour of Oct 1582. If referenceDate is 1st
       
   981 of Oct we render 1 Oct in 1st or 2nd row. If referenceDate is 17 of Oct we show always 16
       
   982 dates before 17 of Oct, and since this month contains the hole 5-14 Oct, the first of Oct
       
   983 will be rendered in 2nd or 3rd row, showing more dates from previous month.
       
   984 */
       
   985 QDate QCalendarModel::referenceDate() const
       
   986 {
       
   987     int refDay = 1;
       
   988     while (refDay <= 31) {
       
   989         QDate refDate(m_shownYear, m_shownMonth, refDay);
       
   990         if (refDate.isValid())
       
   991             return refDate;
       
   992         refDay += 1;
       
   993     }
       
   994     return QDate();
       
   995 }
       
   996 
       
   997 int QCalendarModel::columnForFirstOfMonth(const QDate &date) const
       
   998 {
       
   999     return (columnForDayOfWeek(static_cast<Qt::DayOfWeek>(date.dayOfWeek())) - (date.day() % 7) + 8) % 7;
       
  1000 }
       
  1001 
       
  1002 QDate QCalendarModel::dateForCell(int row, int column) const
       
  1003 {
       
  1004     if (row < m_firstRow || row > m_firstRow + RowCount - 1 ||
       
  1005                 column < m_firstColumn || column > m_firstColumn + ColumnCount - 1)
       
  1006         return QDate();
       
  1007     const QDate refDate = referenceDate();
       
  1008     if (!refDate.isValid())
       
  1009         return QDate();
       
  1010 
       
  1011     const int columnForFirstOfShownMonth = columnForFirstOfMonth(refDate);
       
  1012     if (columnForFirstOfShownMonth - m_firstColumn < MinimumDayOffset)
       
  1013         row -= 1;
       
  1014 
       
  1015     const int requestedDay = 7 * (row - m_firstRow) + column - columnForFirstOfShownMonth - refDate.day() + 1;
       
  1016     return refDate.addDays(requestedDay);
       
  1017 }
       
  1018 
       
  1019 void QCalendarModel::cellForDate(const QDate &date, int *row, int *column) const
       
  1020 {
       
  1021     if (!row && !column)
       
  1022         return;
       
  1023 
       
  1024     if (row)
       
  1025         *row = -1;
       
  1026     if (column)
       
  1027         *column = -1;
       
  1028 
       
  1029     const QDate refDate = referenceDate();
       
  1030     if (!refDate.isValid())
       
  1031         return;
       
  1032 
       
  1033     const int columnForFirstOfShownMonth = columnForFirstOfMonth(refDate);
       
  1034     const int requestedPosition = refDate.daysTo(date) - m_firstColumn + columnForFirstOfShownMonth + refDate.day() - 1;
       
  1035 
       
  1036     int c = requestedPosition % 7;
       
  1037     int r = requestedPosition / 7;
       
  1038     if (c < 0) {
       
  1039         c += 7;
       
  1040         r -= 1;
       
  1041     }
       
  1042 
       
  1043     if (columnForFirstOfShownMonth - m_firstColumn < MinimumDayOffset)
       
  1044         r += 1;
       
  1045 
       
  1046     if (r < 0 || r > RowCount - 1 || c < 0 || c > ColumnCount - 1)
       
  1047         return;
       
  1048 
       
  1049     if (row)
       
  1050         *row = r + m_firstRow;
       
  1051     if (column)
       
  1052         *column = c + m_firstColumn;
       
  1053 }
       
  1054 
       
  1055 QString QCalendarModel::dayName(Qt::DayOfWeek day) const
       
  1056 {
       
  1057     switch (m_horizontalHeaderFormat) {
       
  1058         case QCalendarWidget::SingleLetterDayNames: {
       
  1059             QString standaloneDayName = m_view->locale().standaloneDayName(day, QLocale::NarrowFormat);
       
  1060             if (standaloneDayName == m_view->locale().dayName(day, QLocale::NarrowFormat))
       
  1061                 return standaloneDayName.left(1);
       
  1062             return standaloneDayName;
       
  1063         }
       
  1064         case QCalendarWidget::ShortDayNames:
       
  1065             return m_view->locale().dayName(day, QLocale::ShortFormat);
       
  1066         case QCalendarWidget::LongDayNames:
       
  1067             return m_view->locale().dayName(day, QLocale::LongFormat);
       
  1068         default:
       
  1069             break;
       
  1070     }
       
  1071     return QString();
       
  1072 }
       
  1073 
       
  1074 QTextCharFormat QCalendarModel::formatForCell(int row, int col) const
       
  1075 {
       
  1076     QPalette pal;
       
  1077     QPalette::ColorGroup cg = QPalette::Active;
       
  1078     if (m_view) {
       
  1079         pal = m_view->palette();
       
  1080         if (!m_view->isEnabled())
       
  1081             cg = QPalette::Disabled;
       
  1082         else if (!m_view->isActiveWindow())
       
  1083             cg = QPalette::Inactive;
       
  1084     }
       
  1085 
       
  1086     QTextCharFormat format;
       
  1087     format.setFont(m_view->font());
       
  1088     bool header = (m_weekNumbersShown && col == HeaderColumn)
       
  1089                   || (m_horizontalHeaderFormat != QCalendarWidget::NoHorizontalHeader && row == HeaderRow);
       
  1090     format.setBackground(pal.brush(cg, header ? QPalette::AlternateBase : QPalette::Base));
       
  1091     format.setForeground(pal.brush(cg, QPalette::Text));
       
  1092     if (header) {
       
  1093         format.merge(m_headerFormat);
       
  1094     }
       
  1095 
       
  1096     if (col >= m_firstColumn && col < m_firstColumn + ColumnCount) {
       
  1097         Qt::DayOfWeek dayOfWeek = dayOfWeekForColumn(col);
       
  1098         if (m_dayFormats.contains(dayOfWeek))
       
  1099             format.merge(m_dayFormats.value(dayOfWeek));
       
  1100     }
       
  1101 
       
  1102     if (!header) {
       
  1103         QDate date = dateForCell(row, col);
       
  1104         format.merge(m_dateFormats.value(date));
       
  1105         if(date < m_minimumDate || date > m_maximumDate)
       
  1106             format.setBackground(pal.brush(cg, QPalette::Window));
       
  1107         if (m_shownMonth != date.month())
       
  1108             format.setForeground(pal.brush(QPalette::Disabled, QPalette::Text));
       
  1109     }
       
  1110     return format;
       
  1111 }
       
  1112 
       
  1113 QVariant QCalendarModel::data(const QModelIndex &index, int role) const
       
  1114 {
       
  1115     if (role == Qt::TextAlignmentRole)
       
  1116         return (int) Qt::AlignCenter;
       
  1117 
       
  1118     int row = index.row();
       
  1119     int column = index.column();
       
  1120 
       
  1121     if(role == Qt::DisplayRole) {
       
  1122         if (m_weekNumbersShown && column == HeaderColumn
       
  1123             && row >= m_firstRow && row < m_firstRow + RowCount) {
       
  1124             QDate date = dateForCell(row, columnForDayOfWeek(Qt::Monday));
       
  1125             if (date.isValid())
       
  1126                 return date.weekNumber();
       
  1127         }
       
  1128         if (m_horizontalHeaderFormat != QCalendarWidget::NoHorizontalHeader && row == HeaderRow
       
  1129             && column >= m_firstColumn && column < m_firstColumn + ColumnCount)
       
  1130             return dayName(dayOfWeekForColumn(column));
       
  1131         QDate date = dateForCell(row, column);
       
  1132         if (date.isValid())
       
  1133             return date.day();
       
  1134         return QString();
       
  1135     }
       
  1136 
       
  1137     QTextCharFormat fmt = formatForCell(row, column);
       
  1138     if (role == Qt::BackgroundColorRole)
       
  1139         return fmt.background().color();
       
  1140     if (role == Qt::TextColorRole)
       
  1141         return fmt.foreground().color();
       
  1142     if (role == Qt::FontRole)
       
  1143         return fmt.font();
       
  1144     if (role == Qt::ToolTipRole)
       
  1145         return fmt.toolTip();
       
  1146     return QVariant();
       
  1147 }
       
  1148 
       
  1149 Qt::ItemFlags QCalendarModel::flags(const QModelIndex &index) const
       
  1150 {
       
  1151     QDate date = dateForCell(index.row(), index.column());
       
  1152     if (!date.isValid())
       
  1153         return QAbstractTableModel::flags(index);
       
  1154     if (date < m_minimumDate)
       
  1155         return 0;
       
  1156     if (date > m_maximumDate)
       
  1157         return 0;
       
  1158     return QAbstractTableModel::flags(index);
       
  1159 }
       
  1160 
       
  1161 void QCalendarModel::setDate(const QDate &d)
       
  1162 {
       
  1163     m_date = d;
       
  1164     if (m_date < m_minimumDate)
       
  1165         m_date = m_minimumDate;
       
  1166     else if (m_date > m_maximumDate)
       
  1167         m_date = m_maximumDate;
       
  1168 }
       
  1169 
       
  1170 void QCalendarModel::showMonth(int year, int month)
       
  1171 {
       
  1172     if (m_shownYear == year && m_shownMonth == month)
       
  1173         return;
       
  1174 
       
  1175     m_shownYear = year;
       
  1176     m_shownMonth = month;
       
  1177 
       
  1178     internalUpdate();
       
  1179 }
       
  1180 
       
  1181 void QCalendarModel::setMinimumDate(const QDate &d)
       
  1182 {
       
  1183     if (!d.isValid() || d == m_minimumDate)
       
  1184         return;
       
  1185 
       
  1186     m_minimumDate = d;
       
  1187     if (m_maximumDate < m_minimumDate)
       
  1188         m_maximumDate = m_minimumDate;
       
  1189     if (m_date < m_minimumDate)
       
  1190         m_date = m_minimumDate;
       
  1191     internalUpdate();
       
  1192 }
       
  1193 
       
  1194 void QCalendarModel::setMaximumDate(const QDate &d)
       
  1195 {
       
  1196     if (!d.isValid() || d == m_maximumDate)
       
  1197         return;
       
  1198 
       
  1199     m_maximumDate = d;
       
  1200     if (m_minimumDate > m_maximumDate)
       
  1201         m_minimumDate = m_maximumDate;
       
  1202     if (m_date > m_maximumDate)
       
  1203         m_date = m_maximumDate;
       
  1204     internalUpdate();
       
  1205 }
       
  1206 
       
  1207 void QCalendarModel::setRange(const QDate &min, const QDate &max)
       
  1208 {
       
  1209     m_minimumDate = min;
       
  1210     m_maximumDate = max;
       
  1211     if (m_minimumDate > m_maximumDate)
       
  1212         qSwap(m_minimumDate, m_maximumDate);
       
  1213     if (m_date < m_minimumDate)
       
  1214         m_date = m_minimumDate;
       
  1215     if (m_date > m_maximumDate)
       
  1216         m_date = m_maximumDate;
       
  1217     internalUpdate();
       
  1218 }
       
  1219 
       
  1220 void QCalendarModel::internalUpdate()
       
  1221 {
       
  1222     QModelIndex begin = index(0, 0);
       
  1223     QModelIndex end = index(m_firstRow + RowCount - 1, m_firstColumn + ColumnCount - 1);
       
  1224     emit dataChanged(begin, end);
       
  1225     emit headerDataChanged(Qt::Vertical, 0, m_firstRow + RowCount - 1);
       
  1226     emit headerDataChanged(Qt::Horizontal, 0, m_firstColumn + ColumnCount - 1);
       
  1227 }
       
  1228 
       
  1229 void QCalendarModel::setHorizontalHeaderFormat(QCalendarWidget::HorizontalHeaderFormat format)
       
  1230 {
       
  1231     if (m_horizontalHeaderFormat == format)
       
  1232         return;
       
  1233 
       
  1234     int oldFormat = m_horizontalHeaderFormat;
       
  1235     m_horizontalHeaderFormat = format;
       
  1236     if (oldFormat == QCalendarWidget::NoHorizontalHeader) {
       
  1237         m_firstRow = 1;
       
  1238         insertRow(0);
       
  1239     } else if (m_horizontalHeaderFormat == QCalendarWidget::NoHorizontalHeader) {
       
  1240         m_firstRow = 0;
       
  1241         removeRow(0);
       
  1242     }
       
  1243     internalUpdate();
       
  1244 }
       
  1245 
       
  1246 void QCalendarModel::setFirstColumnDay(Qt::DayOfWeek dayOfWeek)
       
  1247 {
       
  1248     if (m_firstDay == dayOfWeek)
       
  1249         return;
       
  1250 
       
  1251     m_firstDay = dayOfWeek;
       
  1252     internalUpdate();
       
  1253 }
       
  1254 
       
  1255 Qt::DayOfWeek QCalendarModel::firstColumnDay() const
       
  1256 {
       
  1257     return m_firstDay;
       
  1258 }
       
  1259 
       
  1260 bool QCalendarModel::weekNumbersShown() const
       
  1261 {
       
  1262     return m_weekNumbersShown;
       
  1263 }
       
  1264 
       
  1265 void QCalendarModel::setWeekNumbersShown(bool show)
       
  1266 {
       
  1267     if (m_weekNumbersShown == show)
       
  1268         return;
       
  1269 
       
  1270     m_weekNumbersShown = show;
       
  1271     if (show) {
       
  1272         m_firstColumn = 1;
       
  1273         insertColumn(0);
       
  1274     } else {
       
  1275         m_firstColumn = 0;
       
  1276         removeColumn(0);
       
  1277     }
       
  1278     internalUpdate();
       
  1279 }
       
  1280 
       
  1281 QCalendarView::QCalendarView(QWidget *parent)
       
  1282     : QTableView(parent),
       
  1283     readOnly(false),
       
  1284     validDateClicked(false)
       
  1285 {
       
  1286     setTabKeyNavigation(false);
       
  1287     setShowGrid(false);
       
  1288     verticalHeader()->setVisible(false);
       
  1289     horizontalHeader()->setVisible(false);
       
  1290     setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
       
  1291     setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
       
  1292 }
       
  1293 
       
  1294 QModelIndex QCalendarView::moveCursor(CursorAction cursorAction, Qt::KeyboardModifiers modifiers)
       
  1295 {
       
  1296     QCalendarModel *calendarModel = qobject_cast<QCalendarModel *>(model());
       
  1297     if (!calendarModel)
       
  1298         return QTableView::moveCursor(cursorAction, modifiers);
       
  1299 
       
  1300     if (readOnly)
       
  1301         return currentIndex();
       
  1302 
       
  1303     QModelIndex index = currentIndex();
       
  1304     QDate currentDate = static_cast<QCalendarModel*>(model())->dateForCell(index.row(), index.column());
       
  1305     switch (cursorAction) {
       
  1306         case QAbstractItemView::MoveUp:
       
  1307             currentDate = currentDate.addDays(-7);
       
  1308             break;
       
  1309         case QAbstractItemView::MoveDown:
       
  1310             currentDate = currentDate.addDays(7);
       
  1311             break;
       
  1312         case QAbstractItemView::MoveLeft:
       
  1313             currentDate = currentDate.addDays(isRightToLeft() ? 1 : -1);
       
  1314             break;
       
  1315         case QAbstractItemView::MoveRight:
       
  1316             currentDate = currentDate.addDays(isRightToLeft() ? -1 : 1);
       
  1317             break;
       
  1318         case QAbstractItemView::MoveHome:
       
  1319             currentDate = QDate(currentDate.year(), currentDate.month(), 1);
       
  1320             break;
       
  1321         case QAbstractItemView::MoveEnd:
       
  1322             currentDate = QDate(currentDate.year(), currentDate.month(), currentDate.daysInMonth());
       
  1323             break;
       
  1324         case QAbstractItemView::MovePageUp:
       
  1325             currentDate = currentDate.addMonths(-1);
       
  1326             break;
       
  1327         case QAbstractItemView::MovePageDown:
       
  1328             currentDate = currentDate.addMonths(1);
       
  1329             break;
       
  1330         case QAbstractItemView::MoveNext:
       
  1331         case QAbstractItemView::MovePrevious:
       
  1332             return currentIndex();
       
  1333         default:
       
  1334             break;
       
  1335     }
       
  1336     emit changeDate(currentDate, true);
       
  1337     return currentIndex();
       
  1338 }
       
  1339 
       
  1340 void QCalendarView::keyPressEvent(QKeyEvent *event)
       
  1341 {
       
  1342 #ifdef QT_KEYPAD_NAVIGATION
       
  1343     if (event->key() == Qt::Key_Select) {
       
  1344         if (QApplication::keypadNavigationEnabled()) {
       
  1345             if (!hasEditFocus()) {
       
  1346                 setEditFocus(true);
       
  1347                 return;
       
  1348             }
       
  1349         }
       
  1350     } else if (event->key() == Qt::Key_Back) {
       
  1351         if (QApplication::keypadNavigationEnabled() && hasEditFocus()) {
       
  1352             if (qobject_cast<QCalendarModel *>(model())) {
       
  1353                 emit changeDate(origDate, true); //changes selection back to origDate, but doesn't activate
       
  1354                 setEditFocus(false);
       
  1355                 return;
       
  1356             }
       
  1357         }
       
  1358     }
       
  1359 #endif
       
  1360 
       
  1361     if (!readOnly) {
       
  1362         switch (event->key()) {
       
  1363             case Qt::Key_Return:
       
  1364             case Qt::Key_Enter:
       
  1365             case Qt::Key_Select:
       
  1366                 emit editingFinished();
       
  1367                 return;
       
  1368             default:
       
  1369                 break;
       
  1370         }
       
  1371     }
       
  1372     QTableView::keyPressEvent(event);
       
  1373 }
       
  1374 
       
  1375 #ifndef QT_NO_WHEELEVENT
       
  1376 void QCalendarView::wheelEvent(QWheelEvent *event)
       
  1377 {
       
  1378     const int numDegrees = event->delta() / 8;
       
  1379     const int numSteps = numDegrees / 15;
       
  1380     const QModelIndex index = currentIndex();
       
  1381     QDate currentDate = static_cast<QCalendarModel*>(model())->dateForCell(index.row(), index.column());
       
  1382     currentDate = currentDate.addMonths(-numSteps);
       
  1383     emit showDate(currentDate);
       
  1384 }
       
  1385 #endif
       
  1386 
       
  1387 bool QCalendarView::event(QEvent *event)
       
  1388 {
       
  1389 #ifdef QT_KEYPAD_NAVIGATION
       
  1390     if (event->type() == QEvent::FocusIn) {
       
  1391         if (QCalendarModel *calendarModel = qobject_cast<QCalendarModel *>(model())) {
       
  1392             origDate = calendarModel->m_date;
       
  1393         }
       
  1394     }
       
  1395 #endif
       
  1396 
       
  1397     return QTableView::event(event);
       
  1398 }
       
  1399 
       
  1400 QDate QCalendarView::handleMouseEvent(QMouseEvent *event)
       
  1401 {
       
  1402     QCalendarModel *calendarModel = qobject_cast<QCalendarModel *>(model());
       
  1403     if (!calendarModel)
       
  1404         return QDate();
       
  1405 
       
  1406     QPoint pos = event->pos();
       
  1407     QModelIndex index = indexAt(pos);
       
  1408     QDate date = calendarModel->dateForCell(index.row(), index.column());
       
  1409     if (date.isValid() && date >= calendarModel->m_minimumDate
       
  1410             && date <= calendarModel->m_maximumDate) {
       
  1411         return date;
       
  1412     }
       
  1413     return QDate();
       
  1414 }
       
  1415 
       
  1416 void QCalendarView::mouseDoubleClickEvent(QMouseEvent *event)
       
  1417 {
       
  1418     QCalendarModel *calendarModel = qobject_cast<QCalendarModel *>(model());
       
  1419     if (!calendarModel) {
       
  1420         QTableView::mouseDoubleClickEvent(event);
       
  1421         return;
       
  1422     }
       
  1423 
       
  1424     if (readOnly)
       
  1425         return;
       
  1426 
       
  1427     QDate date = handleMouseEvent(event);
       
  1428     validDateClicked = false;
       
  1429     if (date == calendarModel->m_date && !style()->styleHint(QStyle::SH_ItemView_ActivateItemOnSingleClick)) {
       
  1430         emit editingFinished();
       
  1431     }
       
  1432 }
       
  1433 
       
  1434 void QCalendarView::mousePressEvent(QMouseEvent *event)
       
  1435 {
       
  1436     QCalendarModel *calendarModel = qobject_cast<QCalendarModel *>(model());
       
  1437     if (!calendarModel) {
       
  1438         QTableView::mousePressEvent(event);
       
  1439         return;
       
  1440     }
       
  1441 
       
  1442     if (readOnly)
       
  1443         return;
       
  1444 
       
  1445     if (event->button() != Qt::LeftButton)
       
  1446         return;
       
  1447 
       
  1448     QDate date = handleMouseEvent(event);
       
  1449     if (date.isValid()) {
       
  1450         validDateClicked = true;
       
  1451         int row = -1, col = -1;
       
  1452         static_cast<QCalendarModel *>(model())->cellForDate(date, &row, &col);
       
  1453         if (row != -1 && col != -1) {
       
  1454             selectionModel()->setCurrentIndex(model()->index(row, col), QItemSelectionModel::NoUpdate);
       
  1455         }
       
  1456     } else {
       
  1457         validDateClicked = false;
       
  1458         event->ignore();
       
  1459     }
       
  1460 }
       
  1461 
       
  1462 void QCalendarView::mouseMoveEvent(QMouseEvent *event)
       
  1463 {
       
  1464     QCalendarModel *calendarModel = qobject_cast<QCalendarModel *>(model());
       
  1465     if (!calendarModel) {
       
  1466         QTableView::mouseMoveEvent(event);
       
  1467         return;
       
  1468     }
       
  1469 
       
  1470     if (readOnly)
       
  1471         return;
       
  1472 
       
  1473     if (validDateClicked) {
       
  1474        QDate date = handleMouseEvent(event);
       
  1475         if (date.isValid()) {
       
  1476             int row = -1, col = -1;
       
  1477             static_cast<QCalendarModel *>(model())->cellForDate(date, &row, &col);
       
  1478             if (row != -1 && col != -1) {
       
  1479                 selectionModel()->setCurrentIndex(model()->index(row, col), QItemSelectionModel::NoUpdate);
       
  1480             }
       
  1481         }
       
  1482     } else {
       
  1483         event->ignore();
       
  1484     }
       
  1485 }
       
  1486 
       
  1487 void QCalendarView::mouseReleaseEvent(QMouseEvent *event)
       
  1488 {
       
  1489     QCalendarModel *calendarModel = qobject_cast<QCalendarModel *>(model());
       
  1490     if (!calendarModel) {
       
  1491         QTableView::mouseReleaseEvent(event);
       
  1492         return;
       
  1493     }
       
  1494 
       
  1495     if (event->button() != Qt::LeftButton)
       
  1496         return;
       
  1497 
       
  1498     if (readOnly)
       
  1499         return;
       
  1500 
       
  1501     if (validDateClicked) {
       
  1502         QDate date = handleMouseEvent(event);
       
  1503         if (date.isValid()) {
       
  1504             emit changeDate(date, true);
       
  1505             emit clicked(date);
       
  1506             if (style()->styleHint(QStyle::SH_ItemView_ActivateItemOnSingleClick))
       
  1507                 emit editingFinished();
       
  1508         }
       
  1509         validDateClicked = false;
       
  1510     } else {
       
  1511         event->ignore();
       
  1512     }
       
  1513 }
       
  1514 
       
  1515 class QCalendarDelegate : public QItemDelegate
       
  1516 {
       
  1517     Q_OBJECT
       
  1518 public:
       
  1519     QCalendarDelegate(QCalendarWidgetPrivate *w, QObject *parent = 0)
       
  1520         : QItemDelegate(parent), calendarWidgetPrivate(w)
       
  1521             { }
       
  1522     virtual void paint(QPainter *painter, const QStyleOptionViewItem &option,
       
  1523                 const QModelIndex &index) const;
       
  1524     void paintCell(QPainter *painter, const QRect &rect, const QDate &date) const;
       
  1525 
       
  1526 private:
       
  1527     QCalendarWidgetPrivate *calendarWidgetPrivate;
       
  1528     mutable QStyleOptionViewItemV4 storedOption;
       
  1529 };
       
  1530 
       
  1531 //Private tool button class
       
  1532 class QCalToolButton: public QToolButton
       
  1533 {
       
  1534 public:
       
  1535     QCalToolButton(QWidget * parent)
       
  1536         : QToolButton(parent)
       
  1537           {  }
       
  1538 protected:
       
  1539     void paintEvent(QPaintEvent *e)
       
  1540     {
       
  1541         Q_UNUSED(e)
       
  1542 
       
  1543 #ifndef Q_WS_MAC
       
  1544         QStyleOptionToolButton opt;
       
  1545         initStyleOption(&opt);
       
  1546 
       
  1547         if (opt.state & QStyle::State_MouseOver || isDown()) {
       
  1548             //act as normal button
       
  1549             setPalette(QPalette());
       
  1550         } else {
       
  1551             //set the highlight color for button text
       
  1552             QPalette toolPalette = palette();
       
  1553             toolPalette.setColor(QPalette::ButtonText, toolPalette.color(QPalette::HighlightedText));
       
  1554             setPalette(toolPalette);
       
  1555         }
       
  1556 #endif
       
  1557         QToolButton::paintEvent(e);
       
  1558     }
       
  1559 };
       
  1560 
       
  1561 class QPrevNextCalButton : public QToolButton
       
  1562 {
       
  1563     Q_OBJECT
       
  1564 public:
       
  1565     QPrevNextCalButton(QWidget *parent) : QToolButton(parent) {}
       
  1566 protected:
       
  1567     void paintEvent(QPaintEvent *) {
       
  1568         QStylePainter painter(this);
       
  1569         QStyleOptionToolButton opt;
       
  1570         initStyleOption(&opt);
       
  1571         opt.state &= ~QStyle::State_HasFocus;
       
  1572         painter.drawComplexControl(QStyle::CC_ToolButton, opt);
       
  1573     }
       
  1574 };
       
  1575 
       
  1576 class QCalendarWidgetPrivate : public QWidgetPrivate
       
  1577 {
       
  1578     Q_DECLARE_PUBLIC(QCalendarWidget)
       
  1579 public:
       
  1580     QCalendarWidgetPrivate();
       
  1581 
       
  1582     void showMonth(int year, int month);
       
  1583     void update();
       
  1584     void paintCell(QPainter *painter, const QRect &rect, const QDate &date) const;
       
  1585 
       
  1586     void _q_slotShowDate(const QDate &date);
       
  1587     void _q_slotChangeDate(const QDate &date);
       
  1588     void _q_slotChangeDate(const QDate &date, bool changeMonth);
       
  1589     void _q_editingFinished();
       
  1590     void _q_monthChanged(QAction*);
       
  1591     void _q_prevMonthClicked();
       
  1592     void _q_nextMonthClicked();
       
  1593     void _q_yearEditingFinished();
       
  1594     void _q_yearClicked();
       
  1595 
       
  1596     void createNavigationBar(QWidget *widget);
       
  1597     void updateButtonIcons();
       
  1598     void updateMonthMenu();
       
  1599     void updateMonthMenuNames();
       
  1600     void updateNavigationBar();
       
  1601     void updateCurrentPage(const QDate &newDate);
       
  1602     inline QDate getCurrentDate();
       
  1603     void setNavigatorEnabled(bool enable);
       
  1604 
       
  1605     QCalendarModel *m_model;
       
  1606     QCalendarView *m_view;
       
  1607     QCalendarDelegate *m_delegate;
       
  1608     QItemSelectionModel *m_selection;
       
  1609     QCalendarTextNavigator *m_navigator;
       
  1610     bool m_dateEditEnabled;
       
  1611 
       
  1612     QToolButton *nextMonth;
       
  1613     QToolButton *prevMonth;
       
  1614     QCalToolButton *monthButton;
       
  1615     QMenu *monthMenu;
       
  1616     QMap<int, QAction *> monthToAction;
       
  1617     QCalToolButton *yearButton;
       
  1618     QSpinBox *yearEdit;
       
  1619     QWidget *navBarBackground;
       
  1620     QSpacerItem *spaceHolder;
       
  1621 
       
  1622     bool navBarVisible;
       
  1623     mutable QSize cachedSizeHint;
       
  1624     Qt::FocusPolicy oldFocusPolicy;
       
  1625 };
       
  1626 
       
  1627 void QCalendarDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option,
       
  1628             const QModelIndex &index) const
       
  1629 {
       
  1630     QDate date = calendarWidgetPrivate->m_model->dateForCell(index.row(), index.column());
       
  1631     if (date.isValid()) {
       
  1632         storedOption = option;
       
  1633         QRect rect = option.rect;
       
  1634         calendarWidgetPrivate->paintCell(painter, rect, date);
       
  1635     } else {
       
  1636         QItemDelegate::paint(painter, option, index);
       
  1637     }
       
  1638 }
       
  1639 
       
  1640 void QCalendarDelegate::paintCell(QPainter *painter, const QRect &rect, const QDate &date) const
       
  1641 {
       
  1642     storedOption.rect = rect;
       
  1643     int row = -1;
       
  1644     int col = -1;
       
  1645     calendarWidgetPrivate->m_model->cellForDate(date, &row, &col);
       
  1646     QModelIndex idx = calendarWidgetPrivate->m_model->index(row, col);
       
  1647     QItemDelegate::paint(painter, storedOption, idx);
       
  1648 }
       
  1649 
       
  1650 QCalendarWidgetPrivate::QCalendarWidgetPrivate()
       
  1651     : QWidgetPrivate()
       
  1652 {
       
  1653     m_model = 0;
       
  1654     m_view = 0;
       
  1655     m_delegate = 0;
       
  1656     m_selection = 0;
       
  1657     m_navigator = 0;
       
  1658     m_dateEditEnabled = false;
       
  1659     navBarVisible = true;
       
  1660     oldFocusPolicy = Qt::StrongFocus;
       
  1661 }
       
  1662 
       
  1663 void QCalendarWidgetPrivate::setNavigatorEnabled(bool enable)
       
  1664 {
       
  1665     Q_Q(QCalendarWidget);
       
  1666 
       
  1667     bool navigatorEnabled = (m_navigator->widget() != 0);
       
  1668     if (enable == navigatorEnabled)
       
  1669         return;
       
  1670 
       
  1671     if (enable) {
       
  1672         m_navigator->setWidget(q);
       
  1673         q->connect(m_navigator, SIGNAL(dateChanged(QDate)),
       
  1674                 q, SLOT(_q_slotChangeDate(QDate)));
       
  1675         q->connect(m_navigator, SIGNAL(editingFinished()),
       
  1676                 q, SLOT(_q_editingFinished()));
       
  1677         m_view->installEventFilter(m_navigator);
       
  1678     } else {
       
  1679         m_navigator->setWidget(0);
       
  1680         q->disconnect(m_navigator, SIGNAL(dateChanged(QDate)),
       
  1681                 q, SLOT(_q_slotChangeDate(QDate)));
       
  1682         q->disconnect(m_navigator, SIGNAL(editingFinished()),
       
  1683                 q, SLOT(_q_editingFinished()));
       
  1684         m_view->removeEventFilter(m_navigator);
       
  1685     }
       
  1686 }
       
  1687 
       
  1688 void QCalendarWidgetPrivate::createNavigationBar(QWidget *widget)
       
  1689 {
       
  1690     Q_Q(QCalendarWidget);
       
  1691     navBarBackground = new QWidget(widget);
       
  1692     navBarBackground->setObjectName(QLatin1String("qt_calendar_navigationbar"));
       
  1693     navBarBackground->setAutoFillBackground(true);
       
  1694     navBarBackground->setBackgroundRole(QPalette::Highlight);
       
  1695 
       
  1696     prevMonth = new QPrevNextCalButton(navBarBackground);
       
  1697     nextMonth = new QPrevNextCalButton(navBarBackground);
       
  1698     prevMonth->setAutoRaise(true);
       
  1699     nextMonth->setAutoRaise(true);
       
  1700     prevMonth->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Minimum);
       
  1701     nextMonth->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Minimum);
       
  1702     nextMonth->setAutoRaise(true);
       
  1703     updateButtonIcons();
       
  1704     prevMonth->setAutoRepeat(true);
       
  1705     nextMonth->setAutoRepeat(true);
       
  1706 
       
  1707     monthButton = new QCalToolButton(navBarBackground);
       
  1708     monthButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Minimum);
       
  1709     monthButton->setAutoRaise(true);
       
  1710     monthButton->setPopupMode(QToolButton::InstantPopup);
       
  1711     monthMenu = new QMenu(monthButton);
       
  1712     for (int i = 1; i <= 12; i++) {
       
  1713         QString monthName(q->locale().standaloneMonthName(i, QLocale::LongFormat));
       
  1714         QAction *act = monthMenu->addAction(monthName);
       
  1715         act->setData(i);
       
  1716         monthToAction[i] = act;
       
  1717     }
       
  1718     monthButton->setMenu(monthMenu);
       
  1719     yearButton = new QCalToolButton(navBarBackground);
       
  1720     yearButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Minimum);
       
  1721     yearButton->setAutoRaise(true);
       
  1722     yearEdit = new QSpinBox(navBarBackground);
       
  1723 
       
  1724     QFont font = q->font();
       
  1725     font.setBold(true);
       
  1726     monthButton->setFont(font);
       
  1727     yearButton->setFont(font);
       
  1728     yearEdit->setFrame(false);
       
  1729     yearEdit->setMinimum(m_model->m_minimumDate.year());
       
  1730     yearEdit->setMaximum(m_model->m_maximumDate.year());
       
  1731     yearEdit->hide();
       
  1732     spaceHolder = new QSpacerItem(0,0);
       
  1733 
       
  1734     QHBoxLayout *headerLayout = new QHBoxLayout;
       
  1735     headerLayout->setMargin(0);
       
  1736     headerLayout->setSpacing(0);
       
  1737     headerLayout->addWidget(prevMonth);
       
  1738     headerLayout->insertStretch(headerLayout->count());
       
  1739     headerLayout->addWidget(monthButton);
       
  1740     headerLayout->addItem(spaceHolder);
       
  1741     headerLayout->addWidget(yearButton);
       
  1742     headerLayout->insertStretch(headerLayout->count());
       
  1743     headerLayout->addWidget(nextMonth);
       
  1744     navBarBackground->setLayout(headerLayout);
       
  1745 
       
  1746     yearEdit->setFocusPolicy(Qt::StrongFocus);
       
  1747     prevMonth->setFocusPolicy(Qt::NoFocus);
       
  1748     nextMonth->setFocusPolicy(Qt::NoFocus);
       
  1749     yearButton->setFocusPolicy(Qt::NoFocus);
       
  1750     monthButton->setFocusPolicy(Qt::NoFocus);
       
  1751 
       
  1752     //set names for the header controls.
       
  1753     prevMonth->setObjectName(QLatin1String("qt_calendar_prevmonth"));
       
  1754     nextMonth->setObjectName(QLatin1String("qt_calendar_nextmonth"));
       
  1755     monthButton->setObjectName(QLatin1String("qt_calendar_monthbutton"));
       
  1756     yearButton->setObjectName(QLatin1String("qt_calendar_yearbutton"));
       
  1757     yearEdit->setObjectName(QLatin1String("qt_calendar_yearedit"));
       
  1758 
       
  1759     updateMonthMenu();
       
  1760     showMonth(m_model->m_date.year(), m_model->m_date.month());
       
  1761 }
       
  1762 
       
  1763 void QCalendarWidgetPrivate::updateButtonIcons()
       
  1764 {
       
  1765     Q_Q(QCalendarWidget);
       
  1766     prevMonth->setIcon(q->style()->standardIcon(q->isRightToLeft() ? QStyle::SP_ArrowRight : QStyle::SP_ArrowLeft, 0, q));
       
  1767     nextMonth->setIcon(q->style()->standardIcon(q->isRightToLeft() ? QStyle::SP_ArrowLeft : QStyle::SP_ArrowRight, 0, q));
       
  1768 }
       
  1769 
       
  1770 void QCalendarWidgetPrivate::updateMonthMenu()
       
  1771 {
       
  1772     int beg = 1, end = 12;
       
  1773     bool prevEnabled = true;
       
  1774     bool nextEnabled = true;
       
  1775     if (m_model->m_shownYear == m_model->m_minimumDate.year()) {
       
  1776         beg = m_model->m_minimumDate.month();
       
  1777         if (m_model->m_shownMonth == m_model->m_minimumDate.month())
       
  1778             prevEnabled = false;
       
  1779     }
       
  1780     if (m_model->m_shownYear == m_model->m_maximumDate.year()) {
       
  1781         end = m_model->m_maximumDate.month();
       
  1782         if (m_model->m_shownMonth == m_model->m_maximumDate.month())
       
  1783             nextEnabled = false;
       
  1784     }
       
  1785     prevMonth->setEnabled(prevEnabled);
       
  1786     nextMonth->setEnabled(nextEnabled);
       
  1787     for (int i = 1; i <= 12; i++) {
       
  1788         bool monthEnabled = true;
       
  1789         if (i < beg || i > end)
       
  1790             monthEnabled = false;
       
  1791         monthToAction[i]->setEnabled(monthEnabled);
       
  1792     }
       
  1793 }
       
  1794 
       
  1795 void QCalendarWidgetPrivate::updateMonthMenuNames()
       
  1796 {
       
  1797     Q_Q(QCalendarWidget);
       
  1798 
       
  1799     for (int i = 1; i <= 12; i++) {
       
  1800         QString monthName(q->locale().standaloneMonthName(i, QLocale::LongFormat));
       
  1801         monthToAction[i]->setText(monthName);
       
  1802     }
       
  1803 }
       
  1804 
       
  1805 void QCalendarWidgetPrivate::updateCurrentPage(const QDate &date)
       
  1806 {
       
  1807     Q_Q(QCalendarWidget);
       
  1808 
       
  1809     QDate newDate = date;
       
  1810     QDate minDate = q->minimumDate();
       
  1811     QDate maxDate = q->maximumDate();
       
  1812     if (minDate.isValid()&& minDate.daysTo(newDate) < 0)
       
  1813         newDate = minDate;
       
  1814     if (maxDate.isValid()&& maxDate.daysTo(newDate) > 0)
       
  1815         newDate = maxDate;
       
  1816     showMonth(newDate.year(), newDate.month());
       
  1817     int row = -1, col = -1;
       
  1818     m_model->cellForDate(newDate, &row, &col);
       
  1819     if (row != -1 && col != -1)
       
  1820     {
       
  1821         m_view->selectionModel()->setCurrentIndex(m_model->index(row, col),
       
  1822                                                   QItemSelectionModel::NoUpdate);
       
  1823     }
       
  1824 }
       
  1825 
       
  1826 void QCalendarWidgetPrivate::_q_monthChanged(QAction *act)
       
  1827 {
       
  1828     monthButton->setText(act->text());
       
  1829     QDate currentDate = getCurrentDate();
       
  1830     QDate newDate = currentDate.addMonths(act->data().toInt()-currentDate.month());
       
  1831     updateCurrentPage(newDate);
       
  1832 }
       
  1833 
       
  1834 QDate QCalendarWidgetPrivate::getCurrentDate()
       
  1835 {
       
  1836     QModelIndex index = m_view->currentIndex();
       
  1837     return m_model->dateForCell(index.row(), index.column());
       
  1838 }
       
  1839 
       
  1840 void QCalendarWidgetPrivate::_q_prevMonthClicked()
       
  1841 {
       
  1842     QDate currentDate = getCurrentDate().addMonths(-1);
       
  1843     updateCurrentPage(currentDate);
       
  1844 }
       
  1845 
       
  1846 void QCalendarWidgetPrivate::_q_nextMonthClicked()
       
  1847 {
       
  1848     QDate currentDate = getCurrentDate().addMonths(1);
       
  1849     updateCurrentPage(currentDate);
       
  1850 }
       
  1851 
       
  1852 void QCalendarWidgetPrivate::_q_yearEditingFinished()
       
  1853 {
       
  1854     Q_Q(QCalendarWidget);
       
  1855     yearButton->setText(yearEdit->text());
       
  1856     yearEdit->hide();
       
  1857     q->setFocusPolicy(oldFocusPolicy);
       
  1858     qApp->removeEventFilter(q);
       
  1859     spaceHolder->changeSize(0, 0);
       
  1860     yearButton->show();
       
  1861     QDate currentDate = getCurrentDate();
       
  1862     currentDate = currentDate.addYears(yearEdit->text().toInt() - currentDate.year());
       
  1863     updateCurrentPage(currentDate);
       
  1864 }
       
  1865 
       
  1866 void QCalendarWidgetPrivate::_q_yearClicked()
       
  1867 {
       
  1868     Q_Q(QCalendarWidget);
       
  1869     //show the spinbox on top of the button
       
  1870     yearEdit->setGeometry(yearButton->x(), yearButton->y(),
       
  1871                           yearEdit->sizeHint().width(), yearButton->height());
       
  1872     spaceHolder->changeSize(yearButton->width(), 0);
       
  1873     yearButton->hide();
       
  1874     oldFocusPolicy = q->focusPolicy();
       
  1875     q->setFocusPolicy(Qt::NoFocus);
       
  1876     yearEdit->show();
       
  1877     qApp->installEventFilter(q);
       
  1878     yearEdit->raise();
       
  1879     yearEdit->selectAll();
       
  1880     yearEdit->setFocus(Qt::MouseFocusReason);
       
  1881 }
       
  1882 
       
  1883 void QCalendarWidgetPrivate::showMonth(int year, int month)
       
  1884 {
       
  1885     if (m_model->m_shownYear == year && m_model->m_shownMonth == month)
       
  1886         return;
       
  1887     Q_Q(QCalendarWidget);
       
  1888     m_model->showMonth(year, month);
       
  1889     updateNavigationBar();
       
  1890     emit q->currentPageChanged(year, month);
       
  1891     m_view->internalUpdate();
       
  1892     cachedSizeHint = QSize();
       
  1893     update();
       
  1894     updateMonthMenu();
       
  1895 }
       
  1896 
       
  1897 void QCalendarWidgetPrivate::updateNavigationBar()
       
  1898 {
       
  1899     Q_Q(QCalendarWidget);
       
  1900 
       
  1901     QString monthName = q->locale().standaloneMonthName(m_model->m_shownMonth, QLocale::LongFormat);
       
  1902 
       
  1903     monthButton->setText(monthName);
       
  1904     yearButton->setText(QString::number(m_model->m_shownYear));
       
  1905     yearEdit->setValue(m_model->m_shownYear);
       
  1906 }
       
  1907 
       
  1908 void QCalendarWidgetPrivate::update()
       
  1909 {
       
  1910     QDate currentDate = m_model->m_date;
       
  1911     int row, column;
       
  1912     m_model->cellForDate(currentDate, &row, &column);
       
  1913     QModelIndex idx;
       
  1914     m_selection->clear();
       
  1915     if (row != -1 && column != -1) {
       
  1916         idx = m_model->index(row, column);
       
  1917         m_selection->setCurrentIndex(idx, QItemSelectionModel::SelectCurrent);
       
  1918     }
       
  1919 }
       
  1920 
       
  1921 void QCalendarWidgetPrivate::paintCell(QPainter *painter, const QRect &rect, const QDate &date) const
       
  1922 {
       
  1923     Q_Q(const QCalendarWidget);
       
  1924     q->paintCell(painter, rect, date);
       
  1925 }
       
  1926 
       
  1927 void QCalendarWidgetPrivate::_q_slotShowDate(const QDate &date)
       
  1928 {
       
  1929     updateCurrentPage(date);
       
  1930 }
       
  1931 
       
  1932 void QCalendarWidgetPrivate::_q_slotChangeDate(const QDate &date)
       
  1933 {
       
  1934     _q_slotChangeDate(date, true);
       
  1935 }
       
  1936 
       
  1937 void QCalendarWidgetPrivate::_q_slotChangeDate(const QDate &date, bool changeMonth)
       
  1938 {
       
  1939     QDate oldDate = m_model->m_date;
       
  1940     m_model->setDate(date);
       
  1941     QDate newDate = m_model->m_date;
       
  1942     if (changeMonth)
       
  1943         showMonth(newDate.year(), newDate.month());
       
  1944     if (oldDate != newDate) {
       
  1945         update();
       
  1946         Q_Q(QCalendarWidget);
       
  1947         m_navigator->setDate(newDate);
       
  1948         emit q->selectionChanged();
       
  1949     }
       
  1950 }
       
  1951 
       
  1952 void QCalendarWidgetPrivate::_q_editingFinished()
       
  1953 {
       
  1954     Q_Q(QCalendarWidget);
       
  1955     emit q->activated(m_model->m_date);
       
  1956 }
       
  1957 
       
  1958 /*!
       
  1959     \class QCalendarWidget
       
  1960     \brief The QCalendarWidget class provides a monthly based
       
  1961     calendar widget allowing the user to select a date.
       
  1962     \since 4.2
       
  1963 
       
  1964     \ingroup advanced
       
  1965 
       
  1966     \image cleanlooks-calendarwidget.png
       
  1967 
       
  1968     The widget is initialized with the current month and year, but
       
  1969     QCalendarWidget provides several public slots to change the year
       
  1970     and month that is shown.
       
  1971 
       
  1972     By default, today's date is selected, and the user can select a
       
  1973     date using both mouse and keyboard. The currently selected date
       
  1974     can be retrieved using the selectedDate() function. It is
       
  1975     possible to constrain the user selection to a given date range by
       
  1976     setting the minimumDate and maximumDate properties.
       
  1977     Alternatively, both properties can be set in one go using the
       
  1978     setDateRange() convenience slot. Set the \l selectionMode
       
  1979     property to NoSelection to prohibit the user from selecting at
       
  1980     all. Note that a date also can be selected programmatically using
       
  1981     the setSelectedDate() slot.
       
  1982 
       
  1983     The currently displayed month and year can be retrieved using the
       
  1984     monthShown() and yearShown() functions, respectively.
       
  1985 
       
  1986     A newly created calendar widget uses abbreviated day names, and
       
  1987     both Saturdays and Sundays are marked in red. The calendar grid is
       
  1988     not visible. The week numbers are displayed, and the first column
       
  1989     day is Sunday.
       
  1990 
       
  1991     The notation of the days can be altered to a single letter
       
  1992     abbreviations ("M" for "Monday") by setting the
       
  1993     horizontalHeaderFormat property to
       
  1994     QCalendarWidget::SingleLetterDayNames. Setting the same property
       
  1995     to QCalendarWidget::LongDayNames makes the header display the
       
  1996     complete day names. The week numbers can be removed by setting
       
  1997     the verticalHeaderFormat property to
       
  1998     QCalendarWidget::NoVerticalHeader.  The calendar grid can be
       
  1999     turned on by setting the gridVisible property to true using the
       
  2000     setGridVisible() function:
       
  2001 
       
  2002     \table
       
  2003     \row \o
       
  2004         \image qcalendarwidget-grid.png
       
  2005     \row \o
       
  2006         \snippet doc/src/snippets/code/src_gui_widgets_qcalendarwidget.cpp 0
       
  2007     \endtable
       
  2008 
       
  2009     Finally, the day in the first column can be altered using the
       
  2010     setFirstDayOfWeek() function.
       
  2011 
       
  2012     The QCalendarWidget class also provides three signals,
       
  2013     selectionChanged(), activated() and currentPageChanged() making it
       
  2014     possible to respond to user interaction.
       
  2015 
       
  2016     The rendering of the headers, weekdays or single days can be
       
  2017     largely customized by setting QTextCharFormat's for some special
       
  2018     weekday, a special date or for the rendering of the headers.
       
  2019 
       
  2020     Only a subset of the properties in QTextCharFormat are used by the
       
  2021     calendar widget. Currently, the foreground, background and font
       
  2022     properties are used to determine the rendering of individual cells
       
  2023     in the widget.
       
  2024 
       
  2025     \sa QDate, QDateEdit, QTextCharFormat
       
  2026 */
       
  2027 
       
  2028 /*!
       
  2029     \enum QCalendarWidget::SelectionMode
       
  2030 
       
  2031     This enum describes the types of selection offered to the user for
       
  2032     selecting dates in the calendar.
       
  2033 
       
  2034     \value NoSelection      Dates cannot be selected.
       
  2035     \value SingleSelection  Single dates can be selected.
       
  2036 
       
  2037     \sa selectionMode
       
  2038 */
       
  2039 
       
  2040 /*!
       
  2041     Constructs a calendar widget with the given \a parent.
       
  2042 
       
  2043     The widget is initialized with the current month and year, and the
       
  2044     currently selected date is today.
       
  2045 
       
  2046     \sa setCurrentPage()
       
  2047 */
       
  2048 QCalendarWidget::QCalendarWidget(QWidget *parent)
       
  2049     : QWidget(*new QCalendarWidgetPrivate, parent, 0)
       
  2050 {
       
  2051     Q_D(QCalendarWidget);
       
  2052 
       
  2053     setAutoFillBackground(true);
       
  2054     setBackgroundRole(QPalette::Window);
       
  2055 
       
  2056     QVBoxLayout *layoutV = new QVBoxLayout(this);
       
  2057     layoutV->setMargin(0);
       
  2058     d->m_model = new QCalendarModel(this);
       
  2059     QTextCharFormat fmt;
       
  2060     fmt.setForeground(QBrush(Qt::red));
       
  2061     d->m_model->m_dayFormats.insert(Qt::Saturday, fmt);
       
  2062     d->m_model->m_dayFormats.insert(Qt::Sunday, fmt);
       
  2063     d->m_view = new QCalendarView(this);
       
  2064     d->m_view->setObjectName(QLatin1String("qt_calendar_calendarview"));
       
  2065     d->m_view->setModel(d->m_model);
       
  2066     d->m_model->setView(d->m_view);
       
  2067     d->m_view->setSelectionBehavior(QAbstractItemView::SelectItems);
       
  2068     d->m_view->setSelectionMode(QAbstractItemView::SingleSelection);
       
  2069     d->m_view->horizontalHeader()->setResizeMode(QHeaderView::Stretch);
       
  2070     d->m_view->horizontalHeader()->setClickable(false);
       
  2071     d->m_view->verticalHeader()->setResizeMode(QHeaderView::Stretch);
       
  2072     d->m_view->verticalHeader()->setClickable(false);
       
  2073     d->m_selection = d->m_view->selectionModel();
       
  2074     d->createNavigationBar(this);
       
  2075     d->m_view->setFrameStyle(QFrame::NoFrame);
       
  2076     d->m_delegate = new QCalendarDelegate(d, this);
       
  2077     d->m_view->setItemDelegate(d->m_delegate);
       
  2078     d->update();
       
  2079     d->updateNavigationBar();
       
  2080     setFocusPolicy(Qt::StrongFocus);
       
  2081     setFocusProxy(d->m_view);
       
  2082     setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
       
  2083 
       
  2084     connect(d->m_view, SIGNAL(showDate(QDate)),
       
  2085             this, SLOT(_q_slotShowDate(QDate)));
       
  2086     connect(d->m_view, SIGNAL(changeDate(QDate,bool)),
       
  2087             this, SLOT(_q_slotChangeDate(QDate,bool)));
       
  2088     connect(d->m_view, SIGNAL(clicked(QDate)),
       
  2089             this, SIGNAL(clicked(QDate)));
       
  2090     connect(d->m_view, SIGNAL(editingFinished()),
       
  2091             this, SLOT(_q_editingFinished()));
       
  2092 
       
  2093     connect(d->prevMonth, SIGNAL(clicked(bool)),
       
  2094             this, SLOT(_q_prevMonthClicked()));
       
  2095     connect(d->nextMonth, SIGNAL(clicked(bool)),
       
  2096             this, SLOT(_q_nextMonthClicked()));
       
  2097     connect(d->yearButton, SIGNAL(clicked(bool)),
       
  2098             this, SLOT(_q_yearClicked()));
       
  2099     connect(d->monthMenu, SIGNAL(triggered(QAction*)),
       
  2100             this, SLOT(_q_monthChanged(QAction*)));
       
  2101     connect(d->yearEdit, SIGNAL(editingFinished()),
       
  2102             this, SLOT(_q_yearEditingFinished()));
       
  2103 
       
  2104     layoutV->setMargin(0);
       
  2105     layoutV->setSpacing(0);
       
  2106     layoutV->addWidget(d->navBarBackground);
       
  2107     layoutV->addWidget(d->m_view);
       
  2108 
       
  2109     d->m_navigator = new QCalendarTextNavigator(this);
       
  2110     setDateEditEnabled(true);
       
  2111 }
       
  2112 
       
  2113 /*!
       
  2114    Destroys the calendar widget.
       
  2115 */
       
  2116 QCalendarWidget::~QCalendarWidget()
       
  2117 {
       
  2118 }
       
  2119 
       
  2120 /*!
       
  2121    \reimp
       
  2122 */
       
  2123 QSize QCalendarWidget::sizeHint() const
       
  2124 {
       
  2125     return minimumSizeHint();
       
  2126 }
       
  2127 
       
  2128 /*!
       
  2129    \reimp
       
  2130 */
       
  2131 QSize QCalendarWidget::minimumSizeHint() const
       
  2132 {
       
  2133     Q_D(const QCalendarWidget);
       
  2134     if (d->cachedSizeHint.isValid())
       
  2135         return d->cachedSizeHint;
       
  2136 
       
  2137     ensurePolished();
       
  2138 
       
  2139     int w = 0;
       
  2140     int h = 0;
       
  2141 
       
  2142     int end = 53;
       
  2143     int rows = 7;
       
  2144     int cols = 8;
       
  2145 
       
  2146     const int marginH = (style()->pixelMetric(QStyle::PM_FocusFrameHMargin) + 1) * 2;
       
  2147 
       
  2148     if (horizontalHeaderFormat() == QCalendarWidget::NoHorizontalHeader) {
       
  2149         rows = 6;
       
  2150     } else {
       
  2151         for (int i = 1; i <= 7; i++) {
       
  2152             QFontMetrics fm(d->m_model->formatForCell(0, i).font());
       
  2153             w = qMax(w, fm.width(d->m_model->dayName(d->m_model->dayOfWeekForColumn(i))) + marginH);
       
  2154             h = qMax(h, fm.height());
       
  2155         }
       
  2156     }
       
  2157 
       
  2158     if (verticalHeaderFormat() == QCalendarWidget::NoVerticalHeader) {
       
  2159         cols = 7;
       
  2160     } else {
       
  2161         for (int i = 1; i <= 6; i++) {
       
  2162             QFontMetrics fm(d->m_model->formatForCell(i, 0).font());
       
  2163             for (int j = 1; j < end; j++)
       
  2164                 w = qMax(w, fm.width(QString::number(j)) + marginH);
       
  2165             h = qMax(h, fm.height());
       
  2166         }
       
  2167     }
       
  2168 
       
  2169     QFontMetrics fm(d->m_model->formatForCell(1, 1).font());
       
  2170     for (int i = 1; i <= end; i++) {
       
  2171         w = qMax(w, fm.width(QString::number(i)) + marginH);
       
  2172         h = qMax(h, fm.height());
       
  2173     }
       
  2174 
       
  2175     if (d->m_view->showGrid()) {
       
  2176         // hardcoded in tableview
       
  2177         w += 1;
       
  2178         h += 1;
       
  2179     }
       
  2180 
       
  2181     w += 1; // default column span
       
  2182 
       
  2183     h = qMax(h, d->m_view->verticalHeader()->minimumSectionSize());
       
  2184     w = qMax(w, d->m_view->horizontalHeader()->minimumSectionSize());
       
  2185 
       
  2186     //add the size of the header.
       
  2187     QSize headerSize(0, 0);
       
  2188     if (d->navBarVisible) {
       
  2189         int headerH = d->navBarBackground->sizeHint().height();
       
  2190         int headerW = 0;
       
  2191 
       
  2192         headerW += d->prevMonth->sizeHint().width();
       
  2193         headerW += d->nextMonth->sizeHint().width();
       
  2194 
       
  2195         QFontMetrics fm = d->monthButton->fontMetrics();
       
  2196         int monthW = 0;
       
  2197         for (int i = 1; i < 12; i++) {
       
  2198             QString monthName = locale().standaloneMonthName(i, QLocale::LongFormat);
       
  2199             monthW = qMax(monthW, fm.boundingRect(monthName).width());
       
  2200         }
       
  2201         const int buttonDecoMargin = d->monthButton->sizeHint().width() - fm.boundingRect(d->monthButton->text()).width();
       
  2202         headerW += monthW + buttonDecoMargin;
       
  2203 
       
  2204         fm = d->yearButton->fontMetrics();
       
  2205         headerW += fm.boundingRect(QLatin1String("5555")).width() + buttonDecoMargin;
       
  2206 
       
  2207         headerSize = QSize(headerW, headerH);
       
  2208     }
       
  2209     w *= cols;
       
  2210     w = qMax(headerSize.width(), w);
       
  2211     h = (h * rows) + headerSize.height();
       
  2212     d->cachedSizeHint = QSize(w, h);
       
  2213     return d->cachedSizeHint;
       
  2214 }
       
  2215 
       
  2216 /*!
       
  2217     Paints the cell specified by the given \a date, using the given \a painter and \a rect.
       
  2218 */
       
  2219 
       
  2220 void QCalendarWidget::paintCell(QPainter *painter, const QRect &rect, const QDate &date) const
       
  2221 {
       
  2222     Q_D(const QCalendarWidget);
       
  2223     d->m_delegate->paintCell(painter, rect, date);
       
  2224 }
       
  2225 
       
  2226 /*!
       
  2227     \property QCalendarWidget::selectedDate
       
  2228     \brief the currently selected date.
       
  2229 
       
  2230     The selected date must be within the date range specified by the
       
  2231     minimumDate and maximumDate properties. By default, the selected
       
  2232     date is the current date.
       
  2233 
       
  2234     \sa setDateRange()
       
  2235 */
       
  2236 
       
  2237 QDate QCalendarWidget::selectedDate() const
       
  2238 {
       
  2239     Q_D(const QCalendarWidget);
       
  2240     return d->m_model->m_date;
       
  2241 }
       
  2242 
       
  2243 void QCalendarWidget::setSelectedDate(const QDate &date)
       
  2244 {
       
  2245     Q_D(QCalendarWidget);
       
  2246     if (d->m_model->m_date == date && date == d->getCurrentDate())
       
  2247         return;
       
  2248 
       
  2249     if (!date.isValid())
       
  2250         return;
       
  2251 
       
  2252     d->m_model->setDate(date);
       
  2253     d->update();
       
  2254     QDate newDate = d->m_model->m_date;
       
  2255     d->showMonth(newDate.year(), newDate.month());
       
  2256     emit selectionChanged();
       
  2257 }
       
  2258 
       
  2259 /*!
       
  2260     Returns the year of the currently displayed month. Months are
       
  2261     numbered from 1 to 12.
       
  2262 
       
  2263     \sa monthShown(), setCurrentPage()
       
  2264 */
       
  2265 
       
  2266 int QCalendarWidget::yearShown() const
       
  2267 {
       
  2268     Q_D(const QCalendarWidget);
       
  2269     return d->m_model->m_shownYear;
       
  2270 }
       
  2271 
       
  2272 /*!
       
  2273     Returns the currently displayed month. Months are numbered from 1 to
       
  2274     12.
       
  2275 
       
  2276     \sa yearShown(), setCurrentPage()
       
  2277 */
       
  2278 
       
  2279 int QCalendarWidget::monthShown() const
       
  2280 {
       
  2281     Q_D(const QCalendarWidget);
       
  2282     return d->m_model->m_shownMonth;
       
  2283 }
       
  2284 
       
  2285 /*!
       
  2286     Displays the given \a month of the given \a year without changing
       
  2287     the selected date. Use the setSelectedDate() function to alter the
       
  2288     selected date.
       
  2289 
       
  2290     The currently displayed month and year can be retrieved using the
       
  2291     monthShown() and yearShown() functions respectively.
       
  2292 
       
  2293     \sa yearShown(), monthShown(), showPreviousMonth(), showNextMonth(),
       
  2294     showPreviousYear(), showNextYear()
       
  2295 */
       
  2296 
       
  2297 void QCalendarWidget::setCurrentPage(int year, int month)
       
  2298 {
       
  2299     Q_D(QCalendarWidget);
       
  2300     d->showMonth(year, month);
       
  2301 }
       
  2302 
       
  2303 /*!
       
  2304     Shows the next month relative to the currently displayed
       
  2305     month. Note that the selected date is not changed.
       
  2306 
       
  2307     \sa showPreviousMonth(), setCurrentPage(), setSelectedDate()
       
  2308 */
       
  2309 
       
  2310 void QCalendarWidget::showNextMonth()
       
  2311 {
       
  2312     int year = yearShown();
       
  2313     int month = monthShown();
       
  2314     if (month == 12) {
       
  2315         ++year;
       
  2316         month = 1;
       
  2317     } else {
       
  2318         ++month;
       
  2319     }
       
  2320     setCurrentPage(year, month);
       
  2321 }
       
  2322 
       
  2323 /*!
       
  2324     Shows the previous month relative to the currently displayed
       
  2325     month. Note that the selected date is not changed.
       
  2326 
       
  2327     \sa showNextMonth(), setCurrentPage(), setSelectedDate()
       
  2328 */
       
  2329 
       
  2330 void QCalendarWidget::showPreviousMonth()
       
  2331 {
       
  2332     int year = yearShown();
       
  2333     int month = monthShown();
       
  2334     if (month == 1) {
       
  2335         --year;
       
  2336         month = 12;
       
  2337     } else {
       
  2338         --month;
       
  2339     }
       
  2340     setCurrentPage(year, month);
       
  2341 }
       
  2342 
       
  2343 /*!
       
  2344     Shows the currently displayed month in the \e next year relative
       
  2345     to the currently displayed year. Note that the selected date is
       
  2346     not changed.
       
  2347 
       
  2348     \sa showPreviousYear(), setCurrentPage(), setSelectedDate()
       
  2349 */
       
  2350 
       
  2351 void QCalendarWidget::showNextYear()
       
  2352 {
       
  2353     int year = yearShown();
       
  2354     int month = monthShown();
       
  2355     ++year;
       
  2356     setCurrentPage(year, month);
       
  2357 }
       
  2358 
       
  2359 /*!
       
  2360     Shows the currently displayed month in the \e previous year
       
  2361     relative to the currently displayed year. Note that the selected
       
  2362     date is not changed.
       
  2363 
       
  2364     \sa showNextYear(), setCurrentPage(), setSelectedDate()
       
  2365 */
       
  2366 
       
  2367 void QCalendarWidget::showPreviousYear()
       
  2368 {
       
  2369     int year = yearShown();
       
  2370     int month = monthShown();
       
  2371     --year;
       
  2372     setCurrentPage(year, month);
       
  2373 }
       
  2374 
       
  2375 /*!
       
  2376     Shows the month of the selected date.
       
  2377 
       
  2378     \sa selectedDate(), setCurrentPage()
       
  2379 */
       
  2380 void QCalendarWidget::showSelectedDate()
       
  2381 {
       
  2382     QDate currentDate = selectedDate();
       
  2383     setCurrentPage(currentDate.year(), currentDate.month());
       
  2384 }
       
  2385 
       
  2386 /*!
       
  2387     Shows the month of the today's date.
       
  2388 
       
  2389     \sa selectedDate(), setCurrentPage()
       
  2390 */
       
  2391 void QCalendarWidget::showToday()
       
  2392 {
       
  2393     QDate currentDate = QDate::currentDate();
       
  2394     setCurrentPage(currentDate.year(), currentDate.month());
       
  2395 }
       
  2396 
       
  2397 /*!
       
  2398     \property QCalendarWidget::minimumDate
       
  2399     \brief the minimum date of the currently specified date range.
       
  2400 
       
  2401     The user will not be able to select a date that is before the
       
  2402     currently set minimum date.
       
  2403 
       
  2404     \table
       
  2405     \row
       
  2406     \o \image qcalendarwidget-minimum.png
       
  2407     \row
       
  2408     \o
       
  2409     \snippet doc/src/snippets/code/src_gui_widgets_qcalendarwidget.cpp 1
       
  2410     \endtable
       
  2411 
       
  2412     By default, the minimum date is the earliest date that the QDate
       
  2413     class can handle.
       
  2414 
       
  2415     When setting a minimum date, the maximumDate and selectedDate
       
  2416     properties are adjusted if the selection range becomes invalid. If
       
  2417     the provided date is not a valid QDate object, the
       
  2418     setMinimumDate() function does nothing.
       
  2419 
       
  2420     \sa setDateRange()
       
  2421 */
       
  2422 
       
  2423 QDate QCalendarWidget::minimumDate() const
       
  2424 {
       
  2425     Q_D(const QCalendarWidget);
       
  2426     return d->m_model->m_minimumDate;
       
  2427 }
       
  2428 
       
  2429 void QCalendarWidget::setMinimumDate(const QDate &date)
       
  2430 {
       
  2431     Q_D(QCalendarWidget);
       
  2432     if (!date.isValid() || d->m_model->m_minimumDate == date)
       
  2433         return;
       
  2434 
       
  2435     QDate oldDate = d->m_model->m_date;
       
  2436     d->m_model->setMinimumDate(date);
       
  2437     d->yearEdit->setMinimum(d->m_model->m_minimumDate.year());
       
  2438     d->updateMonthMenu();
       
  2439     QDate newDate = d->m_model->m_date;
       
  2440     if (oldDate != newDate) {
       
  2441         d->update();
       
  2442         d->showMonth(newDate.year(), newDate.month());
       
  2443         d->m_navigator->setDate(newDate);
       
  2444         emit selectionChanged();
       
  2445     }
       
  2446 }
       
  2447 
       
  2448 /*!
       
  2449     \property QCalendarWidget::maximumDate
       
  2450     \brief the maximum date of the currently specified date range.
       
  2451 
       
  2452     The user will not be able to select a date which is after the
       
  2453     currently set maximum date.
       
  2454 
       
  2455     \table
       
  2456     \row
       
  2457     \o \image qcalendarwidget-maximum.png
       
  2458     \row
       
  2459     \o
       
  2460     \snippet doc/src/snippets/code/src_gui_widgets_qcalendarwidget.cpp 2
       
  2461     \endtable
       
  2462 
       
  2463     By default, the maximum date is the last day the QDate class can
       
  2464     handle.
       
  2465 
       
  2466     When setting a maximum date, the minimumDate and selectedDate
       
  2467     properties are adjusted if the selection range becomes invalid. If
       
  2468     the provided date is not a valid QDate object, the
       
  2469     setMaximumDate() function does nothing.
       
  2470 
       
  2471     \sa setDateRange()
       
  2472 */
       
  2473 
       
  2474 QDate QCalendarWidget::maximumDate() const
       
  2475 {
       
  2476     Q_D(const QCalendarWidget);
       
  2477     return d->m_model->m_maximumDate;
       
  2478 }
       
  2479 
       
  2480 void QCalendarWidget::setMaximumDate(const QDate &date)
       
  2481 {
       
  2482     Q_D(QCalendarWidget);
       
  2483     if (!date.isValid() || d->m_model->m_maximumDate == date)
       
  2484         return;
       
  2485 
       
  2486     QDate oldDate = d->m_model->m_date;
       
  2487     d->m_model->setMaximumDate(date);
       
  2488     d->yearEdit->setMaximum(d->m_model->m_maximumDate.year());
       
  2489     d->updateMonthMenu();
       
  2490     QDate newDate = d->m_model->m_date;
       
  2491     if (oldDate != newDate) {
       
  2492         d->update();
       
  2493         d->showMonth(newDate.year(), newDate.month());
       
  2494         d->m_navigator->setDate(newDate);
       
  2495         emit selectionChanged();
       
  2496     }
       
  2497 }
       
  2498 
       
  2499 /*!
       
  2500     Defines a date range by setting the minimumDate and maximumDate
       
  2501     properties.
       
  2502 
       
  2503     The date range restricts the user selection, i.e. the user can
       
  2504     only select dates within the specified date range. Note that
       
  2505 
       
  2506     \snippet doc/src/snippets/code/src_gui_widgets_qcalendarwidget.cpp 3
       
  2507 
       
  2508     is analogous to
       
  2509 
       
  2510     \snippet doc/src/snippets/code/src_gui_widgets_qcalendarwidget.cpp 4
       
  2511 
       
  2512     If either the \a min or \a max parameters are not valid QDate
       
  2513     objects, this function does nothing.
       
  2514 
       
  2515     \sa setMinimumDate(), setMaximumDate()
       
  2516 */
       
  2517 
       
  2518 void QCalendarWidget::setDateRange(const QDate &min, const QDate &max)
       
  2519 {
       
  2520     Q_D(QCalendarWidget);
       
  2521     if (d->m_model->m_minimumDate == min && d->m_model->m_maximumDate == max)
       
  2522         return;
       
  2523     if (!min.isValid() || !max.isValid())
       
  2524         return;
       
  2525 
       
  2526     QDate oldDate = d->m_model->m_date;
       
  2527     d->m_model->setRange(min, max);
       
  2528     d->yearEdit->setMinimum(d->m_model->m_minimumDate.year());
       
  2529     d->yearEdit->setMaximum(d->m_model->m_maximumDate.year());
       
  2530     d->updateMonthMenu();
       
  2531     QDate newDate = d->m_model->m_date;
       
  2532     if (oldDate != newDate) {
       
  2533         d->update();
       
  2534         d->showMonth(newDate.year(), newDate.month());
       
  2535         d->m_navigator->setDate(newDate);
       
  2536         emit selectionChanged();
       
  2537     }
       
  2538 }
       
  2539 
       
  2540 
       
  2541 /*! \enum QCalendarWidget::HorizontalHeaderFormat
       
  2542 
       
  2543     This enum type defines the various formats the horizontal header can display.
       
  2544 
       
  2545     \value SingleLetterDayNames The header displays a single letter abbreviation for day names (e.g. M for Monday).
       
  2546     \value ShortDayNames The header displays a short abbreviation for day names (e.g. Mon for Monday).
       
  2547     \value LongDayNames The header displays complete day names (e.g. Monday).
       
  2548     \value NoHorizontalHeader The header is hidden.
       
  2549 
       
  2550     \sa horizontalHeaderFormat(), VerticalHeaderFormat
       
  2551 */
       
  2552 
       
  2553 /*!
       
  2554     \property QCalendarWidget::horizontalHeaderFormat
       
  2555     \brief the format of the horizontal header.
       
  2556 
       
  2557     The default value is QCalendarWidget::ShortDayNames.
       
  2558 */
       
  2559 
       
  2560 void QCalendarWidget::setHorizontalHeaderFormat(QCalendarWidget::HorizontalHeaderFormat format)
       
  2561 {
       
  2562     Q_D(QCalendarWidget);
       
  2563     if (d->m_model->m_horizontalHeaderFormat == format)
       
  2564         return;
       
  2565 
       
  2566     d->m_model->setHorizontalHeaderFormat(format);
       
  2567     d->cachedSizeHint = QSize();
       
  2568     d->m_view->viewport()->update();
       
  2569     d->m_view->updateGeometry();
       
  2570 }
       
  2571 
       
  2572 QCalendarWidget::HorizontalHeaderFormat QCalendarWidget::horizontalHeaderFormat() const
       
  2573 {
       
  2574     Q_D(const QCalendarWidget);
       
  2575     return d->m_model->m_horizontalHeaderFormat;
       
  2576 }
       
  2577 
       
  2578 
       
  2579 /*! 
       
  2580     \enum QCalendarWidget::VerticalHeaderFormat
       
  2581 
       
  2582     This enum type defines the various formats the vertical header can display.
       
  2583 
       
  2584     \value ISOWeekNumbers The header displays ISO week numbers as described by \l QDate::weekNumber().
       
  2585     \value NoVerticalHeader The header is hidden.
       
  2586 
       
  2587     \sa verticalHeaderFormat(), HorizontalHeaderFormat
       
  2588 */
       
  2589 
       
  2590 /*!
       
  2591     \property QCalendarWidget::verticalHeaderFormat
       
  2592     \brief the format of the vertical header.
       
  2593 
       
  2594     The default value is QCalendarWidget::ISOWeekNumber.
       
  2595 */
       
  2596 
       
  2597 QCalendarWidget::VerticalHeaderFormat QCalendarWidget::verticalHeaderFormat() const
       
  2598 {
       
  2599     Q_D(const QCalendarWidget);
       
  2600     bool shown = d->m_model->weekNumbersShown();
       
  2601     if (shown)
       
  2602         return QCalendarWidget::ISOWeekNumbers;
       
  2603     return QCalendarWidget::NoVerticalHeader;
       
  2604 }
       
  2605 
       
  2606 void QCalendarWidget::setVerticalHeaderFormat(QCalendarWidget::VerticalHeaderFormat format)
       
  2607 {
       
  2608     Q_D(QCalendarWidget);
       
  2609     bool show = false;
       
  2610     if (format == QCalendarWidget::ISOWeekNumbers)
       
  2611         show = true;
       
  2612     if (d->m_model->weekNumbersShown() == show)
       
  2613         return;
       
  2614     d->m_model->setWeekNumbersShown(show);
       
  2615     d->cachedSizeHint = QSize();
       
  2616     d->m_view->viewport()->update();
       
  2617     d->m_view->updateGeometry();
       
  2618 }
       
  2619 
       
  2620 /*!
       
  2621     \property QCalendarWidget::gridVisible
       
  2622     \brief whether the table grid is displayed.
       
  2623 
       
  2624     \table
       
  2625     \row
       
  2626         \o \inlineimage qcalendarwidget-grid.png
       
  2627     \row
       
  2628         \o
       
  2629         \snippet doc/src/snippets/code/src_gui_widgets_qcalendarwidget.cpp 5
       
  2630     \endtable
       
  2631 
       
  2632     The default value is false.
       
  2633 */
       
  2634 
       
  2635 bool QCalendarWidget::isGridVisible() const
       
  2636 {
       
  2637     Q_D(const QCalendarWidget);
       
  2638     return d->m_view->showGrid();
       
  2639 }
       
  2640 
       
  2641 void QCalendarWidget::setGridVisible(bool show)
       
  2642 {
       
  2643     Q_D(QCalendarWidget);
       
  2644     d->m_view->setShowGrid(show);
       
  2645     d->cachedSizeHint = QSize();
       
  2646     d->m_view->viewport()->update();
       
  2647     d->m_view->updateGeometry();
       
  2648 }
       
  2649 
       
  2650 /*!
       
  2651     \property QCalendarWidget::selectionMode
       
  2652     \brief the type of selection the user can make in the calendar
       
  2653 
       
  2654     When this property is set to SingleSelection, the user can select a date
       
  2655     within the minimum and maximum allowed dates, using either the mouse or
       
  2656     the keyboard.
       
  2657 
       
  2658     When the property is set to NoSelection, the user will be unable to select
       
  2659     dates, but they can still be selected programmatically. Note that the date
       
  2660     that is selected when the property is set to NoSelection will still be
       
  2661     the selected date of the calendar.
       
  2662 
       
  2663     The default value is SingleSelection.
       
  2664 */
       
  2665 
       
  2666 QCalendarWidget::SelectionMode QCalendarWidget::selectionMode() const
       
  2667 {
       
  2668     Q_D(const QCalendarWidget);
       
  2669     return d->m_view->readOnly ? QCalendarWidget::NoSelection : QCalendarWidget::SingleSelection;
       
  2670 }
       
  2671 
       
  2672 void QCalendarWidget::setSelectionMode(SelectionMode mode)
       
  2673 {
       
  2674     Q_D(QCalendarWidget);
       
  2675     d->m_view->readOnly = (mode == QCalendarWidget::NoSelection);
       
  2676     d->setNavigatorEnabled(isDateEditEnabled() && (selectionMode() != QCalendarWidget::NoSelection));
       
  2677     d->update();
       
  2678 }
       
  2679 
       
  2680 /*!
       
  2681     \property QCalendarWidget::firstDayOfWeek
       
  2682     \brief a value identifying the day displayed in the first column.
       
  2683 
       
  2684     By default, the day displayed in the first column is Sunday
       
  2685 */
       
  2686 
       
  2687 void QCalendarWidget::setFirstDayOfWeek(Qt::DayOfWeek dayOfWeek)
       
  2688 {
       
  2689     Q_D(QCalendarWidget);
       
  2690     if ((Qt::DayOfWeek)d->m_model->firstColumnDay() == dayOfWeek)
       
  2691         return;
       
  2692 
       
  2693     d->m_model->setFirstColumnDay(dayOfWeek);
       
  2694     d->update();
       
  2695 }
       
  2696 
       
  2697 Qt::DayOfWeek QCalendarWidget::firstDayOfWeek() const
       
  2698 {
       
  2699     Q_D(const QCalendarWidget);
       
  2700     return (Qt::DayOfWeek)d->m_model->firstColumnDay();
       
  2701 }
       
  2702 
       
  2703 /*!
       
  2704     Returns the text char format for rendering the header.
       
  2705 */
       
  2706 QTextCharFormat QCalendarWidget::headerTextFormat() const
       
  2707 {
       
  2708     Q_D(const QCalendarWidget);
       
  2709     return d->m_model->m_headerFormat;
       
  2710 }
       
  2711 
       
  2712 /*!
       
  2713     Sets the text char format for rendering the header to \a format.
       
  2714     If you also set a weekday text format, this format's foreground and
       
  2715     background color will take precedence over the header's format.
       
  2716     The other formatting information will still be decided by
       
  2717     the header's format.
       
  2718 */
       
  2719 void QCalendarWidget::setHeaderTextFormat(const QTextCharFormat &format)
       
  2720 {
       
  2721     Q_D(QCalendarWidget);
       
  2722     d->m_model->m_headerFormat = format;
       
  2723     d->cachedSizeHint = QSize();
       
  2724     d->m_view->viewport()->update();
       
  2725     d->m_view->updateGeometry();
       
  2726 }
       
  2727 
       
  2728 /*!
       
  2729     Returns the text char format for rendering of day in the week \a dayOfWeek.
       
  2730 
       
  2731     \sa headerTextFormat()
       
  2732 */
       
  2733 QTextCharFormat QCalendarWidget::weekdayTextFormat(Qt::DayOfWeek dayOfWeek) const
       
  2734 {
       
  2735     Q_D(const QCalendarWidget);
       
  2736     return d->m_model->m_dayFormats.value(dayOfWeek);
       
  2737 }
       
  2738 
       
  2739 /*!
       
  2740     Sets the text char format for rendering of day in the week \a dayOfWeek to \a format.
       
  2741     The format will take precedence over the header format in case of foreground
       
  2742     and background color. Other text formatting information is taken from the headers format.
       
  2743 
       
  2744     \sa setHeaderTextFormat()
       
  2745 */
       
  2746 void QCalendarWidget::setWeekdayTextFormat(Qt::DayOfWeek dayOfWeek, const QTextCharFormat &format)
       
  2747 {
       
  2748     Q_D(QCalendarWidget);
       
  2749     d->m_model->m_dayFormats[dayOfWeek] = format;
       
  2750     d->cachedSizeHint = QSize();
       
  2751     d->m_view->viewport()->update();
       
  2752     d->m_view->updateGeometry();
       
  2753 }
       
  2754 
       
  2755 /*!
       
  2756     Returns a QMap from QDate to QTextCharFormat showing all dates
       
  2757     that use a special format that alters their rendering.
       
  2758 */
       
  2759 QMap<QDate, QTextCharFormat> QCalendarWidget::dateTextFormat() const
       
  2760 {
       
  2761     Q_D(const QCalendarWidget);
       
  2762     return d->m_model->m_dateFormats;
       
  2763 }
       
  2764 
       
  2765 /*!
       
  2766     Returns a QTextCharFormat for \a date. The char format can be be
       
  2767     empty if the date is not renderd specially.
       
  2768 */
       
  2769 QTextCharFormat QCalendarWidget::dateTextFormat(const QDate &date) const
       
  2770 {
       
  2771     Q_D(const QCalendarWidget);
       
  2772     return d->m_model->m_dateFormats.value(date);
       
  2773 }
       
  2774 
       
  2775 /*!
       
  2776     Sets the format used to render the given \a date to that specified by \a format.
       
  2777 
       
  2778     If \a date is null, all date formats are cleared.
       
  2779 */
       
  2780 void QCalendarWidget::setDateTextFormat(const QDate &date, const QTextCharFormat &format)
       
  2781 {
       
  2782     Q_D(QCalendarWidget);
       
  2783     if (date.isNull())
       
  2784         d->m_model->m_dateFormats.clear();
       
  2785     else
       
  2786         d->m_model->m_dateFormats[date] = format;
       
  2787     d->m_view->viewport()->update();
       
  2788     d->m_view->updateGeometry();
       
  2789 }
       
  2790 
       
  2791 /*!
       
  2792     \property QCalendarWidget::dateEditEnabled
       
  2793     \brief whether the date edit popup is enabled
       
  2794     \since 4.3
       
  2795 
       
  2796     If this property is enabled, pressing a non-modifier key will cause a
       
  2797     date edit to popup if the calendar widget has focus, allowing the user
       
  2798     to specify a date in the form specified by the current locale.
       
  2799 
       
  2800     By default, this property is enabled.
       
  2801 
       
  2802     The date edit is simpler in appearance than QDateEdit, but allows the
       
  2803     user to navigate between fields using the left and right cursor keys,
       
  2804     increment and decrement individual fields using the up and down cursor
       
  2805     keys, and enter values directly using the number keys.
       
  2806 
       
  2807     \sa QCalendarWidget::dateEditAcceptDelay
       
  2808 */
       
  2809 bool QCalendarWidget::isDateEditEnabled() const
       
  2810 {
       
  2811     Q_D(const QCalendarWidget);
       
  2812     return d->m_dateEditEnabled;
       
  2813 }
       
  2814 
       
  2815 void QCalendarWidget::setDateEditEnabled(bool enable)
       
  2816 {
       
  2817     Q_D(QCalendarWidget);
       
  2818     if (isDateEditEnabled() == enable)
       
  2819         return;
       
  2820 
       
  2821     d->m_dateEditEnabled = enable;
       
  2822 
       
  2823     d->setNavigatorEnabled(enable && (selectionMode() != QCalendarWidget::NoSelection));
       
  2824 }
       
  2825 
       
  2826 /*!
       
  2827     \property QCalendarWidget::dateEditAcceptDelay
       
  2828     \brief the time an inactive date edit is shown before its contents are accepted
       
  2829     \since 4.3
       
  2830 
       
  2831     If the calendar widget's \l{dateEditEnabled}{date edit is enabled}, this
       
  2832     property specifies the amount of time (in millseconds) that the date edit
       
  2833     remains open after the most recent user input. Once this time has elapsed,
       
  2834     the date specified in the date edit is accepted and the popup is closed.
       
  2835 
       
  2836     By default, the delay is defined to be 1500 milliseconds (1.5 seconds).
       
  2837 */
       
  2838 int QCalendarWidget::dateEditAcceptDelay() const
       
  2839 {
       
  2840     Q_D(const QCalendarWidget);
       
  2841     return d->m_navigator->dateEditAcceptDelay();
       
  2842 }
       
  2843 
       
  2844 void QCalendarWidget::setDateEditAcceptDelay(int delay)
       
  2845 {
       
  2846     Q_D(QCalendarWidget);
       
  2847     d->m_navigator->setDateEditAcceptDelay(delay);
       
  2848 }
       
  2849 
       
  2850 /*!
       
  2851     \since 4.4
       
  2852 
       
  2853     Updates the cell specified by the given \a date unless updates
       
  2854     are disabled or the cell is hidden.
       
  2855 
       
  2856     \sa updateCells(), yearShown(), monthShown()
       
  2857 */
       
  2858 void QCalendarWidget::updateCell(const QDate &date)
       
  2859 {
       
  2860     if (!date.isValid()) {
       
  2861         qWarning("QCalendarWidget::updateCell: Invalid date");
       
  2862         return;
       
  2863     }
       
  2864 
       
  2865     if (!isVisible())
       
  2866         return;
       
  2867 
       
  2868     Q_D(QCalendarWidget);
       
  2869     int row, column;
       
  2870     d->m_model->cellForDate(date, &row, &column);
       
  2871     if (row == -1 || column == -1)
       
  2872         return;
       
  2873 
       
  2874     QModelIndex modelIndex = d->m_model->index(row, column);
       
  2875     if (!modelIndex.isValid())
       
  2876         return;
       
  2877 
       
  2878     d->m_view->viewport()->update(d->m_view->visualRect(modelIndex));
       
  2879 }
       
  2880 
       
  2881 /*!
       
  2882     \since 4.4
       
  2883 
       
  2884     Updates all visible cells unless updates are disabled.
       
  2885 
       
  2886     \sa updateCell()
       
  2887 */
       
  2888 void QCalendarWidget::updateCells()
       
  2889 {
       
  2890     Q_D(QCalendarWidget);
       
  2891     if (isVisible())
       
  2892         d->m_view->viewport()->update();
       
  2893 }
       
  2894 
       
  2895 /*!
       
  2896     \fn void QCalendarWidget::selectionChanged()
       
  2897 
       
  2898     This signal is emitted when the currently selected date is
       
  2899     changed.
       
  2900 
       
  2901     The currently selected date can be changed by the user using the
       
  2902     mouse or keyboard, or by the programmer using setSelectedDate().
       
  2903 
       
  2904     \sa selectedDate()
       
  2905 */
       
  2906 
       
  2907 /*!
       
  2908     \fn void QCalendarWidget::currentPageChanged(int year, int month)
       
  2909 
       
  2910     This signal is emitted when the currently shown month is changed.
       
  2911     The new \a year and \a month are passed as parameters.
       
  2912 
       
  2913     \sa setCurrentPage()
       
  2914 */
       
  2915 
       
  2916 /*!
       
  2917     \fn void QCalendarWidget::activated(const QDate &date)
       
  2918 
       
  2919     This signal is emitted whenever the user presses the Return or
       
  2920     Enter key or double-clicks a \a date in the calendar
       
  2921     widget.
       
  2922 */
       
  2923 
       
  2924 /*!
       
  2925     \fn void QCalendarWidget::clicked(const QDate &date)
       
  2926 
       
  2927     This signal is emitted when a mouse button is clicked. The date
       
  2928     the mouse was clicked on is specified by \a date. The signal is
       
  2929     only emitted when clicked on a valid date, e.g., dates are not
       
  2930     outside the minimumDate() and maximumDate(). If the selection mode
       
  2931     is NoSelection, this signal will not be emitted.
       
  2932 
       
  2933 */
       
  2934 
       
  2935 /*!
       
  2936     \property QCalendarWidget::headerVisible
       
  2937     \brief whether the navigation bar is shown or not
       
  2938 
       
  2939     \obsolete
       
  2940 
       
  2941     Use navigationBarVisible() instead.
       
  2942 
       
  2943     By default, this property is true.
       
  2944 */
       
  2945 
       
  2946 /*!
       
  2947     \obsolete
       
  2948 
       
  2949     Use setNavigationBarVisible() instead.
       
  2950 */
       
  2951 bool QCalendarWidget::isHeaderVisible() const
       
  2952 {
       
  2953     Q_D(const QCalendarWidget);
       
  2954     return d->navBarVisible;
       
  2955 }
       
  2956 
       
  2957 /*!
       
  2958     \obsolete
       
  2959 
       
  2960     Use setNavigationBarVisible() instead.
       
  2961 
       
  2962 */
       
  2963 void QCalendarWidget::setHeaderVisible(bool visible)
       
  2964 {
       
  2965     setNavigationBarVisible(visible);
       
  2966 }
       
  2967 
       
  2968 /*!
       
  2969     \property QCalendarWidget::navigationBarVisible
       
  2970     \brief whether the navigation bar is shown or not
       
  2971 
       
  2972     \since 4.3
       
  2973 
       
  2974     When this property is true (the default), the next month,
       
  2975     previous month, month selection, year selection controls are
       
  2976     shown on top.
       
  2977 
       
  2978     When the property is set to false, these controls are hidden.
       
  2979 */
       
  2980 
       
  2981 void QCalendarWidget::setNavigationBarVisible(bool visible)
       
  2982 {
       
  2983     Q_D(QCalendarWidget);
       
  2984     d->navBarVisible = visible;
       
  2985     d->cachedSizeHint = QSize();
       
  2986     d->navBarBackground->setVisible(visible);
       
  2987     updateGeometry();
       
  2988 }
       
  2989 
       
  2990 /*!
       
  2991   \reimp
       
  2992 */
       
  2993 bool QCalendarWidget::event(QEvent *event)
       
  2994 {
       
  2995     Q_D(QCalendarWidget);
       
  2996     switch (event->type()) {
       
  2997         case QEvent::LayoutDirectionChange:
       
  2998             d->updateButtonIcons();
       
  2999         case QEvent::LocaleChange:
       
  3000             d->cachedSizeHint = QSize();
       
  3001             d->updateMonthMenuNames();
       
  3002             d->updateNavigationBar();
       
  3003             d->m_view->updateGeometry();
       
  3004             break;
       
  3005         case QEvent::FontChange:
       
  3006         case QEvent::ApplicationFontChange:
       
  3007             d->cachedSizeHint = QSize();
       
  3008             d->m_view->updateGeometry();
       
  3009             break;
       
  3010         case QEvent::StyleChange:
       
  3011             d->cachedSizeHint = QSize();
       
  3012             d->m_view->updateGeometry();
       
  3013         default:
       
  3014             break;
       
  3015     }
       
  3016     return QWidget::event(event);
       
  3017 }
       
  3018 
       
  3019 /*!
       
  3020   \reimp
       
  3021 */
       
  3022 bool QCalendarWidget::eventFilter(QObject *watched, QEvent *event)
       
  3023 {
       
  3024     Q_D(QCalendarWidget);
       
  3025     if (event->type() == QEvent::MouseButtonPress && d->yearEdit->hasFocus()) {
       
  3026         QWidget *tlw = window();
       
  3027         QWidget *widget = static_cast<QWidget*>(watched);
       
  3028         //as we have a event filter on the whole application we first make sure that the top level widget
       
  3029         //of both this and the watched widget are the same to decide if we should finish the year edition.
       
  3030         if (widget->window() == tlw) {
       
  3031             QPoint mousePos = widget->mapTo(tlw, static_cast<QMouseEvent *>(event)->pos());
       
  3032             QRect geom = QRect(d->yearEdit->mapTo(tlw, QPoint(0, 0)), d->yearEdit->size());
       
  3033             if (!geom.contains(mousePos)) {
       
  3034                 event->accept();
       
  3035                 d->_q_yearEditingFinished();
       
  3036                 setFocus();
       
  3037                 return true;
       
  3038             }
       
  3039         }
       
  3040     }
       
  3041     return QWidget::eventFilter(watched, event);
       
  3042 }
       
  3043 
       
  3044 /*!
       
  3045   \reimp
       
  3046 */
       
  3047 void QCalendarWidget::mousePressEvent(QMouseEvent *event)
       
  3048 {
       
  3049     setAttribute(Qt::WA_NoMouseReplay);
       
  3050     QWidget::mousePressEvent(event);
       
  3051     setFocus();
       
  3052 }
       
  3053 
       
  3054 /*!
       
  3055   \reimp
       
  3056 */
       
  3057 void QCalendarWidget::resizeEvent(QResizeEvent * event)
       
  3058 {
       
  3059     Q_D(QCalendarWidget);
       
  3060 
       
  3061     // XXX Should really use a QWidgetStack for yearEdit and yearButton,
       
  3062     // XXX here we hide the year edit when the layout is likely to break
       
  3063     // XXX the manual positioning of the yearEdit over the yearButton.
       
  3064     if(d->yearEdit->isVisible() && event->size().width() != event->oldSize().width())
       
  3065         d->_q_yearEditingFinished();
       
  3066 
       
  3067     QWidget::resizeEvent(event);
       
  3068 }
       
  3069 
       
  3070 /*!
       
  3071   \reimp
       
  3072 */
       
  3073 void QCalendarWidget::keyPressEvent(QKeyEvent * event)
       
  3074 {
       
  3075     Q_D(QCalendarWidget);
       
  3076     if(d->yearEdit->isVisible()&& event->key() == Qt::Key_Escape)
       
  3077     {
       
  3078         d->yearEdit->setValue(yearShown());
       
  3079         d->_q_yearEditingFinished();
       
  3080         return;
       
  3081     }
       
  3082     QWidget::keyPressEvent(event);
       
  3083 }
       
  3084 
       
  3085 QT_END_NAMESPACE
       
  3086 
       
  3087 #include "qcalendarwidget.moc"
       
  3088 #include "moc_qcalendarwidget.cpp"
       
  3089 
       
  3090 #endif //QT_NO_CALENDARWIDGET