1
/****************************************************************************
3
** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
4
** Contact: http://www.qt-project.org/legal
6
** This file is part of the QtGui module of the Qt Toolkit.
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.
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.
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.
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.
40
****************************************************************************/
42
#include "qcalendarwidget.h"
44
#ifndef QT_NO_CALENDARWIDGET
46
#include <qabstractitemmodel.h>
47
#include <qitemdelegate.h>
48
#include <qdatetime.h>
49
#include <qtableview.h>
52
#include <qtextformat.h>
53
#include <qheaderview.h>
54
#include <private/qwidget_p.h>
55
#include <qpushbutton.h>
56
#include <qtoolbutton.h>
60
#include <qapplication.h>
61
#include <qbasictimer.h>
62
#include <qstylepainter.h>
63
#include <private/qcalendartextnavigator_p.h>
75
class QCalendarDateSectionValidator
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;
96
QString highlightString(const QString &str, int pos) const;
100
QString QCalendarDateSectionValidator::highlightString(const QString &str, int pos) const
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>");
109
class QCalendarDayValidator : public QCalendarDateSectionValidator
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;
125
QCalendarDayValidator::QCalendarDayValidator()
126
: QCalendarDateSectionValidator(), m_pos(0), m_day(1), m_oldDay(1)
130
QCalendarDateSectionValidator::Section QCalendarDayValidator::handleKey(int key)
132
if (key == Qt::Key_Right || key == Qt::Key_Left) {
134
return QCalendarDateSectionValidator::ThisSection;
135
} else if (key == Qt::Key_Up) {
140
return QCalendarDateSectionValidator::ThisSection;
141
} else if (key == Qt::Key_Down) {
146
return QCalendarDateSectionValidator::ThisSection;
147
} else if (key == Qt::Key_Back || key == Qt::Key_Backspace) {
156
//m_day = m_oldDay / 10 * 10 + m_day / 10;
159
return QCalendarDateSectionValidator::PrevSection;
160
return QCalendarDateSectionValidator::ThisSection;
162
if (key < Qt::Key_0 || key > Qt::Key_9)
163
return QCalendarDateSectionValidator::ThisSection;
164
int pressedKey = key - Qt::Key_0;
168
m_day = m_day % 10 * 10 + pressedKey;
174
return QCalendarDateSectionValidator::NextSection;
176
return QCalendarDateSectionValidator::ThisSection;
179
QDate QCalendarDayValidator::applyToDate(const QDate &date) const
186
if (day > date.daysInMonth())
187
day = date.daysInMonth();
188
return QDate(date.year(), date.month(), day);
191
void QCalendarDayValidator::setDate(const QDate &date)
193
m_day = m_oldDay = date.day();
197
QString QCalendarDayValidator::text() const
201
str += QLatin1Char('0');
202
str += QString::number(m_day);
203
return highlightString(str, m_pos);
206
QString QCalendarDayValidator::text(const QDate &date, int repeat) const
209
return QString::number(date.day());
210
} else if (repeat == 2) {
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);
223
//////////////////////////////////
225
class QCalendarMonthValidator : public QCalendarDateSectionValidator
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;
241
QCalendarMonthValidator::QCalendarMonthValidator()
242
: QCalendarDateSectionValidator(), m_pos(0), m_month(1), m_oldMonth(1)
246
QCalendarDateSectionValidator::Section QCalendarMonthValidator::handleKey(int key)
248
if (key == Qt::Key_Right || key == Qt::Key_Left) {
250
return QCalendarDateSectionValidator::ThisSection;
251
} else if (key == Qt::Key_Up) {
256
return QCalendarDateSectionValidator::ThisSection;
257
} else if (key == Qt::Key_Down) {
262
return QCalendarDateSectionValidator::ThisSection;
263
} else if (key == Qt::Key_Back || key == Qt::Key_Backspace) {
269
m_month = m_oldMonth;
271
m_month = m_month / 10;
272
//m_month = m_oldMonth / 10 * 10 + m_month / 10;
275
return QCalendarDateSectionValidator::PrevSection;
276
return QCalendarDateSectionValidator::ThisSection;
278
if (key < Qt::Key_0 || key > Qt::Key_9)
279
return QCalendarDateSectionValidator::ThisSection;
280
int pressedKey = key - Qt::Key_0;
282
m_month = pressedKey;
284
m_month = m_month % 10 * 10 + pressedKey;
290
return QCalendarDateSectionValidator::NextSection;
292
return QCalendarDateSectionValidator::ThisSection;
295
QDate QCalendarMonthValidator::applyToDate(const QDate &date) const
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);
309
void QCalendarMonthValidator::setDate(const QDate &date)
311
m_month = m_oldMonth = date.month();
315
QString QCalendarMonthValidator::text() const
318
if (m_month / 10 == 0)
319
str += QLatin1Char('0');
320
str += QString::number(m_month);
321
return highlightString(str, m_pos);
324
QString QCalendarMonthValidator::text(const QDate &date, int repeat) const
327
return QString::number(date.month());
328
} else if (repeat == 2) {
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);
340
//////////////////////////////////
342
class QCalendarYearValidator : public QCalendarDateSectionValidator
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;
359
QCalendarYearValidator::QCalendarYearValidator()
360
: QCalendarDateSectionValidator(), m_pos(0), m_year(2000), m_oldYear(2000)
364
int QCalendarYearValidator::pow10(int n)
367
for (int i = 0; i < n; i++)
372
QCalendarDateSectionValidator::Section QCalendarYearValidator::handleKey(int key)
374
if (key == Qt::Key_Right || key == Qt::Key_Left) {
376
return QCalendarDateSectionValidator::ThisSection;
377
} else if (key == Qt::Key_Up) {
380
return QCalendarDateSectionValidator::ThisSection;
381
} else if (key == Qt::Key_Down) {
384
return QCalendarDateSectionValidator::ThisSection;
385
} else if (key == Qt::Key_Back || key == Qt::Key_Backspace) {
390
int pow = pow10(m_pos);
391
m_year = m_oldYear / pow * pow + m_year % (pow * 10) / 10;
394
return QCalendarDateSectionValidator::PrevSection;
395
return QCalendarDateSectionValidator::ThisSection;
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;
405
return QCalendarDateSectionValidator::NextSection;
407
return QCalendarDateSectionValidator::ThisSection;
410
QDate QCalendarYearValidator::applyToDate(const QDate &date) const
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);
422
void QCalendarYearValidator::setDate(const QDate &date)
424
m_year = m_oldYear = date.year();
428
QString QCalendarYearValidator::text() const
432
for (int i = 0; i < 3; i++) {
433
if (m_year / pow == 0)
434
str += QLatin1Char('0');
437
str += QString::number(m_year);
438
return highlightString(str, m_pos);
441
QString QCalendarYearValidator::text(const QDate &date, int repeat) const
445
int year = date.year() % 100;
447
str = QLatin1Char('0');
448
return str + QString::number(year);
450
return QString::number(date.year());
453
///////////////////////////////////
455
class QCalendarDateValidator
458
QCalendarDateValidator();
459
~QCalendarDateValidator();
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);
467
void setLocale(const QLocale &locale);
471
struct SectionToken {
472
SectionToken(QCalendarDateSectionValidator *val, int rep) : validator(val), repeat(rep) {}
473
QCalendarDateSectionValidator *validator;
478
void toPreviousToken();
481
int countRepeat(const QString &str, int index) const;
484
QStringList m_separators;
485
QList<SectionToken *> m_tokens;
486
QCalendarDateSectionValidator *m_yearValidator;
487
QCalendarDateSectionValidator *m_monthValidator;
488
QCalendarDateSectionValidator *m_dayValidator;
490
SectionToken *m_currentToken;
495
QCalendarDateSectionValidator::Section m_lastSectionMove;
498
QCalendarDateValidator::QCalendarDateValidator()
499
: m_currentToken(0), m_lastSectionMove(QCalendarDateSectionValidator::ThisSection)
501
m_initialDate = m_currentDate = QDate::currentDate();
502
m_yearValidator = new QCalendarYearValidator();
503
m_monthValidator = new QCalendarMonthValidator();
504
m_dayValidator = new QCalendarDayValidator();
507
void QCalendarDateValidator::setLocale(const QLocale &locale)
509
m_yearValidator->m_locale = locale;
510
m_monthValidator->m_locale = locale;
511
m_dayValidator->m_locale = locale;
514
QCalendarDateValidator::~QCalendarDateValidator()
516
delete m_yearValidator;
517
delete m_monthValidator;
518
delete m_dayValidator;
522
// from qdatetime.cpp
523
int QCalendarDateValidator::countRepeat(const QString &str, int index) const
525
Q_ASSERT(index >= 0 && index < str.size());
527
const QChar ch = str.at(index);
528
while (index + count < str.size() && str.at(index + count) == ch)
533
void QCalendarDateValidator::setInitialDate(const QDate &date)
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;
543
QString QCalendarDateValidator::currentText() const
546
QStringListIterator itSep(m_separators);
547
QListIterator<SectionToken *> itTok(m_tokens);
548
while (itSep.hasNext()) {
550
if (itTok.hasNext()) {
551
SectionToken *token = itTok.next();
552
QCalendarDateSectionValidator *validator = token->validator;
553
if (m_currentToken == token)
554
str += validator->text();
556
str += validator->text(m_currentDate, token->repeat);
562
void QCalendarDateValidator::clear()
564
QListIterator<SectionToken *> it(m_tokens);
569
m_separators.clear();
574
void QCalendarDateValidator::setFormat(const QString &format)
579
const QLatin1Char quote('\'');
580
bool quoting = false;
582
while (pos < format.size()) {
583
QString mid = format.mid(pos);
586
if (mid.startsWith(quote)) {
589
const QChar nextChar = format.at(pos);
591
separator += nextChar;
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);
604
separator += nextChar;
607
m_tokens.append(token);
608
m_separators.append(separator);
609
separator = QString();
611
m_currentToken = token;
618
m_separators += separator;
621
void QCalendarDateValidator::applyToDate()
623
m_currentDate = m_yearValidator->applyToDate(m_currentDate);
624
m_currentDate = m_monthValidator->applyToDate(m_currentDate);
625
m_currentDate = m_dayValidator->applyToDate(m_currentDate);
628
void QCalendarDateValidator::toNextToken()
630
const int idx = m_tokens.indexOf(m_currentToken);
633
if (idx + 1 >= m_tokens.count())
634
m_currentToken = m_tokens.first();
636
m_currentToken = m_tokens.at(idx + 1);
639
void QCalendarDateValidator::toPreviousToken()
641
const int idx = m_tokens.indexOf(m_currentToken);
645
m_currentToken = m_tokens.last();
647
m_currentToken = m_tokens.at(idx - 1);
650
void QCalendarDateValidator::handleKeyEvent(QKeyEvent *keyEvent)
655
int key = keyEvent->key();
656
if (m_lastSectionMove == QCalendarDateSectionValidator::NextSection) {
657
if (key == Qt::Key_Back || key == Qt::Key_Backspace)
660
if (key == Qt::Key_Right)
662
else if (key == Qt::Key_Left)
665
m_lastSectionMove = m_currentToken->validator->handleKey(key);
668
if (m_lastSectionMove == QCalendarDateSectionValidator::NextSection)
670
else if (m_lastSectionMove == QCalendarDateSectionValidator::PrevSection)
674
QWidget *QCalendarTextNavigator::widget() const
679
void QCalendarTextNavigator::setWidget(QWidget *widget)
684
QDate QCalendarTextNavigator::date() const
689
void QCalendarTextNavigator::setDate(const QDate &date)
694
void QCalendarTextNavigator::updateDateLabel()
699
m_acceptTimer.start(m_editDelay, this);
701
m_dateText->setText(m_dateValidator->currentText());
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);
713
m_dateFrame->raise();
717
void QCalendarTextNavigator::applyDate()
719
QDate date = m_dateValidator->currentDate();
724
emit dateChanged(date);
727
void QCalendarTextNavigator::createDateLabel()
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);
743
m_dateFrame->setAutoFillBackground(true);
744
m_dateFrame->setBackgroundRole(QPalette::Window);
747
void QCalendarTextNavigator::removeDateLabel()
751
m_acceptTimer.stop();
753
m_dateFrame->deleteLater();
754
delete m_dateValidator;
760
bool QCalendarTextNavigator::eventFilter(QObject *o, QEvent *e)
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) {
768
emit editingFinished();
770
} else if (ke->key() == Qt::Key_Escape) {
772
} else if (e->type() == QEvent::KeyPress) {
774
m_dateValidator->handleKeyEvent(ke);
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
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));
792
return QObject::eventFilter(o,e);
795
void QCalendarTextNavigator::timerEvent(QTimerEvent *e)
797
if (e->timerId() == m_acceptTimer.timerId()) {
803
int QCalendarTextNavigator::dateEditAcceptDelay() const
808
void QCalendarTextNavigator::setDateEditAcceptDelay(int delay)
815
class QCalendarModel : public QAbstractTableModel
819
QCalendarModel(QObject *parent = 0);
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;
828
bool insertRows(int row, int count, const QModelIndex &parent = QModelIndex())
830
beginInsertRows(parent, row, row + count - 1);
834
bool insertColumns(int column, int count, const QModelIndex &parent = QModelIndex())
836
beginInsertColumns(parent, column, column + count - 1);
840
bool removeRows(int row, int count, const QModelIndex &parent = QModelIndex())
842
beginRemoveRows(parent, row, row + count - 1);
846
bool removeColumns(int column, int count, const QModelIndex &parent = QModelIndex())
848
beginRemoveColumns(parent, column, column + count - 1);
853
void showMonth(int year, int month);
854
void setDate(const QDate &d);
856
void setMinimumDate(const QDate &date);
857
void setMaximumDate(const QDate &date);
859
void setRange(const QDate &min, const QDate &max);
861
void setHorizontalHeaderFormat(QCalendarWidget::HorizontalHeaderFormat format);
863
void setFirstColumnDay(Qt::DayOfWeek dayOfWeek);
864
Qt::DayOfWeek firstColumnDay() const;
866
bool weekNumbersShown() const;
867
void setWeekNumbersShown(bool show);
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;
876
void setView(QCalendarView *view)
879
void internalUpdate();
880
QDate referenceDate() const;
881
int columnForFirstOfMonth(const QDate &date) const;
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;
899
class QCalendarView : public QTableView
903
QCalendarView(QWidget *parent = 0);
905
void internalUpdate() { updateGeometries(); }
906
void setReadOnly(bool enable);
907
virtual void keyboardSearch(const QString & search) { Q_UNUSED(search) }
910
void showDate(const QDate &date);
911
void changeDate(const QDate &date, bool changeMonth);
912
void clicked(const QDate &date);
913
void editingFinished();
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);
923
void keyPressEvent(QKeyEvent *event);
924
bool event(QEvent *event);
926
QDate handleMouseEvent(QMouseEvent *event);
930
bool validDateClicked;
931
#ifdef QT_KEYPAD_NAVIGATION
936
QCalendarModel::QCalendarModel(QObject *parent)
937
: QAbstractTableModel(parent)
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;
952
Qt::DayOfWeek QCalendarModel::dayOfWeekForColumn(int column) const
954
int col = column - m_firstColumn;
955
if (col < 0 || col > 6)
957
int day = m_firstDay + col;
960
return Qt::DayOfWeek(day);
963
int QCalendarModel::columnForDayOfWeek(Qt::DayOfWeek day) const
965
if (day < 1 || day > 7)
967
int column = (int)day - (int)m_firstDay;
970
return column + m_firstColumn;
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.
985
QDate QCalendarModel::referenceDate() const
988
while (refDay <= 31) {
989
QDate refDate(m_shownYear, m_shownMonth, refDay);
990
if (refDate.isValid())
997
int QCalendarModel::columnForFirstOfMonth(const QDate &date) const
999
return (columnForDayOfWeek(static_cast<Qt::DayOfWeek>(date.dayOfWeek())) - (date.day() % 7) + 8) % 7;
1002
QDate QCalendarModel::dateForCell(int row, int column) const
1004
if (row < m_firstRow || row > m_firstRow + RowCount - 1 ||
1005
column < m_firstColumn || column > m_firstColumn + ColumnCount - 1)
1007
const QDate refDate = referenceDate();
1008
if (!refDate.isValid())
1011
const int columnForFirstOfShownMonth = columnForFirstOfMonth(refDate);
1012
if (columnForFirstOfShownMonth - m_firstColumn < MinimumDayOffset)
1015
const int requestedDay = 7 * (row - m_firstRow) + column - columnForFirstOfShownMonth - refDate.day() + 1;
1016
return refDate.addDays(requestedDay);
1019
void QCalendarModel::cellForDate(const QDate &date, int *row, int *column) const
1021
if (!row && !column)
1029
const QDate refDate = referenceDate();
1030
if (!refDate.isValid())
1033
const int columnForFirstOfShownMonth = columnForFirstOfMonth(refDate);
1034
const int requestedPosition = refDate.daysTo(date) - m_firstColumn + columnForFirstOfShownMonth + refDate.day() - 1;
1036
int c = requestedPosition % 7;
1037
int r = requestedPosition / 7;
1043
if (columnForFirstOfShownMonth - m_firstColumn < MinimumDayOffset)
1046
if (r < 0 || r > RowCount - 1 || c < 0 || c > ColumnCount - 1)
1050
*row = r + m_firstRow;
1052
*column = c + m_firstColumn;
1055
QString QCalendarModel::dayName(Qt::DayOfWeek day) const
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;
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);
1074
QTextCharFormat QCalendarModel::formatForCell(int row, int col) const
1077
QPalette::ColorGroup cg = QPalette::Active;
1079
pal = m_view->palette();
1080
if (!m_view->isEnabled())
1081
cg = QPalette::Disabled;
1082
else if (!m_view->isActiveWindow())
1083
cg = QPalette::Inactive;
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));
1093
format.merge(m_headerFormat);
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));
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));
1113
QVariant QCalendarModel::data(const QModelIndex &index, int role) const
1115
if (role == Qt::TextAlignmentRole)
1116
return (int) Qt::AlignCenter;
1118
int row = index.row();
1119
int column = index.column();
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));
1126
return date.weekNumber();
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);
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)
1144
if (role == Qt::ToolTipRole)
1145
return fmt.toolTip();
1149
Qt::ItemFlags QCalendarModel::flags(const QModelIndex &index) const
1151
QDate date = dateForCell(index.row(), index.column());
1152
if (!date.isValid())
1153
return QAbstractTableModel::flags(index);
1154
if (date < m_minimumDate)
1156
if (date > m_maximumDate)
1158
return QAbstractTableModel::flags(index);
1161
void QCalendarModel::setDate(const QDate &d)
1164
if (m_date < m_minimumDate)
1165
m_date = m_minimumDate;
1166
else if (m_date > m_maximumDate)
1167
m_date = m_maximumDate;
1170
void QCalendarModel::showMonth(int year, int month)
1172
if (m_shownYear == year && m_shownMonth == month)
1176
m_shownMonth = month;
1181
void QCalendarModel::setMinimumDate(const QDate &d)
1183
if (!d.isValid() || d == m_minimumDate)
1187
if (m_maximumDate < m_minimumDate)
1188
m_maximumDate = m_minimumDate;
1189
if (m_date < m_minimumDate)
1190
m_date = m_minimumDate;
1194
void QCalendarModel::setMaximumDate(const QDate &d)
1196
if (!d.isValid() || d == m_maximumDate)
1200
if (m_minimumDate > m_maximumDate)
1201
m_minimumDate = m_maximumDate;
1202
if (m_date > m_maximumDate)
1203
m_date = m_maximumDate;
1207
void QCalendarModel::setRange(const QDate &min, const QDate &max)
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;
1220
void QCalendarModel::internalUpdate()
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);
1229
void QCalendarModel::setHorizontalHeaderFormat(QCalendarWidget::HorizontalHeaderFormat format)
1231
if (m_horizontalHeaderFormat == format)
1234
int oldFormat = m_horizontalHeaderFormat;
1235
m_horizontalHeaderFormat = format;
1236
if (oldFormat == QCalendarWidget::NoHorizontalHeader) {
1239
} else if (m_horizontalHeaderFormat == QCalendarWidget::NoHorizontalHeader) {
1246
void QCalendarModel::setFirstColumnDay(Qt::DayOfWeek dayOfWeek)
1248
if (m_firstDay == dayOfWeek)
1251
m_firstDay = dayOfWeek;
1255
Qt::DayOfWeek QCalendarModel::firstColumnDay() const
1260
bool QCalendarModel::weekNumbersShown() const
1262
return m_weekNumbersShown;
1265
void QCalendarModel::setWeekNumbersShown(bool show)
1267
if (m_weekNumbersShown == show)
1270
m_weekNumbersShown = show;
1281
QCalendarView::QCalendarView(QWidget *parent)
1282
: QTableView(parent),
1284
validDateClicked(false)
1286
setTabKeyNavigation(false);
1288
verticalHeader()->setVisible(false);
1289
horizontalHeader()->setVisible(false);
1290
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
1291
setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
1294
QModelIndex QCalendarView::moveCursor(CursorAction cursorAction, Qt::KeyboardModifiers modifiers)
1296
QCalendarModel *calendarModel = qobject_cast<QCalendarModel *>(model());
1298
return QTableView::moveCursor(cursorAction, modifiers);
1301
return currentIndex();
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);
1309
case QAbstractItemView::MoveDown:
1310
currentDate = currentDate.addDays(7);
1312
case QAbstractItemView::MoveLeft:
1313
currentDate = currentDate.addDays(isRightToLeft() ? 1 : -1);
1315
case QAbstractItemView::MoveRight:
1316
currentDate = currentDate.addDays(isRightToLeft() ? -1 : 1);
1318
case QAbstractItemView::MoveHome:
1319
currentDate = QDate(currentDate.year(), currentDate.month(), 1);
1321
case QAbstractItemView::MoveEnd:
1322
currentDate = QDate(currentDate.year(), currentDate.month(), currentDate.daysInMonth());
1324
case QAbstractItemView::MovePageUp:
1325
currentDate = currentDate.addMonths(-1);
1327
case QAbstractItemView::MovePageDown:
1328
currentDate = currentDate.addMonths(1);
1330
case QAbstractItemView::MoveNext:
1331
case QAbstractItemView::MovePrevious:
1332
return currentIndex();
1336
emit changeDate(currentDate, true);
1337
return currentIndex();
1340
void QCalendarView::keyPressEvent(QKeyEvent *event)
1342
#ifdef QT_KEYPAD_NAVIGATION
1343
if (event->key() == Qt::Key_Select) {
1344
if (QApplication::keypadNavigationEnabled()) {
1345
if (!hasEditFocus()) {
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);
1362
switch (event->key()) {
1363
case Qt::Key_Return:
1365
case Qt::Key_Select:
1366
emit editingFinished();
1372
QTableView::keyPressEvent(event);
1375
#ifndef QT_NO_WHEELEVENT
1376
void QCalendarView::wheelEvent(QWheelEvent *event)
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);
1387
bool QCalendarView::event(QEvent *event)
1389
#ifdef QT_KEYPAD_NAVIGATION
1390
if (event->type() == QEvent::FocusIn) {
1391
if (QCalendarModel *calendarModel = qobject_cast<QCalendarModel *>(model())) {
1392
origDate = calendarModel->m_date;
1397
return QTableView::event(event);
1400
QDate QCalendarView::handleMouseEvent(QMouseEvent *event)
1402
QCalendarModel *calendarModel = qobject_cast<QCalendarModel *>(model());
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) {
1416
void QCalendarView::mouseDoubleClickEvent(QMouseEvent *event)
1418
QCalendarModel *calendarModel = qobject_cast<QCalendarModel *>(model());
1419
if (!calendarModel) {
1420
QTableView::mouseDoubleClickEvent(event);
1427
QDate date = handleMouseEvent(event);
1428
validDateClicked = false;
1429
if (date == calendarModel->m_date && !style()->styleHint(QStyle::SH_ItemView_ActivateItemOnSingleClick)) {
1430
emit editingFinished();
1434
void QCalendarView::mousePressEvent(QMouseEvent *event)
1436
QCalendarModel *calendarModel = qobject_cast<QCalendarModel *>(model());
1437
if (!calendarModel) {
1438
QTableView::mousePressEvent(event);
1445
if (event->button() != Qt::LeftButton)
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);
1457
validDateClicked = false;
1462
void QCalendarView::mouseMoveEvent(QMouseEvent *event)
1464
QCalendarModel *calendarModel = qobject_cast<QCalendarModel *>(model());
1465
if (!calendarModel) {
1466
QTableView::mouseMoveEvent(event);
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);
1487
void QCalendarView::mouseReleaseEvent(QMouseEvent *event)
1489
QCalendarModel *calendarModel = qobject_cast<QCalendarModel *>(model());
1490
if (!calendarModel) {
1491
QTableView::mouseReleaseEvent(event);
1495
if (event->button() != Qt::LeftButton)
1501
if (validDateClicked) {
1502
QDate date = handleMouseEvent(event);
1503
if (date.isValid()) {
1504
emit changeDate(date, true);
1506
if (style()->styleHint(QStyle::SH_ItemView_ActivateItemOnSingleClick))
1507
emit editingFinished();
1509
validDateClicked = false;
1515
class QCalendarDelegate : public QItemDelegate
1519
QCalendarDelegate(QCalendarWidgetPrivate *w, QObject *parent = 0)
1520
: QItemDelegate(parent), calendarWidgetPrivate(w)
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;
1527
QCalendarWidgetPrivate *calendarWidgetPrivate;
1528
mutable QStyleOptionViewItem storedOption;
1531
//Private tool button class
1532
class QCalToolButton: public QToolButton
1535
QCalToolButton(QWidget * parent)
1536
: QToolButton(parent)
1539
void paintEvent(QPaintEvent *e)
1544
QStyleOptionToolButton opt;
1545
initStyleOption(&opt);
1547
if (opt.state & QStyle::State_MouseOver || isDown()) {
1548
//act as normal button
1549
setPalette(QPalette());
1551
//set the highlight color for button text
1552
QPalette toolPalette = palette();
1553
toolPalette.setColor(QPalette::ButtonText, toolPalette.color(QPalette::HighlightedText));
1554
setPalette(toolPalette);
1557
QToolButton::paintEvent(e);
1561
class QPrevNextCalButton : public QToolButton
1565
QPrevNextCalButton(QWidget *parent) : QToolButton(parent) {}
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);
1576
class QCalendarWidgetPrivate : public QWidgetPrivate
1578
Q_DECLARE_PUBLIC(QCalendarWidget)
1580
QCalendarWidgetPrivate();
1582
void showMonth(int year, int month);
1584
void paintCell(QPainter *painter, const QRect &rect, const QDate &date) const;
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();
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);
1605
QCalendarModel *m_model;
1606
QCalendarView *m_view;
1607
QCalendarDelegate *m_delegate;
1608
QItemSelectionModel *m_selection;
1609
QCalendarTextNavigator *m_navigator;
1610
bool m_dateEditEnabled;
1612
QToolButton *nextMonth;
1613
QToolButton *prevMonth;
1614
QCalToolButton *monthButton;
1616
QMap<int, QAction *> monthToAction;
1617
QCalToolButton *yearButton;
1619
QWidget *navBarBackground;
1620
QSpacerItem *spaceHolder;
1623
mutable QSize cachedSizeHint;
1624
Qt::FocusPolicy oldFocusPolicy;
1627
void QCalendarDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option,
1628
const QModelIndex &index) const
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);
1636
QItemDelegate::paint(painter, option, index);
1640
void QCalendarDelegate::paintCell(QPainter *painter, const QRect &rect, const QDate &date) const
1642
storedOption.rect = rect;
1645
calendarWidgetPrivate->m_model->cellForDate(date, &row, &col);
1646
QModelIndex idx = calendarWidgetPrivate->m_model->index(row, col);
1647
QItemDelegate::paint(painter, storedOption, idx);
1650
QCalendarWidgetPrivate::QCalendarWidgetPrivate()
1658
m_dateEditEnabled = false;
1659
navBarVisible = true;
1660
oldFocusPolicy = Qt::StrongFocus;
1663
void QCalendarWidgetPrivate::setNavigatorEnabled(bool enable)
1665
Q_Q(QCalendarWidget);
1667
bool navigatorEnabled = (m_navigator->widget() != 0);
1668
if (enable == navigatorEnabled)
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);
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);
1688
void QCalendarWidgetPrivate::createNavigationBar(QWidget *widget)
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);
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);
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);
1716
monthToAction[i] = act;
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);
1724
QFont font = q->font();
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());
1732
spaceHolder = new QSpacerItem(0,0);
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);
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);
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"));
1760
showMonth(m_model->m_date.year(), m_model->m_date.month());
1763
void QCalendarWidgetPrivate::updateButtonIcons()
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));
1770
void QCalendarWidgetPrivate::updateMonthMenu()
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;
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;
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);
1795
void QCalendarWidgetPrivate::updateMonthMenuNames()
1797
Q_Q(QCalendarWidget);
1799
for (int i = 1; i <= 12; i++) {
1800
QString monthName(q->locale().standaloneMonthName(i, QLocale::LongFormat));
1801
monthToAction[i]->setText(monthName);
1805
void QCalendarWidgetPrivate::updateCurrentPage(const QDate &date)
1807
Q_Q(QCalendarWidget);
1809
QDate newDate = date;
1810
QDate minDate = q->minimumDate();
1811
QDate maxDate = q->maximumDate();
1812
if (minDate.isValid()&& minDate.daysTo(newDate) < 0)
1814
if (maxDate.isValid()&& maxDate.daysTo(newDate) > 0)
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)
1821
m_view->selectionModel()->setCurrentIndex(m_model->index(row, col),
1822
QItemSelectionModel::NoUpdate);
1826
void QCalendarWidgetPrivate::_q_monthChanged(QAction *act)
1828
monthButton->setText(act->text());
1829
QDate currentDate = getCurrentDate();
1830
QDate newDate = currentDate.addMonths(act->data().toInt()-currentDate.month());
1831
updateCurrentPage(newDate);
1834
QDate QCalendarWidgetPrivate::getCurrentDate()
1836
QModelIndex index = m_view->currentIndex();
1837
return m_model->dateForCell(index.row(), index.column());
1840
void QCalendarWidgetPrivate::_q_prevMonthClicked()
1842
QDate currentDate = getCurrentDate().addMonths(-1);
1843
updateCurrentPage(currentDate);
1846
void QCalendarWidgetPrivate::_q_nextMonthClicked()
1848
QDate currentDate = getCurrentDate().addMonths(1);
1849
updateCurrentPage(currentDate);
1852
void QCalendarWidgetPrivate::_q_yearEditingFinished()
1854
Q_Q(QCalendarWidget);
1855
yearButton->setText(yearEdit->text());
1857
q->setFocusPolicy(oldFocusPolicy);
1858
qApp->removeEventFilter(q);
1859
spaceHolder->changeSize(0, 0);
1861
QDate currentDate = getCurrentDate();
1862
currentDate = currentDate.addYears(yearEdit->text().toInt() - currentDate.year());
1863
updateCurrentPage(currentDate);
1866
void QCalendarWidgetPrivate::_q_yearClicked()
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);
1874
oldFocusPolicy = q->focusPolicy();
1875
q->setFocusPolicy(Qt::NoFocus);
1877
qApp->installEventFilter(q);
1879
yearEdit->selectAll();
1880
yearEdit->setFocus(Qt::MouseFocusReason);
1883
void QCalendarWidgetPrivate::showMonth(int year, int month)
1885
if (m_model->m_shownYear == year && m_model->m_shownMonth == month)
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();
1897
void QCalendarWidgetPrivate::updateNavigationBar()
1899
Q_Q(QCalendarWidget);
1901
QString monthName = q->locale().standaloneMonthName(m_model->m_shownMonth, QLocale::LongFormat);
1903
monthButton->setText(monthName);
1904
yearButton->setText(QString::number(m_model->m_shownYear));
1905
yearEdit->setValue(m_model->m_shownYear);
1908
void QCalendarWidgetPrivate::update()
1910
QDate currentDate = m_model->m_date;
1912
m_model->cellForDate(currentDate, &row, &column);
1914
m_selection->clear();
1915
if (row != -1 && column != -1) {
1916
idx = m_model->index(row, column);
1917
m_selection->setCurrentIndex(idx, QItemSelectionModel::SelectCurrent);
1921
void QCalendarWidgetPrivate::paintCell(QPainter *painter, const QRect &rect, const QDate &date) const
1923
Q_Q(const QCalendarWidget);
1924
q->paintCell(painter, rect, date);
1927
void QCalendarWidgetPrivate::_q_slotShowDate(const QDate &date)
1929
updateCurrentPage(date);
1932
void QCalendarWidgetPrivate::_q_slotChangeDate(const QDate &date)
1934
_q_slotChangeDate(date, true);
1937
void QCalendarWidgetPrivate::_q_slotChangeDate(const QDate &date, bool changeMonth)
1939
QDate oldDate = m_model->m_date;
1940
m_model->setDate(date);
1941
QDate newDate = m_model->m_date;
1943
showMonth(newDate.year(), newDate.month());
1944
if (oldDate != newDate) {
1946
Q_Q(QCalendarWidget);
1947
m_navigator->setDate(newDate);
1948
emit q->selectionChanged();
1952
void QCalendarWidgetPrivate::_q_editingFinished()
1954
Q_Q(QCalendarWidget);
1955
emit q->activated(m_model->m_date);
1959
\class QCalendarWidget
1960
\brief The QCalendarWidget class provides a monthly based
1961
calendar widget allowing the user to select a date.
1967
\image fusion-calendarwidget.png
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.
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.
1984
The currently displayed month and year can be retrieved using the
1985
monthShown() and yearShown() functions, respectively.
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.
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:
2005
\image qcalendarwidget-grid.png
2007
\snippet code/src_gui_widgets_qcalendarwidget.cpp 0
2010
Finally, the day in the first column can be altered using the
2011
setFirstDayOfWeek() function.
2013
The QCalendarWidget class also provides three signals,
2014
selectionChanged(), activated() and currentPageChanged() making it
2015
possible to respond to user interaction.
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.
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
2026
\sa QDate, QDateEdit, QTextCharFormat
2030
\enum QCalendarWidget::SelectionMode
2032
This enum describes the types of selection offered to the user for
2033
selecting dates in the calendar.
2035
\value NoSelection Dates cannot be selected.
2036
\value SingleSelection Single dates can be selected.
2042
Constructs a calendar widget with the given \a parent.
2044
The widget is initialized with the current month and year, and the
2045
currently selected date is today.
2047
\sa setCurrentPage()
2049
QCalendarWidget::QCalendarWidget(QWidget *parent)
2050
: QWidget(*new QCalendarWidgetPrivate, parent, 0)
2052
Q_D(QCalendarWidget);
2054
setAutoFillBackground(true);
2055
setBackgroundRole(QPalette::Window);
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);
2080
d->updateNavigationBar();
2081
setFocusPolicy(Qt::StrongFocus);
2082
setFocusProxy(d->m_view);
2083
setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
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()));
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()));
2105
layoutV->setMargin(0);
2106
layoutV->setSpacing(0);
2107
layoutV->addWidget(d->navBarBackground);
2108
layoutV->addWidget(d->m_view);
2110
d->m_navigator = new QCalendarTextNavigator(this);
2111
setDateEditEnabled(true);
2115
Destroys the calendar widget.
2117
QCalendarWidget::~QCalendarWidget()
2124
QSize QCalendarWidget::sizeHint() const
2126
return minimumSizeHint();
2132
QSize QCalendarWidget::minimumSizeHint() const
2134
Q_D(const QCalendarWidget);
2135
if (d->cachedSizeHint.isValid())
2136
return d->cachedSizeHint;
2147
const int marginH = (style()->pixelMetric(QStyle::PM_FocusFrameHMargin) + 1) * 2;
2149
if (horizontalHeaderFormat() == QCalendarWidget::NoHorizontalHeader) {
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());
2159
if (verticalHeaderFormat() == QCalendarWidget::NoVerticalHeader) {
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());
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());
2176
if (d->m_view->showGrid()) {
2177
// hardcoded in tableview
2182
w += 1; // default column span
2184
h = qMax(h, d->m_view->verticalHeader()->minimumSectionSize());
2185
w = qMax(w, d->m_view->horizontalHeader()->minimumSectionSize());
2187
//add the size of the header.
2188
QSize headerSize(0, 0);
2189
if (d->navBarVisible) {
2190
int headerH = d->navBarBackground->sizeHint().height();
2193
headerW += d->prevMonth->sizeHint().width();
2194
headerW += d->nextMonth->sizeHint().width();
2196
QFontMetrics fm = d->monthButton->fontMetrics();
2198
for (int i = 1; i < 12; i++) {
2199
QString monthName = locale().standaloneMonthName(i, QLocale::LongFormat);
2200
monthW = qMax(monthW, fm.boundingRect(monthName).width());
2202
const int buttonDecoMargin = d->monthButton->sizeHint().width() - fm.boundingRect(d->monthButton->text()).width();
2203
headerW += monthW + buttonDecoMargin;
2205
fm = d->yearButton->fontMetrics();
2206
headerW += fm.boundingRect(QLatin1String("5555")).width() + buttonDecoMargin;
2208
headerSize = QSize(headerW, headerH);
2211
w = qMax(headerSize.width(), w);
2212
h = (h * rows) + headerSize.height();
2213
d->cachedSizeHint = QSize(w, h);
2214
return d->cachedSizeHint;
2218
Paints the cell specified by the given \a date, using the given \a painter and \a rect.
2221
void QCalendarWidget::paintCell(QPainter *painter, const QRect &rect, const QDate &date) const
2223
Q_D(const QCalendarWidget);
2224
d->m_delegate->paintCell(painter, rect, date);
2228
\property QCalendarWidget::selectedDate
2229
\brief the currently selected date.
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.
2238
QDate QCalendarWidget::selectedDate() const
2240
Q_D(const QCalendarWidget);
2241
return d->m_model->m_date;
2244
void QCalendarWidget::setSelectedDate(const QDate &date)
2246
Q_D(QCalendarWidget);
2247
if (d->m_model->m_date == date && date == d->getCurrentDate())
2250
if (!date.isValid())
2253
d->m_model->setDate(date);
2255
QDate newDate = d->m_model->m_date;
2256
d->showMonth(newDate.year(), newDate.month());
2257
emit selectionChanged();
2261
Returns the year of the currently displayed month. Months are
2262
numbered from 1 to 12.
2264
\sa monthShown(), setCurrentPage()
2267
int QCalendarWidget::yearShown() const
2269
Q_D(const QCalendarWidget);
2270
return d->m_model->m_shownYear;
2274
Returns the currently displayed month. Months are numbered from 1 to
2277
\sa yearShown(), setCurrentPage()
2280
int QCalendarWidget::monthShown() const
2282
Q_D(const QCalendarWidget);
2283
return d->m_model->m_shownMonth;
2287
Displays the given \a month of the given \a year without changing
2288
the selected date. Use the setSelectedDate() function to alter the
2291
The currently displayed month and year can be retrieved using the
2292
monthShown() and yearShown() functions respectively.
2294
\sa yearShown(), monthShown(), showPreviousMonth(), showNextMonth(),
2295
showPreviousYear(), showNextYear()
2298
void QCalendarWidget::setCurrentPage(int year, int month)
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)
2307
d->showMonth(year, month);
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);
2319
Shows the next month relative to the currently displayed
2320
month. Note that the selected date is not changed.
2322
\sa showPreviousMonth(), setCurrentPage(), setSelectedDate()
2325
void QCalendarWidget::showNextMonth()
2327
int year = yearShown();
2328
int month = monthShown();
2335
setCurrentPage(year, month);
2339
Shows the previous month relative to the currently displayed
2340
month. Note that the selected date is not changed.
2342
\sa showNextMonth(), setCurrentPage(), setSelectedDate()
2345
void QCalendarWidget::showPreviousMonth()
2347
int year = yearShown();
2348
int month = monthShown();
2355
setCurrentPage(year, month);
2359
Shows the currently displayed month in the \e next year relative
2360
to the currently displayed year. Note that the selected date is
2363
\sa showPreviousYear(), setCurrentPage(), setSelectedDate()
2366
void QCalendarWidget::showNextYear()
2368
int year = yearShown();
2369
int month = monthShown();
2371
setCurrentPage(year, month);
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.
2379
\sa showNextYear(), setCurrentPage(), setSelectedDate()
2382
void QCalendarWidget::showPreviousYear()
2384
int year = yearShown();
2385
int month = monthShown();
2387
setCurrentPage(year, month);
2391
Shows the month of the selected date.
2393
\sa selectedDate(), setCurrentPage()
2395
void QCalendarWidget::showSelectedDate()
2397
QDate currentDate = selectedDate();
2398
setCurrentPage(currentDate.year(), currentDate.month());
2402
Shows the month of the today's date.
2404
\sa selectedDate(), setCurrentPage()
2406
void QCalendarWidget::showToday()
2408
QDate currentDate = QDate::currentDate();
2409
setCurrentPage(currentDate.year(), currentDate.month());
2413
\property QCalendarWidget::minimumDate
2414
\brief the minimum date of the currently specified date range.
2416
The user will not be able to select a date that is before the
2417
currently set minimum date.
2421
\li \image qcalendarwidget-minimum.png
2424
\snippet code/src_gui_widgets_qcalendarwidget.cpp 1
2427
By default, the minimum date is the earliest date that the QDate
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.
2438
QDate QCalendarWidget::minimumDate() const
2440
Q_D(const QCalendarWidget);
2441
return d->m_model->m_minimumDate;
2444
void QCalendarWidget::setMinimumDate(const QDate &date)
2446
Q_D(QCalendarWidget);
2447
if (!date.isValid() || d->m_model->m_minimumDate == date)
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) {
2457
d->showMonth(newDate.year(), newDate.month());
2458
d->m_navigator->setDate(newDate);
2459
emit selectionChanged();
2464
\property QCalendarWidget::maximumDate
2465
\brief the maximum date of the currently specified date range.
2467
The user will not be able to select a date which is after the
2468
currently set maximum date.
2472
\li \image qcalendarwidget-maximum.png
2475
\snippet code/src_gui_widgets_qcalendarwidget.cpp 2
2478
By default, the maximum date is the last day the QDate class can
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.
2489
QDate QCalendarWidget::maximumDate() const
2491
Q_D(const QCalendarWidget);
2492
return d->m_model->m_maximumDate;
2495
void QCalendarWidget::setMaximumDate(const QDate &date)
2497
Q_D(QCalendarWidget);
2498
if (!date.isValid() || d->m_model->m_maximumDate == date)
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) {
2508
d->showMonth(newDate.year(), newDate.month());
2509
d->m_navigator->setDate(newDate);
2510
emit selectionChanged();
2515
Defines a date range by setting the minimumDate and maximumDate
2518
The date range restricts the user selection, i.e. the user can
2519
only select dates within the specified date range. Note that
2521
\snippet code/src_gui_widgets_qcalendarwidget.cpp 3
2525
\snippet code/src_gui_widgets_qcalendarwidget.cpp 4
2527
If either the \a min or \a max parameters are not valid QDate
2528
objects, this function does nothing.
2530
\sa setMinimumDate(), setMaximumDate()
2533
void QCalendarWidget::setDateRange(const QDate &min, const QDate &max)
2535
Q_D(QCalendarWidget);
2536
if (d->m_model->m_minimumDate == min && d->m_model->m_maximumDate == max)
2538
if (!min.isValid() || !max.isValid())
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) {
2549
d->showMonth(newDate.year(), newDate.month());
2550
d->m_navigator->setDate(newDate);
2551
emit selectionChanged();
2556
/*! \enum QCalendarWidget::HorizontalHeaderFormat
2558
This enum type defines the various formats the horizontal header can display.
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.
2565
\sa horizontalHeaderFormat(), VerticalHeaderFormat
2569
\property QCalendarWidget::horizontalHeaderFormat
2570
\brief the format of the horizontal header.
2572
The default value is QCalendarWidget::ShortDayNames.
2575
void QCalendarWidget::setHorizontalHeaderFormat(QCalendarWidget::HorizontalHeaderFormat format)
2577
Q_D(QCalendarWidget);
2578
if (d->m_model->m_horizontalHeaderFormat == format)
2581
d->m_model->setHorizontalHeaderFormat(format);
2582
d->cachedSizeHint = QSize();
2583
d->m_view->viewport()->update();
2584
d->m_view->updateGeometry();
2587
QCalendarWidget::HorizontalHeaderFormat QCalendarWidget::horizontalHeaderFormat() const
2589
Q_D(const QCalendarWidget);
2590
return d->m_model->m_horizontalHeaderFormat;
2595
\enum QCalendarWidget::VerticalHeaderFormat
2597
This enum type defines the various formats the vertical header can display.
2599
\value ISOWeekNumbers The header displays ISO week numbers as described by \l QDate::weekNumber().
2600
\value NoVerticalHeader The header is hidden.
2602
\sa verticalHeaderFormat(), HorizontalHeaderFormat
2606
\property QCalendarWidget::verticalHeaderFormat
2607
\brief the format of the vertical header.
2609
The default value is QCalendarWidget::ISOWeekNumber.
2612
QCalendarWidget::VerticalHeaderFormat QCalendarWidget::verticalHeaderFormat() const
2614
Q_D(const QCalendarWidget);
2615
bool shown = d->m_model->weekNumbersShown();
2617
return QCalendarWidget::ISOWeekNumbers;
2618
return QCalendarWidget::NoVerticalHeader;
2621
void QCalendarWidget::setVerticalHeaderFormat(QCalendarWidget::VerticalHeaderFormat format)
2623
Q_D(QCalendarWidget);
2625
if (format == QCalendarWidget::ISOWeekNumbers)
2627
if (d->m_model->weekNumbersShown() == show)
2629
d->m_model->setWeekNumbersShown(show);
2630
d->cachedSizeHint = QSize();
2631
d->m_view->viewport()->update();
2632
d->m_view->updateGeometry();
2636
\property QCalendarWidget::gridVisible
2637
\brief whether the table grid is displayed.
2641
\li \inlineimage qcalendarwidget-grid.png
2644
\snippet code/src_gui_widgets_qcalendarwidget.cpp 5
2647
The default value is false.
2650
bool QCalendarWidget::isGridVisible() const
2652
Q_D(const QCalendarWidget);
2653
return d->m_view->showGrid();
2656
void QCalendarWidget::setGridVisible(bool show)
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();
2666
\property QCalendarWidget::selectionMode
2667
\brief the type of selection the user can make in the calendar
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
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.
2678
The default value is SingleSelection.
2681
QCalendarWidget::SelectionMode QCalendarWidget::selectionMode() const
2683
Q_D(const QCalendarWidget);
2684
return d->m_view->readOnly ? QCalendarWidget::NoSelection : QCalendarWidget::SingleSelection;
2687
void QCalendarWidget::setSelectionMode(SelectionMode mode)
2689
Q_D(QCalendarWidget);
2690
d->m_view->readOnly = (mode == QCalendarWidget::NoSelection);
2691
d->setNavigatorEnabled(isDateEditEnabled() && (selectionMode() != QCalendarWidget::NoSelection));
2696
\property QCalendarWidget::firstDayOfWeek
2697
\brief a value identifying the day displayed in the first column.
2699
By default, the day displayed in the first column
2700
is the first day of the week for the calendar's locale.
2703
void QCalendarWidget::setFirstDayOfWeek(Qt::DayOfWeek dayOfWeek)
2705
Q_D(QCalendarWidget);
2706
if ((Qt::DayOfWeek)d->m_model->firstColumnDay() == dayOfWeek)
2709
d->m_model->setFirstColumnDay(dayOfWeek);
2713
Qt::DayOfWeek QCalendarWidget::firstDayOfWeek() const
2715
Q_D(const QCalendarWidget);
2716
return (Qt::DayOfWeek)d->m_model->firstColumnDay();
2720
Returns the text char format for rendering the header.
2722
QTextCharFormat QCalendarWidget::headerTextFormat() const
2724
Q_D(const QCalendarWidget);
2725
return d->m_model->m_headerFormat;
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.
2735
void QCalendarWidget::setHeaderTextFormat(const QTextCharFormat &format)
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();
2745
Returns the text char format for rendering of day in the week \a dayOfWeek.
2747
\sa headerTextFormat()
2749
QTextCharFormat QCalendarWidget::weekdayTextFormat(Qt::DayOfWeek dayOfWeek) const
2751
Q_D(const QCalendarWidget);
2752
return d->m_model->m_dayFormats.value(dayOfWeek);
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.
2760
\sa setHeaderTextFormat()
2762
void QCalendarWidget::setWeekdayTextFormat(Qt::DayOfWeek dayOfWeek, const QTextCharFormat &format)
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();
2772
Returns a QMap from QDate to QTextCharFormat showing all dates
2773
that use a special format that alters their rendering.
2775
QMap<QDate, QTextCharFormat> QCalendarWidget::dateTextFormat() const
2777
Q_D(const QCalendarWidget);
2778
return d->m_model->m_dateFormats;
2782
Returns a QTextCharFormat for \a date. The char format can be be
2783
empty if the date is not renderd specially.
2785
QTextCharFormat QCalendarWidget::dateTextFormat(const QDate &date) const
2787
Q_D(const QCalendarWidget);
2788
return d->m_model->m_dateFormats.value(date);
2792
Sets the format used to render the given \a date to that specified by \a format.
2794
If \a date is null, all date formats are cleared.
2796
void QCalendarWidget::setDateTextFormat(const QDate &date, const QTextCharFormat &format)
2798
Q_D(QCalendarWidget);
2800
d->m_model->m_dateFormats.clear();
2802
d->m_model->m_dateFormats[date] = format;
2803
d->m_view->viewport()->update();
2804
d->m_view->updateGeometry();
2808
\property QCalendarWidget::dateEditEnabled
2809
\brief whether the date edit popup is enabled
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.
2816
By default, this property is enabled.
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.
2823
\sa QCalendarWidget::dateEditAcceptDelay
2825
bool QCalendarWidget::isDateEditEnabled() const
2827
Q_D(const QCalendarWidget);
2828
return d->m_dateEditEnabled;
2831
void QCalendarWidget::setDateEditEnabled(bool enable)
2833
Q_D(QCalendarWidget);
2834
if (isDateEditEnabled() == enable)
2837
d->m_dateEditEnabled = enable;
2839
d->setNavigatorEnabled(enable && (selectionMode() != QCalendarWidget::NoSelection));
2843
\property QCalendarWidget::dateEditAcceptDelay
2844
\brief the time an inactive date edit is shown before its contents are accepted
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.
2852
By default, the delay is defined to be 1500 milliseconds (1.5 seconds).
2854
int QCalendarWidget::dateEditAcceptDelay() const
2856
Q_D(const QCalendarWidget);
2857
return d->m_navigator->dateEditAcceptDelay();
2860
void QCalendarWidget::setDateEditAcceptDelay(int delay)
2862
Q_D(QCalendarWidget);
2863
d->m_navigator->setDateEditAcceptDelay(delay);
2869
Updates the cell specified by the given \a date unless updates
2870
are disabled or the cell is hidden.
2872
\sa updateCells(), yearShown(), monthShown()
2874
void QCalendarWidget::updateCell(const QDate &date)
2876
if (!date.isValid()) {
2877
qWarning("QCalendarWidget::updateCell: Invalid date");
2884
Q_D(QCalendarWidget);
2886
d->m_model->cellForDate(date, &row, &column);
2887
if (row == -1 || column == -1)
2890
QModelIndex modelIndex = d->m_model->index(row, column);
2891
if (!modelIndex.isValid())
2894
d->m_view->viewport()->update(d->m_view->visualRect(modelIndex));
2900
Updates all visible cells unless updates are disabled.
2904
void QCalendarWidget::updateCells()
2906
Q_D(QCalendarWidget);
2908
d->m_view->viewport()->update();
2912
\fn void QCalendarWidget::selectionChanged()
2914
This signal is emitted when the currently selected date is
2917
The currently selected date can be changed by the user using the
2918
mouse or keyboard, or by the programmer using setSelectedDate().
2924
\fn void QCalendarWidget::currentPageChanged(int year, int month)
2926
This signal is emitted when the currently shown month is changed.
2927
The new \a year and \a month are passed as parameters.
2929
\sa setCurrentPage()
2933
\fn void QCalendarWidget::activated(const QDate &date)
2935
This signal is emitted whenever the user presses the Return or
2936
Enter key or double-clicks a \a date in the calendar
2941
\fn void QCalendarWidget::clicked(const QDate &date)
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.
2952
\property QCalendarWidget::navigationBarVisible
2953
\brief whether the navigation bar is shown or not
2957
When this property is true (the default), the next month,
2958
previous month, month selection, year selection controls are
2961
When the property is set to false, these controls are hidden.
2964
bool QCalendarWidget::isNavigationBarVisible() const
2966
Q_D(const QCalendarWidget);
2967
return d->navBarVisible;
2971
void QCalendarWidget::setNavigationBarVisible(bool visible)
2973
Q_D(QCalendarWidget);
2974
d->navBarVisible = visible;
2975
d->cachedSizeHint = QSize();
2976
d->navBarBackground->setVisible(visible);
2983
bool QCalendarWidget::event(QEvent *event)
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();
2996
case QEvent::FontChange:
2997
case QEvent::ApplicationFontChange:
2998
d->cachedSizeHint = QSize();
2999
d->m_view->updateGeometry();
3001
case QEvent::StyleChange:
3002
d->cachedSizeHint = QSize();
3003
d->m_view->updateGeometry();
3007
return QWidget::event(event);
3013
bool QCalendarWidget::eventFilter(QObject *watched, QEvent *event)
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)) {
3026
d->_q_yearEditingFinished();
3032
return QWidget::eventFilter(watched, event);
3038
void QCalendarWidget::mousePressEvent(QMouseEvent *event)
3040
setAttribute(Qt::WA_NoMouseReplay);
3041
QWidget::mousePressEvent(event);
3048
void QCalendarWidget::resizeEvent(QResizeEvent * event)
3050
Q_D(QCalendarWidget);
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();
3058
QWidget::resizeEvent(event);
3064
void QCalendarWidget::keyPressEvent(QKeyEvent * event)
3066
Q_D(QCalendarWidget);
3067
if(d->yearEdit->isVisible()&& event->key() == Qt::Key_Escape)
3069
d->yearEdit->setValue(yearShown());
3070
d->_q_yearEditingFinished();
3073
QWidget::keyPressEvent(event);
3078
#include "qcalendarwidget.moc"
3079
#include "moc_qcalendarwidget.cpp"
3081
#endif //QT_NO_CALENDARWIDGET