qcalendarwidget.cpp

来自「QT 开发环境里面一个很重要的文件」· C++ 代码 · 共 2,019 行 · 第 1/4 页

CPP
2,019
字号
/******************************************************************************** Copyright (C) 1992-2006 Trolltech ASA. All rights reserved.**** This file is part of the QtGui module of the Qt Toolkit.**** This file may be used under the terms of the GNU General Public** License version 2.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 GNU** General Public Licensing requirements will be met:** http://www.trolltech.com/products/qt/opensource.html**** If you are unsure which license is appropriate for your use, please** review the following information:** http://www.trolltech.com/products/qt/licensing.html or contact the** sales department at sales@trolltech.com.**** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.******************************************************************************/#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>enum {    RowCount = 6,    ColumnCount = 7,    HeaderColumn = 0,    HeaderRow = 0,    MinimumDayOffset = 1};class QCalendarView;class QCalendarModel : public QAbstractTableModel{    Q_OBJECTpublic:    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;    int dayOfWeekForColumn(int section) const;    int columnForDayOfWeek(int day) const;    QDate dateForCell(int row, int column) const;    void cellForDate(const QDate &date, int *row, int *column) const;    QString dayName(int day) const;    void setView(QCalendarView *view)        { m_view = view; }    void internalUpdate();    int m_firstColumn;    int m_firstRow;    QDate date;    QDate minimumDate;    QDate maximumDate;    int shownYear;    int shownMonth;    Qt::DayOfWeek m_firstDay;    QCalendarWidget::HorizontalHeaderFormat 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_OBJECTpublic:    QCalendarView(QWidget *parent = 0);    void internalUpdate() { updateGeometries(); }    void setReadOnly(bool enable);signals:    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);    void keyPressEvent(QKeyEvent *event);    bool event(QEvent *event);    QDate handleMouseEvent(QMouseEvent *event);public:    bool readOnly;private:    bool validDateClicked;};QCalendarModel::QCalendarModel(QObject *parent)    : QAbstractTableModel(parent){    date = QDate::currentDate();    minimumDate = QDate::fromJulianDay(0);    maximumDate = QDate(7999, 12, 31);    shownYear = date.year();    shownMonth = date.month();    m_firstDay = Qt::Sunday;    horizontalHeaderFormat = QCalendarWidget::ShortDayNames;    m_weekNumbersShown = true;    m_firstColumn = 1;    m_firstRow = 1;    m_view = 0;}int QCalendarModel::dayOfWeekForColumn(int column) const{    int col = column - m_firstColumn;    if (col < 0 || col > 6)        return 0;    int day = m_firstDay + col;    if (day > 7)        day -= 7;    return Qt::DayOfWeek(day);}int QCalendarModel::columnForDayOfWeek(int 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;}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();    QDate firstDate(shownYear, shownMonth, 15);    if (!firstDate.isValid()) {        return QDate();    }    int columnForFirstOfShownMonth = columnForDayOfWeek(firstDate.dayOfWeek());    if (columnForFirstOfShownMonth - m_firstColumn < MinimumDayOffset)        row -= 1;    int daysInShownMonth = firstDate.daysInMonth();    int requestedDay = 7 * (row - m_firstRow) + column - columnForFirstOfShownMonth + 1;    if (requestedDay > daysInShownMonth) {        QDate nextMonth = firstDate.addMonths(1);        if (!nextMonth.isValid()) {            return QDate();        }        return QDate(nextMonth.year(), nextMonth.month(),                    requestedDay - daysInShownMonth);    } else if (requestedDay <= 0) {        QDate previousMonth = firstDate.addMonths(-1);        if (!previousMonth.isValid()) {            return QDate();        }        int daysInMonth = previousMonth.daysInMonth();        return QDate(previousMonth.year(), previousMonth.month(),                    daysInMonth + requestedDay);    }    return QDate(shownYear, shownMonth, requestedDay);}void QCalendarModel::cellForDate(const QDate &date, int *row, int *column) const{    int day = date.day();    QDate firstDate(shownYear, shownMonth, 15);    int columnForFirstOfShownMonth = columnForDayOfWeek(firstDate.dayOfWeek());    int daysInShownMonth = firstDate.daysInMonth();    QDate previousMonth = firstDate.addMonths(-1);    QDate nextMonth = firstDate.addMonths(1);    if (date.year() == shownYear && date.month() == shownMonth) {        *column = (day + columnForFirstOfShownMonth - m_firstColumn - 1) % 7;        *row = (day + columnForFirstOfShownMonth - m_firstColumn - 1) / 7;    } else if (previousMonth.isValid() &&            date.year() == previousMonth.year() && date.month() == previousMonth.month()) {        int daysInMonth = previousMonth.daysInMonth();        *column = (day - daysInMonth + columnForFirstOfShownMonth - m_firstColumn - 1) % 7;        *row = (day - daysInMonth + columnForFirstOfShownMonth - m_firstColumn - 1) / 7;        if (*column < 0) {            *column += 7;            *row -= 1;        }    } else if (nextMonth.isValid() &&            date.year() == nextMonth.year() && date.month() == nextMonth.month()) {        *column = (day + daysInShownMonth + columnForFirstOfShownMonth - m_firstColumn - 1) % 7;        *row = (day + daysInShownMonth + columnForFirstOfShownMonth - m_firstColumn - 1) / 7;    } else {        *row = -1;        *column = -1;        return;    }    if (columnForFirstOfShownMonth - m_firstColumn < MinimumDayOffset)        *row += 1;    if (*row < 0 || *row > RowCount - 1 || *column < 0 || *column > ColumnCount - 1) {        *row = -1;        *column = -1;        return;    }    *row += m_firstRow;    *column += m_firstColumn;}QString QCalendarModel::dayName(int day) const{    switch (horizontalHeaderFormat) {        case QCalendarWidget::SingleLetterDayNames:            return QDate::shortDayName(day).left(1);        case QCalendarWidget::ShortDayNames:            return QDate::shortDayName(day);        case QCalendarWidget::LongDayNames:            return QDate::longDayName(day);        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)                  || (horizontalHeaderFormat != QCalendarWidget::NoHorizontalHeader && row == HeaderRow);    format.setBackground(pal.brush(cg, header ? QPalette::AlternateBase : QPalette::Base));    if (header) {        format.merge(m_headerFormat);    }    if (col >= m_firstColumn && col < m_firstColumn + ColumnCount) {        Qt::DayOfWeek dayOfWeek = Qt::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 < minimumDate || date > maximumDate)            format.setBackground(pal.brush(cg, QPalette::Window));        if (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 (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();    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 < minimumDate)        return 0;    if (date > maximumDate)        return 0;    return QAbstractTableModel::flags(index);}void QCalendarModel::setDate(const QDate &d){    date = d;    if (date < minimumDate)        date = minimumDate;    else if (date > maximumDate)        date = maximumDate;}void QCalendarModel::showMonth(int year, int month){    if (shownYear == year && shownMonth == month)        return;    shownYear = year;    shownMonth = month;    internalUpdate();}void QCalendarModel::setMinimumDate(const QDate &d){    if (!d.isValid() || d == minimumDate)        return;    minimumDate = d;    if (maximumDate < minimumDate)        maximumDate = minimumDate;    if (date < minimumDate)        date = minimumDate;    internalUpdate();}void QCalendarModel::setMaximumDate(const QDate &d){    if (!d.isValid() || d == maximumDate)        return;    maximumDate = d;    if (minimumDate > maximumDate)        minimumDate = maximumDate;    if (date > maximumDate)        date = maximumDate;    internalUpdate();}void QCalendarModel::setRange(const QDate &min, const QDate &max){    minimumDate = min;    maximumDate = max;    if(minimumDate > maximumDate)        qSwap(minimumDate, maximumDate);    if (date < minimumDate)        date = minimumDate;    if (date > maximumDate)        date = 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 (horizontalHeaderFormat == format)        return;    int oldFormat = horizontalHeaderFormat;    horizontalHeaderFormat = format;    if (oldFormat == QCalendarWidget::NoHorizontalHeader) {        m_firstRow = 1;        insertRow(0);    } else if (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);

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?