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