📄 qcalendarwidget.cpp
字号:
QString QCalendarYearValidator::text(const QDate &date, int repeat) const{ if (repeat < 4) { QString str; int year = date.year() % 100; if (year / 10 == 0) str = QLatin1String("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.cppint 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 QLatin1String 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();}class QCalendarTextNavigator: public QObject{ Q_OBJECTpublic: QCalendarTextNavigator(QObject *parent = 0) : QObject(parent), m_dateText(0), m_dateFrame(0), m_dateValidator(0), m_calendar(0), m_editDelay(1500) { } QCalendarWidget *calendar() const; void setCalendar(QCalendarWidget *calendar); void applyDate(); void updateDateLabel(); void createDateLabel(); void removeDateLabel(); int dateEditAcceptDelay() const; void setDateEditAcceptDelay(int delay); bool eventFilter(QObject *o, QEvent *e); void timerEvent(QTimerEvent *e); void setLocale(const QLocale &locale);signals: void changeDate(const QDate &date, bool changeMonth); void editingFinished();private: QLabel *m_dateText; QFrame *m_dateFrame; QBasicTimer m_acceptTimer; QCalendarDateValidator *m_dateValidator; QCalendarWidget *m_calendar; int m_editDelay; QLocale m_locale;};QCalendarWidget *QCalendarTextNavigator::calendar() const{ return m_calendar;}void QCalendarTextNavigator::setCalendar(QCalendarWidget *calendar){ m_calendar = calendar;}void QCalendarTextNavigator::updateDateLabel(){ if (!m_calendar) return; m_acceptTimer.start(m_editDelay, this); m_dateText->setText(m_dateValidator->currentText()); QSize s = m_dateFrame->sizeHint(); QRect r = m_calendar->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(); emit changeDate(date, true);}void QCalendarTextNavigator::setLocale(const QLocale &locale){ m_locale = locale; if (m_dateValidator != 0) { m_dateValidator->setLocale(locale); updateDateLabel(); }}void QCalendarTextNavigator::createDateLabel(){ if (m_dateFrame) return; m_dateFrame = new QFrame(m_calendar); 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_locale); m_dateValidator->setFormat(m_locale.dateFormat(QLocale::ShortFormat)); m_dateValidator->setInitialDate(m_calendar->selectedDate()); 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_calendar && m_calendar->selectionMode() != QCalendarWidget::NoSelection) { 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; } } } 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_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; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -