~ubuntu-branches/ubuntu/wily/qtbase-opensource-src/wily

« back to all changes in this revision

Viewing changes to src/widgets/widgets/qcalendarwidget.cpp

  • Committer: Package Import Robot
  • Author(s): Timo Jyrinki
  • Date: 2013-02-05 12:46:17 UTC
  • Revision ID: package-import@ubuntu.com-20130205124617-c8jouts182j002fx
Tags: upstream-5.0.1+dfsg
ImportĀ upstreamĀ versionĀ 5.0.1+dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/****************************************************************************
 
2
**
 
3
** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
 
4
** Contact: http://www.qt-project.org/legal
 
5
**
 
6
** This file is part of the QtGui module of the Qt Toolkit.
 
7
**
 
8
** $QT_BEGIN_LICENSE:LGPL$
 
9
** Commercial License Usage
 
10
** Licensees holding valid commercial Qt licenses may use this file in
 
11
** accordance with the commercial license agreement provided with the
 
12
** Software or, alternatively, in accordance with the terms contained in
 
13
** a written agreement between you and Digia.  For licensing terms and
 
14
** conditions see http://qt.digia.com/licensing.  For further information
 
15
** use the contact form at http://qt.digia.com/contact-us.
 
16
**
 
17
** GNU Lesser General Public License Usage
 
18
** Alternatively, this file may be used under the terms of the GNU Lesser
 
19
** General Public License version 2.1 as published by the Free Software
 
20
** Foundation and appearing in the file LICENSE.LGPL included in the
 
21
** packaging of this file.  Please review the following information to
 
22
** ensure the GNU Lesser General Public License version 2.1 requirements
 
23
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
 
24
**
 
25
** In addition, as a special exception, Digia gives you certain additional
 
26
** rights.  These rights are described in the Digia Qt LGPL Exception
 
27
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
 
28
**
 
29
** GNU General Public License Usage
 
30
** Alternatively, this file may be used under the terms of the GNU
 
31
** General Public License version 3.0 as published by the Free Software
 
32
** Foundation and appearing in the file LICENSE.GPL included in the
 
33
** packaging of this file.  Please review the following information to
 
34
** ensure the GNU General Public License version 3.0 requirements will be
 
35
** met: http://www.gnu.org/copyleft/gpl.html.
 
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 = QLocale().firstDayOfWeek();
 
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 QStyleOptionViewItem 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
    \inmodule QtWidgets
 
1966
 
 
1967
    \image fusion-calendarwidget.png
 
1968
 
 
1969
    The widget is initialized with the current month and year, but
 
1970
    QCalendarWidget provides several public slots to change the year
 
1971
    and month that is shown.
 
1972
 
 
1973
    By default, today's date is selected, and the user can select a
 
1974
    date using both mouse and keyboard. The currently selected date
 
1975
    can be retrieved using the selectedDate() function. It is
 
1976
    possible to constrain the user selection to a given date range by
 
1977
    setting the minimumDate and maximumDate properties.
 
1978
    Alternatively, both properties can be set in one go using the
 
1979
    setDateRange() convenience slot. Set the \l selectionMode
 
1980
    property to NoSelection to prohibit the user from selecting at
 
1981
    all. Note that a date also can be selected programmatically using
 
1982
    the setSelectedDate() slot.
 
1983
 
 
1984
    The currently displayed month and year can be retrieved using the
 
1985
    monthShown() and yearShown() functions, respectively.
 
1986
 
 
1987
    A newly created calendar widget uses abbreviated day names, and
 
1988
    both Saturdays and Sundays are marked in red. The calendar grid is
 
1989
    not visible. The week numbers are displayed, and the first column
 
1990
    day is the first day of the week for the calendar's locale.
 
1991
 
 
1992
    The notation of the days can be altered to a single letter
 
1993
    abbreviations ("M" for "Monday") by setting the
 
1994
    horizontalHeaderFormat property to
 
1995
    QCalendarWidget::SingleLetterDayNames. Setting the same property
 
1996
    to QCalendarWidget::LongDayNames makes the header display the
 
1997
    complete day names. The week numbers can be removed by setting
 
1998
    the verticalHeaderFormat property to
 
1999
    QCalendarWidget::NoVerticalHeader.  The calendar grid can be
 
2000
    turned on by setting the gridVisible property to true using the
 
2001
    setGridVisible() function:
 
2002
 
 
2003
    \table
 
2004
    \row \li
 
2005
        \image qcalendarwidget-grid.png
 
2006
    \row \li
 
2007
        \snippet code/src_gui_widgets_qcalendarwidget.cpp 0
 
2008
    \endtable
 
2009
 
 
2010
    Finally, the day in the first column can be altered using the
 
2011
    setFirstDayOfWeek() function.
 
2012
 
 
2013
    The QCalendarWidget class also provides three signals,
 
2014
    selectionChanged(), activated() and currentPageChanged() making it
 
2015
    possible to respond to user interaction.
 
2016
 
 
2017
    The rendering of the headers, weekdays or single days can be
 
2018
    largely customized by setting QTextCharFormat's for some special
 
2019
    weekday, a special date or for the rendering of the headers.
 
2020
 
 
2021
    Only a subset of the properties in QTextCharFormat are used by the
 
2022
    calendar widget. Currently, the foreground, background and font
 
2023
    properties are used to determine the rendering of individual cells
 
2024
    in the widget.
 
2025
 
 
2026
    \sa QDate, QDateEdit, QTextCharFormat
 
2027
*/
 
2028
 
 
2029
/*!
 
2030
    \enum QCalendarWidget::SelectionMode
 
2031
 
 
2032
    This enum describes the types of selection offered to the user for
 
2033
    selecting dates in the calendar.
 
2034
 
 
2035
    \value NoSelection      Dates cannot be selected.
 
2036
    \value SingleSelection  Single dates can be selected.
 
2037
 
 
2038
    \sa selectionMode
 
2039
*/
 
2040
 
 
2041
/*!
 
2042
    Constructs a calendar widget with the given \a parent.
 
2043
 
 
2044
    The widget is initialized with the current month and year, and the
 
2045
    currently selected date is today.
 
2046
 
 
2047
    \sa setCurrentPage()
 
2048
*/
 
2049
QCalendarWidget::QCalendarWidget(QWidget *parent)
 
2050
    : QWidget(*new QCalendarWidgetPrivate, parent, 0)
 
2051
{
 
2052
    Q_D(QCalendarWidget);
 
2053
 
 
2054
    setAutoFillBackground(true);
 
2055
    setBackgroundRole(QPalette::Window);
 
2056
 
 
2057
    QVBoxLayout *layoutV = new QVBoxLayout(this);
 
2058
    layoutV->setMargin(0);
 
2059
    d->m_model = new QCalendarModel(this);
 
2060
    QTextCharFormat fmt;
 
2061
    fmt.setForeground(QBrush(Qt::red));
 
2062
    d->m_model->m_dayFormats.insert(Qt::Saturday, fmt);
 
2063
    d->m_model->m_dayFormats.insert(Qt::Sunday, fmt);
 
2064
    d->m_view = new QCalendarView(this);
 
2065
    d->m_view->setObjectName(QLatin1String("qt_calendar_calendarview"));
 
2066
    d->m_view->setModel(d->m_model);
 
2067
    d->m_model->setView(d->m_view);
 
2068
    d->m_view->setSelectionBehavior(QAbstractItemView::SelectItems);
 
2069
    d->m_view->setSelectionMode(QAbstractItemView::SingleSelection);
 
2070
    d->m_view->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
 
2071
    d->m_view->horizontalHeader()->setSectionsClickable(false);
 
2072
    d->m_view->verticalHeader()->setSectionResizeMode(QHeaderView::Stretch);
 
2073
    d->m_view->verticalHeader()->setSectionsClickable(false);
 
2074
    d->m_selection = d->m_view->selectionModel();
 
2075
    d->createNavigationBar(this);
 
2076
    d->m_view->setFrameStyle(QFrame::NoFrame);
 
2077
    d->m_delegate = new QCalendarDelegate(d, this);
 
2078
    d->m_view->setItemDelegate(d->m_delegate);
 
2079
    d->update();
 
2080
    d->updateNavigationBar();
 
2081
    setFocusPolicy(Qt::StrongFocus);
 
2082
    setFocusProxy(d->m_view);
 
2083
    setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
 
2084
 
 
2085
    connect(d->m_view, SIGNAL(showDate(QDate)),
 
2086
            this, SLOT(_q_slotShowDate(QDate)));
 
2087
    connect(d->m_view, SIGNAL(changeDate(QDate,bool)),
 
2088
            this, SLOT(_q_slotChangeDate(QDate,bool)));
 
2089
    connect(d->m_view, SIGNAL(clicked(QDate)),
 
2090
            this, SIGNAL(clicked(QDate)));
 
2091
    connect(d->m_view, SIGNAL(editingFinished()),
 
2092
            this, SLOT(_q_editingFinished()));
 
2093
 
 
2094
    connect(d->prevMonth, SIGNAL(clicked(bool)),
 
2095
            this, SLOT(_q_prevMonthClicked()));
 
2096
    connect(d->nextMonth, SIGNAL(clicked(bool)),
 
2097
            this, SLOT(_q_nextMonthClicked()));
 
2098
    connect(d->yearButton, SIGNAL(clicked(bool)),
 
2099
            this, SLOT(_q_yearClicked()));
 
2100
    connect(d->monthMenu, SIGNAL(triggered(QAction*)),
 
2101
            this, SLOT(_q_monthChanged(QAction*)));
 
2102
    connect(d->yearEdit, SIGNAL(editingFinished()),
 
2103
            this, SLOT(_q_yearEditingFinished()));
 
2104
 
 
2105
    layoutV->setMargin(0);
 
2106
    layoutV->setSpacing(0);
 
2107
    layoutV->addWidget(d->navBarBackground);
 
2108
    layoutV->addWidget(d->m_view);
 
2109
 
 
2110
    d->m_navigator = new QCalendarTextNavigator(this);
 
2111
    setDateEditEnabled(true);
 
2112
}
 
2113
 
 
2114
/*!
 
2115
   Destroys the calendar widget.
 
2116
*/
 
2117
QCalendarWidget::~QCalendarWidget()
 
2118
{
 
2119
}
 
2120
 
 
2121
/*!
 
2122
   \reimp
 
2123
*/
 
2124
QSize QCalendarWidget::sizeHint() const
 
2125
{
 
2126
    return minimumSizeHint();
 
2127
}
 
2128
 
 
2129
/*!
 
2130
   \reimp
 
2131
*/
 
2132
QSize QCalendarWidget::minimumSizeHint() const
 
2133
{
 
2134
    Q_D(const QCalendarWidget);
 
2135
    if (d->cachedSizeHint.isValid())
 
2136
        return d->cachedSizeHint;
 
2137
 
 
2138
    ensurePolished();
 
2139
 
 
2140
    int w = 0;
 
2141
    int h = 0;
 
2142
 
 
2143
    int end = 53;
 
2144
    int rows = 7;
 
2145
    int cols = 8;
 
2146
 
 
2147
    const int marginH = (style()->pixelMetric(QStyle::PM_FocusFrameHMargin) + 1) * 2;
 
2148
 
 
2149
    if (horizontalHeaderFormat() == QCalendarWidget::NoHorizontalHeader) {
 
2150
        rows = 6;
 
2151
    } else {
 
2152
        for (int i = 1; i <= 7; i++) {
 
2153
            QFontMetrics fm(d->m_model->formatForCell(0, i).font());
 
2154
            w = qMax(w, fm.width(d->m_model->dayName(d->m_model->dayOfWeekForColumn(i))) + marginH);
 
2155
            h = qMax(h, fm.height());
 
2156
        }
 
2157
    }
 
2158
 
 
2159
    if (verticalHeaderFormat() == QCalendarWidget::NoVerticalHeader) {
 
2160
        cols = 7;
 
2161
    } else {
 
2162
        for (int i = 1; i <= 6; i++) {
 
2163
            QFontMetrics fm(d->m_model->formatForCell(i, 0).font());
 
2164
            for (int j = 1; j < end; j++)
 
2165
                w = qMax(w, fm.width(QString::number(j)) + marginH);
 
2166
            h = qMax(h, fm.height());
 
2167
        }
 
2168
    }
 
2169
 
 
2170
    QFontMetrics fm(d->m_model->formatForCell(1, 1).font());
 
2171
    for (int i = 1; i <= end; i++) {
 
2172
        w = qMax(w, fm.width(QString::number(i)) + marginH);
 
2173
        h = qMax(h, fm.height());
 
2174
    }
 
2175
 
 
2176
    if (d->m_view->showGrid()) {
 
2177
        // hardcoded in tableview
 
2178
        w += 1;
 
2179
        h += 1;
 
2180
    }
 
2181
 
 
2182
    w += 1; // default column span
 
2183
 
 
2184
    h = qMax(h, d->m_view->verticalHeader()->minimumSectionSize());
 
2185
    w = qMax(w, d->m_view->horizontalHeader()->minimumSectionSize());
 
2186
 
 
2187
    //add the size of the header.
 
2188
    QSize headerSize(0, 0);
 
2189
    if (d->navBarVisible) {
 
2190
        int headerH = d->navBarBackground->sizeHint().height();
 
2191
        int headerW = 0;
 
2192
 
 
2193
        headerW += d->prevMonth->sizeHint().width();
 
2194
        headerW += d->nextMonth->sizeHint().width();
 
2195
 
 
2196
        QFontMetrics fm = d->monthButton->fontMetrics();
 
2197
        int monthW = 0;
 
2198
        for (int i = 1; i < 12; i++) {
 
2199
            QString monthName = locale().standaloneMonthName(i, QLocale::LongFormat);
 
2200
            monthW = qMax(monthW, fm.boundingRect(monthName).width());
 
2201
        }
 
2202
        const int buttonDecoMargin = d->monthButton->sizeHint().width() - fm.boundingRect(d->monthButton->text()).width();
 
2203
        headerW += monthW + buttonDecoMargin;
 
2204
 
 
2205
        fm = d->yearButton->fontMetrics();
 
2206
        headerW += fm.boundingRect(QLatin1String("5555")).width() + buttonDecoMargin;
 
2207
 
 
2208
        headerSize = QSize(headerW, headerH);
 
2209
    }
 
2210
    w *= cols;
 
2211
    w = qMax(headerSize.width(), w);
 
2212
    h = (h * rows) + headerSize.height();
 
2213
    d->cachedSizeHint = QSize(w, h);
 
2214
    return d->cachedSizeHint;
 
2215
}
 
2216
 
 
2217
/*!
 
2218
    Paints the cell specified by the given \a date, using the given \a painter and \a rect.
 
2219
*/
 
2220
 
 
2221
void QCalendarWidget::paintCell(QPainter *painter, const QRect &rect, const QDate &date) const
 
2222
{
 
2223
    Q_D(const QCalendarWidget);
 
2224
    d->m_delegate->paintCell(painter, rect, date);
 
2225
}
 
2226
 
 
2227
/*!
 
2228
    \property QCalendarWidget::selectedDate
 
2229
    \brief the currently selected date.
 
2230
 
 
2231
    The selected date must be within the date range specified by the
 
2232
    minimumDate and maximumDate properties. By default, the selected
 
2233
    date is the current date.
 
2234
 
 
2235
    \sa setDateRange()
 
2236
*/
 
2237
 
 
2238
QDate QCalendarWidget::selectedDate() const
 
2239
{
 
2240
    Q_D(const QCalendarWidget);
 
2241
    return d->m_model->m_date;
 
2242
}
 
2243
 
 
2244
void QCalendarWidget::setSelectedDate(const QDate &date)
 
2245
{
 
2246
    Q_D(QCalendarWidget);
 
2247
    if (d->m_model->m_date == date && date == d->getCurrentDate())
 
2248
        return;
 
2249
 
 
2250
    if (!date.isValid())
 
2251
        return;
 
2252
 
 
2253
    d->m_model->setDate(date);
 
2254
    d->update();
 
2255
    QDate newDate = d->m_model->m_date;
 
2256
    d->showMonth(newDate.year(), newDate.month());
 
2257
    emit selectionChanged();
 
2258
}
 
2259
 
 
2260
/*!
 
2261
    Returns the year of the currently displayed month. Months are
 
2262
    numbered from 1 to 12.
 
2263
 
 
2264
    \sa monthShown(), setCurrentPage()
 
2265
*/
 
2266
 
 
2267
int QCalendarWidget::yearShown() const
 
2268
{
 
2269
    Q_D(const QCalendarWidget);
 
2270
    return d->m_model->m_shownYear;
 
2271
}
 
2272
 
 
2273
/*!
 
2274
    Returns the currently displayed month. Months are numbered from 1 to
 
2275
    12.
 
2276
 
 
2277
    \sa yearShown(), setCurrentPage()
 
2278
*/
 
2279
 
 
2280
int QCalendarWidget::monthShown() const
 
2281
{
 
2282
    Q_D(const QCalendarWidget);
 
2283
    return d->m_model->m_shownMonth;
 
2284
}
 
2285
 
 
2286
/*!
 
2287
    Displays the given \a month of the given \a year without changing
 
2288
    the selected date. Use the setSelectedDate() function to alter the
 
2289
    selected date.
 
2290
 
 
2291
    The currently displayed month and year can be retrieved using the
 
2292
    monthShown() and yearShown() functions respectively.
 
2293
 
 
2294
    \sa yearShown(), monthShown(), showPreviousMonth(), showNextMonth(),
 
2295
    showPreviousYear(), showNextYear()
 
2296
*/
 
2297
 
 
2298
void QCalendarWidget::setCurrentPage(int year, int month)
 
2299
{
 
2300
    Q_D(QCalendarWidget);
 
2301
    QDate currentDate = d->getCurrentDate();
 
2302
    int day = currentDate.day();
 
2303
    int daysInMonths = QDate(year, month, 1).daysInMonth();
 
2304
    if (day > daysInMonths)
 
2305
        day = daysInMonths;
 
2306
 
 
2307
    d->showMonth(year, month);
 
2308
 
 
2309
    QDate newDate(year, month, day);
 
2310
    int row = -1, col = -1;
 
2311
    d->m_model->cellForDate(newDate, &row, &col);
 
2312
    if (row != -1 && col != -1) {
 
2313
        d->m_view->selectionModel()->setCurrentIndex(d->m_model->index(row, col),
 
2314
                                                  QItemSelectionModel::NoUpdate);
 
2315
    }
 
2316
}
 
2317
 
 
2318
/*!
 
2319
    Shows the next month relative to the currently displayed
 
2320
    month. Note that the selected date is not changed.
 
2321
 
 
2322
    \sa showPreviousMonth(), setCurrentPage(), setSelectedDate()
 
2323
*/
 
2324
 
 
2325
void QCalendarWidget::showNextMonth()
 
2326
{
 
2327
    int year = yearShown();
 
2328
    int month = monthShown();
 
2329
    if (month == 12) {
 
2330
        ++year;
 
2331
        month = 1;
 
2332
    } else {
 
2333
        ++month;
 
2334
    }
 
2335
    setCurrentPage(year, month);
 
2336
}
 
2337
 
 
2338
/*!
 
2339
    Shows the previous month relative to the currently displayed
 
2340
    month. Note that the selected date is not changed.
 
2341
 
 
2342
    \sa showNextMonth(), setCurrentPage(), setSelectedDate()
 
2343
*/
 
2344
 
 
2345
void QCalendarWidget::showPreviousMonth()
 
2346
{
 
2347
    int year = yearShown();
 
2348
    int month = monthShown();
 
2349
    if (month == 1) {
 
2350
        --year;
 
2351
        month = 12;
 
2352
    } else {
 
2353
        --month;
 
2354
    }
 
2355
    setCurrentPage(year, month);
 
2356
}
 
2357
 
 
2358
/*!
 
2359
    Shows the currently displayed month in the \e next year relative
 
2360
    to the currently displayed year. Note that the selected date is
 
2361
    not changed.
 
2362
 
 
2363
    \sa showPreviousYear(), setCurrentPage(), setSelectedDate()
 
2364
*/
 
2365
 
 
2366
void QCalendarWidget::showNextYear()
 
2367
{
 
2368
    int year = yearShown();
 
2369
    int month = monthShown();
 
2370
    ++year;
 
2371
    setCurrentPage(year, month);
 
2372
}
 
2373
 
 
2374
/*!
 
2375
    Shows the currently displayed month in the \e previous year
 
2376
    relative to the currently displayed year. Note that the selected
 
2377
    date is not changed.
 
2378
 
 
2379
    \sa showNextYear(), setCurrentPage(), setSelectedDate()
 
2380
*/
 
2381
 
 
2382
void QCalendarWidget::showPreviousYear()
 
2383
{
 
2384
    int year = yearShown();
 
2385
    int month = monthShown();
 
2386
    --year;
 
2387
    setCurrentPage(year, month);
 
2388
}
 
2389
 
 
2390
/*!
 
2391
    Shows the month of the selected date.
 
2392
 
 
2393
    \sa selectedDate(), setCurrentPage()
 
2394
*/
 
2395
void QCalendarWidget::showSelectedDate()
 
2396
{
 
2397
    QDate currentDate = selectedDate();
 
2398
    setCurrentPage(currentDate.year(), currentDate.month());
 
2399
}
 
2400
 
 
2401
/*!
 
2402
    Shows the month of the today's date.
 
2403
 
 
2404
    \sa selectedDate(), setCurrentPage()
 
2405
*/
 
2406
void QCalendarWidget::showToday()
 
2407
{
 
2408
    QDate currentDate = QDate::currentDate();
 
2409
    setCurrentPage(currentDate.year(), currentDate.month());
 
2410
}
 
2411
 
 
2412
/*!
 
2413
    \property QCalendarWidget::minimumDate
 
2414
    \brief the minimum date of the currently specified date range.
 
2415
 
 
2416
    The user will not be able to select a date that is before the
 
2417
    currently set minimum date.
 
2418
 
 
2419
    \table
 
2420
    \row
 
2421
    \li \image qcalendarwidget-minimum.png
 
2422
    \row
 
2423
    \li
 
2424
    \snippet code/src_gui_widgets_qcalendarwidget.cpp 1
 
2425
    \endtable
 
2426
 
 
2427
    By default, the minimum date is the earliest date that the QDate
 
2428
    class can handle.
 
2429
 
 
2430
    When setting a minimum date, the maximumDate and selectedDate
 
2431
    properties are adjusted if the selection range becomes invalid. If
 
2432
    the provided date is not a valid QDate object, the
 
2433
    setMinimumDate() function does nothing.
 
2434
 
 
2435
    \sa setDateRange()
 
2436
*/
 
2437
 
 
2438
QDate QCalendarWidget::minimumDate() const
 
2439
{
 
2440
    Q_D(const QCalendarWidget);
 
2441
    return d->m_model->m_minimumDate;
 
2442
}
 
2443
 
 
2444
void QCalendarWidget::setMinimumDate(const QDate &date)
 
2445
{
 
2446
    Q_D(QCalendarWidget);
 
2447
    if (!date.isValid() || d->m_model->m_minimumDate == date)
 
2448
        return;
 
2449
 
 
2450
    QDate oldDate = d->m_model->m_date;
 
2451
    d->m_model->setMinimumDate(date);
 
2452
    d->yearEdit->setMinimum(d->m_model->m_minimumDate.year());
 
2453
    d->updateMonthMenu();
 
2454
    QDate newDate = d->m_model->m_date;
 
2455
    if (oldDate != newDate) {
 
2456
        d->update();
 
2457
        d->showMonth(newDate.year(), newDate.month());
 
2458
        d->m_navigator->setDate(newDate);
 
2459
        emit selectionChanged();
 
2460
    }
 
2461
}
 
2462
 
 
2463
/*!
 
2464
    \property QCalendarWidget::maximumDate
 
2465
    \brief the maximum date of the currently specified date range.
 
2466
 
 
2467
    The user will not be able to select a date which is after the
 
2468
    currently set maximum date.
 
2469
 
 
2470
    \table
 
2471
    \row
 
2472
    \li \image qcalendarwidget-maximum.png
 
2473
    \row
 
2474
    \li
 
2475
    \snippet code/src_gui_widgets_qcalendarwidget.cpp 2
 
2476
    \endtable
 
2477
 
 
2478
    By default, the maximum date is the last day the QDate class can
 
2479
    handle.
 
2480
 
 
2481
    When setting a maximum date, the minimumDate and selectedDate
 
2482
    properties are adjusted if the selection range becomes invalid. If
 
2483
    the provided date is not a valid QDate object, the
 
2484
    setMaximumDate() function does nothing.
 
2485
 
 
2486
    \sa setDateRange()
 
2487
*/
 
2488
 
 
2489
QDate QCalendarWidget::maximumDate() const
 
2490
{
 
2491
    Q_D(const QCalendarWidget);
 
2492
    return d->m_model->m_maximumDate;
 
2493
}
 
2494
 
 
2495
void QCalendarWidget::setMaximumDate(const QDate &date)
 
2496
{
 
2497
    Q_D(QCalendarWidget);
 
2498
    if (!date.isValid() || d->m_model->m_maximumDate == date)
 
2499
        return;
 
2500
 
 
2501
    QDate oldDate = d->m_model->m_date;
 
2502
    d->m_model->setMaximumDate(date);
 
2503
    d->yearEdit->setMaximum(d->m_model->m_maximumDate.year());
 
2504
    d->updateMonthMenu();
 
2505
    QDate newDate = d->m_model->m_date;
 
2506
    if (oldDate != newDate) {
 
2507
        d->update();
 
2508
        d->showMonth(newDate.year(), newDate.month());
 
2509
        d->m_navigator->setDate(newDate);
 
2510
        emit selectionChanged();
 
2511
    }
 
2512
}
 
2513
 
 
2514
/*!
 
2515
    Defines a date range by setting the minimumDate and maximumDate
 
2516
    properties.
 
2517
 
 
2518
    The date range restricts the user selection, i.e. the user can
 
2519
    only select dates within the specified date range. Note that
 
2520
 
 
2521
    \snippet code/src_gui_widgets_qcalendarwidget.cpp 3
 
2522
 
 
2523
    is analogous to
 
2524
 
 
2525
    \snippet code/src_gui_widgets_qcalendarwidget.cpp 4
 
2526
 
 
2527
    If either the \a min or \a max parameters are not valid QDate
 
2528
    objects, this function does nothing.
 
2529
 
 
2530
    \sa setMinimumDate(), setMaximumDate()
 
2531
*/
 
2532
 
 
2533
void QCalendarWidget::setDateRange(const QDate &min, const QDate &max)
 
2534
{
 
2535
    Q_D(QCalendarWidget);
 
2536
    if (d->m_model->m_minimumDate == min && d->m_model->m_maximumDate == max)
 
2537
        return;
 
2538
    if (!min.isValid() || !max.isValid())
 
2539
        return;
 
2540
 
 
2541
    QDate oldDate = d->m_model->m_date;
 
2542
    d->m_model->setRange(min, max);
 
2543
    d->yearEdit->setMinimum(d->m_model->m_minimumDate.year());
 
2544
    d->yearEdit->setMaximum(d->m_model->m_maximumDate.year());
 
2545
    d->updateMonthMenu();
 
2546
    QDate newDate = d->m_model->m_date;
 
2547
    if (oldDate != newDate) {
 
2548
        d->update();
 
2549
        d->showMonth(newDate.year(), newDate.month());
 
2550
        d->m_navigator->setDate(newDate);
 
2551
        emit selectionChanged();
 
2552
    }
 
2553
}
 
2554
 
 
2555
 
 
2556
/*! \enum QCalendarWidget::HorizontalHeaderFormat
 
2557
 
 
2558
    This enum type defines the various formats the horizontal header can display.
 
2559
 
 
2560
    \value SingleLetterDayNames The header displays a single letter abbreviation for day names (e.g. M for Monday).
 
2561
    \value ShortDayNames The header displays a short abbreviation for day names (e.g. Mon for Monday).
 
2562
    \value LongDayNames The header displays complete day names (e.g. Monday).
 
2563
    \value NoHorizontalHeader The header is hidden.
 
2564
 
 
2565
    \sa horizontalHeaderFormat(), VerticalHeaderFormat
 
2566
*/
 
2567
 
 
2568
/*!
 
2569
    \property QCalendarWidget::horizontalHeaderFormat
 
2570
    \brief the format of the horizontal header.
 
2571
 
 
2572
    The default value is QCalendarWidget::ShortDayNames.
 
2573
*/
 
2574
 
 
2575
void QCalendarWidget::setHorizontalHeaderFormat(QCalendarWidget::HorizontalHeaderFormat format)
 
2576
{
 
2577
    Q_D(QCalendarWidget);
 
2578
    if (d->m_model->m_horizontalHeaderFormat == format)
 
2579
        return;
 
2580
 
 
2581
    d->m_model->setHorizontalHeaderFormat(format);
 
2582
    d->cachedSizeHint = QSize();
 
2583
    d->m_view->viewport()->update();
 
2584
    d->m_view->updateGeometry();
 
2585
}
 
2586
 
 
2587
QCalendarWidget::HorizontalHeaderFormat QCalendarWidget::horizontalHeaderFormat() const
 
2588
{
 
2589
    Q_D(const QCalendarWidget);
 
2590
    return d->m_model->m_horizontalHeaderFormat;
 
2591
}
 
2592
 
 
2593
 
 
2594
/*! 
 
2595
    \enum QCalendarWidget::VerticalHeaderFormat
 
2596
 
 
2597
    This enum type defines the various formats the vertical header can display.
 
2598
 
 
2599
    \value ISOWeekNumbers The header displays ISO week numbers as described by \l QDate::weekNumber().
 
2600
    \value NoVerticalHeader The header is hidden.
 
2601
 
 
2602
    \sa verticalHeaderFormat(), HorizontalHeaderFormat
 
2603
*/
 
2604
 
 
2605
/*!
 
2606
    \property QCalendarWidget::verticalHeaderFormat
 
2607
    \brief the format of the vertical header.
 
2608
 
 
2609
    The default value is QCalendarWidget::ISOWeekNumber.
 
2610
*/
 
2611
 
 
2612
QCalendarWidget::VerticalHeaderFormat QCalendarWidget::verticalHeaderFormat() const
 
2613
{
 
2614
    Q_D(const QCalendarWidget);
 
2615
    bool shown = d->m_model->weekNumbersShown();
 
2616
    if (shown)
 
2617
        return QCalendarWidget::ISOWeekNumbers;
 
2618
    return QCalendarWidget::NoVerticalHeader;
 
2619
}
 
2620
 
 
2621
void QCalendarWidget::setVerticalHeaderFormat(QCalendarWidget::VerticalHeaderFormat format)
 
2622
{
 
2623
    Q_D(QCalendarWidget);
 
2624
    bool show = false;
 
2625
    if (format == QCalendarWidget::ISOWeekNumbers)
 
2626
        show = true;
 
2627
    if (d->m_model->weekNumbersShown() == show)
 
2628
        return;
 
2629
    d->m_model->setWeekNumbersShown(show);
 
2630
    d->cachedSizeHint = QSize();
 
2631
    d->m_view->viewport()->update();
 
2632
    d->m_view->updateGeometry();
 
2633
}
 
2634
 
 
2635
/*!
 
2636
    \property QCalendarWidget::gridVisible
 
2637
    \brief whether the table grid is displayed.
 
2638
 
 
2639
    \table
 
2640
    \row
 
2641
        \li \inlineimage qcalendarwidget-grid.png
 
2642
    \row
 
2643
        \li
 
2644
        \snippet code/src_gui_widgets_qcalendarwidget.cpp 5
 
2645
    \endtable
 
2646
 
 
2647
    The default value is false.
 
2648
*/
 
2649
 
 
2650
bool QCalendarWidget::isGridVisible() const
 
2651
{
 
2652
    Q_D(const QCalendarWidget);
 
2653
    return d->m_view->showGrid();
 
2654
}
 
2655
 
 
2656
void QCalendarWidget::setGridVisible(bool show)
 
2657
{
 
2658
    Q_D(QCalendarWidget);
 
2659
    d->m_view->setShowGrid(show);
 
2660
    d->cachedSizeHint = QSize();
 
2661
    d->m_view->viewport()->update();
 
2662
    d->m_view->updateGeometry();
 
2663
}
 
2664
 
 
2665
/*!
 
2666
    \property QCalendarWidget::selectionMode
 
2667
    \brief the type of selection the user can make in the calendar
 
2668
 
 
2669
    When this property is set to SingleSelection, the user can select a date
 
2670
    within the minimum and maximum allowed dates, using either the mouse or
 
2671
    the keyboard.
 
2672
 
 
2673
    When the property is set to NoSelection, the user will be unable to select
 
2674
    dates, but they can still be selected programmatically. Note that the date
 
2675
    that is selected when the property is set to NoSelection will still be
 
2676
    the selected date of the calendar.
 
2677
 
 
2678
    The default value is SingleSelection.
 
2679
*/
 
2680
 
 
2681
QCalendarWidget::SelectionMode QCalendarWidget::selectionMode() const
 
2682
{
 
2683
    Q_D(const QCalendarWidget);
 
2684
    return d->m_view->readOnly ? QCalendarWidget::NoSelection : QCalendarWidget::SingleSelection;
 
2685
}
 
2686
 
 
2687
void QCalendarWidget::setSelectionMode(SelectionMode mode)
 
2688
{
 
2689
    Q_D(QCalendarWidget);
 
2690
    d->m_view->readOnly = (mode == QCalendarWidget::NoSelection);
 
2691
    d->setNavigatorEnabled(isDateEditEnabled() && (selectionMode() != QCalendarWidget::NoSelection));
 
2692
    d->update();
 
2693
}
 
2694
 
 
2695
/*!
 
2696
    \property QCalendarWidget::firstDayOfWeek
 
2697
    \brief a value identifying the day displayed in the first column.
 
2698
 
 
2699
    By default, the day displayed in the first column
 
2700
    is the first day of the week for the calendar's locale.
 
2701
*/
 
2702
 
 
2703
void QCalendarWidget::setFirstDayOfWeek(Qt::DayOfWeek dayOfWeek)
 
2704
{
 
2705
    Q_D(QCalendarWidget);
 
2706
    if ((Qt::DayOfWeek)d->m_model->firstColumnDay() == dayOfWeek)
 
2707
        return;
 
2708
 
 
2709
    d->m_model->setFirstColumnDay(dayOfWeek);
 
2710
    d->update();
 
2711
}
 
2712
 
 
2713
Qt::DayOfWeek QCalendarWidget::firstDayOfWeek() const
 
2714
{
 
2715
    Q_D(const QCalendarWidget);
 
2716
    return (Qt::DayOfWeek)d->m_model->firstColumnDay();
 
2717
}
 
2718
 
 
2719
/*!
 
2720
    Returns the text char format for rendering the header.
 
2721
*/
 
2722
QTextCharFormat QCalendarWidget::headerTextFormat() const
 
2723
{
 
2724
    Q_D(const QCalendarWidget);
 
2725
    return d->m_model->m_headerFormat;
 
2726
}
 
2727
 
 
2728
/*!
 
2729
    Sets the text char format for rendering the header to \a format.
 
2730
    If you also set a weekday text format, this format's foreground and
 
2731
    background color will take precedence over the header's format.
 
2732
    The other formatting information will still be decided by
 
2733
    the header's format.
 
2734
*/
 
2735
void QCalendarWidget::setHeaderTextFormat(const QTextCharFormat &format)
 
2736
{
 
2737
    Q_D(QCalendarWidget);
 
2738
    d->m_model->m_headerFormat = format;
 
2739
    d->cachedSizeHint = QSize();
 
2740
    d->m_view->viewport()->update();
 
2741
    d->m_view->updateGeometry();
 
2742
}
 
2743
 
 
2744
/*!
 
2745
    Returns the text char format for rendering of day in the week \a dayOfWeek.
 
2746
 
 
2747
    \sa headerTextFormat()
 
2748
*/
 
2749
QTextCharFormat QCalendarWidget::weekdayTextFormat(Qt::DayOfWeek dayOfWeek) const
 
2750
{
 
2751
    Q_D(const QCalendarWidget);
 
2752
    return d->m_model->m_dayFormats.value(dayOfWeek);
 
2753
}
 
2754
 
 
2755
/*!
 
2756
    Sets the text char format for rendering of day in the week \a dayOfWeek to \a format.
 
2757
    The format will take precedence over the header format in case of foreground
 
2758
    and background color. Other text formatting information is taken from the headers format.
 
2759
 
 
2760
    \sa setHeaderTextFormat()
 
2761
*/
 
2762
void QCalendarWidget::setWeekdayTextFormat(Qt::DayOfWeek dayOfWeek, const QTextCharFormat &format)
 
2763
{
 
2764
    Q_D(QCalendarWidget);
 
2765
    d->m_model->m_dayFormats[dayOfWeek] = format;
 
2766
    d->cachedSizeHint = QSize();
 
2767
    d->m_view->viewport()->update();
 
2768
    d->m_view->updateGeometry();
 
2769
}
 
2770
 
 
2771
/*!
 
2772
    Returns a QMap from QDate to QTextCharFormat showing all dates
 
2773
    that use a special format that alters their rendering.
 
2774
*/
 
2775
QMap<QDate, QTextCharFormat> QCalendarWidget::dateTextFormat() const
 
2776
{
 
2777
    Q_D(const QCalendarWidget);
 
2778
    return d->m_model->m_dateFormats;
 
2779
}
 
2780
 
 
2781
/*!
 
2782
    Returns a QTextCharFormat for \a date. The char format can be be
 
2783
    empty if the date is not renderd specially.
 
2784
*/
 
2785
QTextCharFormat QCalendarWidget::dateTextFormat(const QDate &date) const
 
2786
{
 
2787
    Q_D(const QCalendarWidget);
 
2788
    return d->m_model->m_dateFormats.value(date);
 
2789
}
 
2790
 
 
2791
/*!
 
2792
    Sets the format used to render the given \a date to that specified by \a format.
 
2793
 
 
2794
    If \a date is null, all date formats are cleared.
 
2795
*/
 
2796
void QCalendarWidget::setDateTextFormat(const QDate &date, const QTextCharFormat &format)
 
2797
{
 
2798
    Q_D(QCalendarWidget);
 
2799
    if (date.isNull())
 
2800
        d->m_model->m_dateFormats.clear();
 
2801
    else
 
2802
        d->m_model->m_dateFormats[date] = format;
 
2803
    d->m_view->viewport()->update();
 
2804
    d->m_view->updateGeometry();
 
2805
}
 
2806
 
 
2807
/*!
 
2808
    \property QCalendarWidget::dateEditEnabled
 
2809
    \brief whether the date edit popup is enabled
 
2810
    \since 4.3
 
2811
 
 
2812
    If this property is enabled, pressing a non-modifier key will cause a
 
2813
    date edit to popup if the calendar widget has focus, allowing the user
 
2814
    to specify a date in the form specified by the current locale.
 
2815
 
 
2816
    By default, this property is enabled.
 
2817
 
 
2818
    The date edit is simpler in appearance than QDateEdit, but allows the
 
2819
    user to navigate between fields using the left and right cursor keys,
 
2820
    increment and decrement individual fields using the up and down cursor
 
2821
    keys, and enter values directly using the number keys.
 
2822
 
 
2823
    \sa QCalendarWidget::dateEditAcceptDelay
 
2824
*/
 
2825
bool QCalendarWidget::isDateEditEnabled() const
 
2826
{
 
2827
    Q_D(const QCalendarWidget);
 
2828
    return d->m_dateEditEnabled;
 
2829
}
 
2830
 
 
2831
void QCalendarWidget::setDateEditEnabled(bool enable)
 
2832
{
 
2833
    Q_D(QCalendarWidget);
 
2834
    if (isDateEditEnabled() == enable)
 
2835
        return;
 
2836
 
 
2837
    d->m_dateEditEnabled = enable;
 
2838
 
 
2839
    d->setNavigatorEnabled(enable && (selectionMode() != QCalendarWidget::NoSelection));
 
2840
}
 
2841
 
 
2842
/*!
 
2843
    \property QCalendarWidget::dateEditAcceptDelay
 
2844
    \brief the time an inactive date edit is shown before its contents are accepted
 
2845
    \since 4.3
 
2846
 
 
2847
    If the calendar widget's \l{dateEditEnabled}{date edit is enabled}, this
 
2848
    property specifies the amount of time (in millseconds) that the date edit
 
2849
    remains open after the most recent user input. Once this time has elapsed,
 
2850
    the date specified in the date edit is accepted and the popup is closed.
 
2851
 
 
2852
    By default, the delay is defined to be 1500 milliseconds (1.5 seconds).
 
2853
*/
 
2854
int QCalendarWidget::dateEditAcceptDelay() const
 
2855
{
 
2856
    Q_D(const QCalendarWidget);
 
2857
    return d->m_navigator->dateEditAcceptDelay();
 
2858
}
 
2859
 
 
2860
void QCalendarWidget::setDateEditAcceptDelay(int delay)
 
2861
{
 
2862
    Q_D(QCalendarWidget);
 
2863
    d->m_navigator->setDateEditAcceptDelay(delay);
 
2864
}
 
2865
 
 
2866
/*!
 
2867
    \since 4.4
 
2868
 
 
2869
    Updates the cell specified by the given \a date unless updates
 
2870
    are disabled or the cell is hidden.
 
2871
 
 
2872
    \sa updateCells(), yearShown(), monthShown()
 
2873
*/
 
2874
void QCalendarWidget::updateCell(const QDate &date)
 
2875
{
 
2876
    if (!date.isValid()) {
 
2877
        qWarning("QCalendarWidget::updateCell: Invalid date");
 
2878
        return;
 
2879
    }
 
2880
 
 
2881
    if (!isVisible())
 
2882
        return;
 
2883
 
 
2884
    Q_D(QCalendarWidget);
 
2885
    int row, column;
 
2886
    d->m_model->cellForDate(date, &row, &column);
 
2887
    if (row == -1 || column == -1)
 
2888
        return;
 
2889
 
 
2890
    QModelIndex modelIndex = d->m_model->index(row, column);
 
2891
    if (!modelIndex.isValid())
 
2892
        return;
 
2893
 
 
2894
    d->m_view->viewport()->update(d->m_view->visualRect(modelIndex));
 
2895
}
 
2896
 
 
2897
/*!
 
2898
    \since 4.4
 
2899
 
 
2900
    Updates all visible cells unless updates are disabled.
 
2901
 
 
2902
    \sa updateCell()
 
2903
*/
 
2904
void QCalendarWidget::updateCells()
 
2905
{
 
2906
    Q_D(QCalendarWidget);
 
2907
    if (isVisible())
 
2908
        d->m_view->viewport()->update();
 
2909
}
 
2910
 
 
2911
/*!
 
2912
    \fn void QCalendarWidget::selectionChanged()
 
2913
 
 
2914
    This signal is emitted when the currently selected date is
 
2915
    changed.
 
2916
 
 
2917
    The currently selected date can be changed by the user using the
 
2918
    mouse or keyboard, or by the programmer using setSelectedDate().
 
2919
 
 
2920
    \sa selectedDate()
 
2921
*/
 
2922
 
 
2923
/*!
 
2924
    \fn void QCalendarWidget::currentPageChanged(int year, int month)
 
2925
 
 
2926
    This signal is emitted when the currently shown month is changed.
 
2927
    The new \a year and \a month are passed as parameters.
 
2928
 
 
2929
    \sa setCurrentPage()
 
2930
*/
 
2931
 
 
2932
/*!
 
2933
    \fn void QCalendarWidget::activated(const QDate &date)
 
2934
 
 
2935
    This signal is emitted whenever the user presses the Return or
 
2936
    Enter key or double-clicks a \a date in the calendar
 
2937
    widget.
 
2938
*/
 
2939
 
 
2940
/*!
 
2941
    \fn void QCalendarWidget::clicked(const QDate &date)
 
2942
 
 
2943
    This signal is emitted when a mouse button is clicked. The date
 
2944
    the mouse was clicked on is specified by \a date. The signal is
 
2945
    only emitted when clicked on a valid date, e.g., dates are not
 
2946
    outside the minimumDate() and maximumDate(). If the selection mode
 
2947
    is NoSelection, this signal will not be emitted.
 
2948
 
 
2949
*/
 
2950
 
 
2951
/*!
 
2952
    \property QCalendarWidget::navigationBarVisible
 
2953
    \brief whether the navigation bar is shown or not
 
2954
 
 
2955
    \since 4.3
 
2956
 
 
2957
    When this property is true (the default), the next month,
 
2958
    previous month, month selection, year selection controls are
 
2959
    shown on top.
 
2960
 
 
2961
    When the property is set to false, these controls are hidden.
 
2962
*/
 
2963
 
 
2964
bool QCalendarWidget::isNavigationBarVisible() const
 
2965
{
 
2966
    Q_D(const QCalendarWidget);
 
2967
    return d->navBarVisible;
 
2968
}
 
2969
 
 
2970
 
 
2971
void QCalendarWidget::setNavigationBarVisible(bool visible)
 
2972
{
 
2973
    Q_D(QCalendarWidget);
 
2974
    d->navBarVisible = visible;
 
2975
    d->cachedSizeHint = QSize();
 
2976
    d->navBarBackground->setVisible(visible);
 
2977
    updateGeometry();
 
2978
}
 
2979
 
 
2980
/*!
 
2981
  \reimp
 
2982
*/
 
2983
bool QCalendarWidget::event(QEvent *event)
 
2984
{
 
2985
    Q_D(QCalendarWidget);
 
2986
    switch (event->type()) {
 
2987
        case QEvent::LayoutDirectionChange:
 
2988
            d->updateButtonIcons();
 
2989
        case QEvent::LocaleChange:
 
2990
            d->m_model->setFirstColumnDay(locale().firstDayOfWeek());
 
2991
            d->cachedSizeHint = QSize();
 
2992
            d->updateMonthMenuNames();
 
2993
            d->updateNavigationBar();
 
2994
            d->m_view->updateGeometry();
 
2995
            break;
 
2996
        case QEvent::FontChange:
 
2997
        case QEvent::ApplicationFontChange:
 
2998
            d->cachedSizeHint = QSize();
 
2999
            d->m_view->updateGeometry();
 
3000
            break;
 
3001
        case QEvent::StyleChange:
 
3002
            d->cachedSizeHint = QSize();
 
3003
            d->m_view->updateGeometry();
 
3004
        default:
 
3005
            break;
 
3006
    }
 
3007
    return QWidget::event(event);
 
3008
}
 
3009
 
 
3010
/*!
 
3011
  \reimp
 
3012
*/
 
3013
bool QCalendarWidget::eventFilter(QObject *watched, QEvent *event)
 
3014
{
 
3015
    Q_D(QCalendarWidget);
 
3016
    if (event->type() == QEvent::MouseButtonPress && d->yearEdit->hasFocus()) {
 
3017
        QWidget *tlw = window();
 
3018
        QWidget *widget = static_cast<QWidget*>(watched);
 
3019
        //as we have a event filter on the whole application we first make sure that the top level widget
 
3020
        //of both this and the watched widget are the same to decide if we should finish the year edition.
 
3021
        if (widget->window() == tlw) {
 
3022
            QPoint mousePos = widget->mapTo(tlw, static_cast<QMouseEvent *>(event)->pos());
 
3023
            QRect geom = QRect(d->yearEdit->mapTo(tlw, QPoint(0, 0)), d->yearEdit->size());
 
3024
            if (!geom.contains(mousePos)) {
 
3025
                event->accept();
 
3026
                d->_q_yearEditingFinished();
 
3027
                setFocus();
 
3028
                return true;
 
3029
            }
 
3030
        }
 
3031
    }
 
3032
    return QWidget::eventFilter(watched, event);
 
3033
}
 
3034
 
 
3035
/*!
 
3036
  \reimp
 
3037
*/
 
3038
void QCalendarWidget::mousePressEvent(QMouseEvent *event)
 
3039
{
 
3040
    setAttribute(Qt::WA_NoMouseReplay);
 
3041
    QWidget::mousePressEvent(event);
 
3042
    setFocus();
 
3043
}
 
3044
 
 
3045
/*!
 
3046
  \reimp
 
3047
*/
 
3048
void QCalendarWidget::resizeEvent(QResizeEvent * event)
 
3049
{
 
3050
    Q_D(QCalendarWidget);
 
3051
 
 
3052
    // XXX Should really use a QWidgetStack for yearEdit and yearButton,
 
3053
    // XXX here we hide the year edit when the layout is likely to break
 
3054
    // XXX the manual positioning of the yearEdit over the yearButton.
 
3055
    if(d->yearEdit->isVisible() && event->size().width() != event->oldSize().width())
 
3056
        d->_q_yearEditingFinished();
 
3057
 
 
3058
    QWidget::resizeEvent(event);
 
3059
}
 
3060
 
 
3061
/*!
 
3062
  \reimp
 
3063
*/
 
3064
void QCalendarWidget::keyPressEvent(QKeyEvent * event)
 
3065
{
 
3066
    Q_D(QCalendarWidget);
 
3067
    if(d->yearEdit->isVisible()&& event->key() == Qt::Key_Escape)
 
3068
    {
 
3069
        d->yearEdit->setValue(yearShown());
 
3070
        d->_q_yearEditingFinished();
 
3071
        return;
 
3072
    }
 
3073
    QWidget::keyPressEvent(event);
 
3074
}
 
3075
 
 
3076
QT_END_NAMESPACE
 
3077
 
 
3078
#include "qcalendarwidget.moc"
 
3079
#include "moc_qcalendarwidget.cpp"
 
3080
 
 
3081
#endif //QT_NO_CALENDARWIDGET