From 2dee00621632ab8acd0b3d59bdba264afe2f32c1 Mon Sep 17 00:00:00 2001 From: Soroush Rabiei Date: Thu, 8 Aug 2019 15:19:18 +0200 Subject: Adapt QCalendarWidget and QDateTimeEdit to support choice of calendar [ChangeLog][QtWidgets][QCalendarWidget] Allow choice of calendar, with Gregorian remaining the default. [ChangeLog][QtWidgets][QDateTimeEdit] Allow choice of calendar, with Gregorian remaining the default. Change-Id: Ia11dd895032393543aee534b177324e643dcfb20 Done-with: Edward Welbourne Reviewed-by: Volker Hilsheimer --- src/widgets/widgets/qcalendarwidget.cpp | 333 +++++++++++++++++++------------- 1 file changed, 198 insertions(+), 135 deletions(-) (limited to 'src/widgets/widgets/qcalendarwidget.cpp') diff --git a/src/widgets/widgets/qcalendarwidget.cpp b/src/widgets/widgets/qcalendarwidget.cpp index 81cc0b833a..296a15f94b 100644 --- a/src/widgets/widgets/qcalendarwidget.cpp +++ b/src/widgets/widgets/qcalendarwidget.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2019 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtWidgets module of the Qt Toolkit. @@ -57,6 +57,7 @@ #include #include #include +#include #include @@ -90,16 +91,15 @@ public: 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 QDate applyToDate(const QDate &date, QCalendar cal = QCalendar()) const = 0; + virtual void setDate(const QDate &date, QCalendar cal = QCalendar()) = 0; virtual QString text() const = 0; - virtual QString text(const QDate &date, int repeat) const = 0; + virtual QString text(const QDate &date, QCalendar cal, int repeat) const = 0; QLocale m_locale; protected: static QString highlightString(const QString &str, int pos); -private: }; QString QCalendarDateSectionValidator::highlightString(const QString &str, int pos) @@ -117,10 +117,10 @@ class QCalendarDayValidator : public QCalendarDateSectionValidator public: QCalendarDayValidator(); virtual Section handleKey(int key) override; - virtual QDate applyToDate(const QDate &date) const override; - virtual void setDate(const QDate &date) override; + virtual QDate applyToDate(const QDate &date, QCalendar cal) const override; + virtual void setDate(const QDate &date, QCalendar cal) override; virtual QString text() const override; - virtual QString text(const QDate &date, int repeat) const override; + virtual QString text(const QDate &date, QCalendar cal, int repeat) const override; private: int m_pos; int m_day; @@ -181,21 +181,18 @@ QCalendarDateSectionValidator::Section QCalendarDayValidator::handleKey(int key) return QCalendarDateSectionValidator::ThisSection; } -QDate QCalendarDayValidator::applyToDate(const QDate &date) const +QDate QCalendarDayValidator::applyToDate(const QDate &date, QCalendar cal) 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); + auto parts = cal.partsFromDate(date); + if (!parts.isValid()) + return QDate(); + parts.day = qMin(qMax(1, m_day), cal.daysInMonth(parts.year, parts.month)); + return cal.dateFromParts(parts); } -void QCalendarDayValidator::setDate(const QDate &date) +void QCalendarDayValidator::setDate(const QDate &date, QCalendar cal) { - m_day = m_oldDay = date.day(); + m_day = m_oldDay = date.day(cal); m_pos = 0; } @@ -204,16 +201,16 @@ QString QCalendarDayValidator::text() const return highlightString(formatNumber(m_day, 2), m_pos); } -QString QCalendarDayValidator::text(const QDate &date, int repeat) const +QString QCalendarDayValidator::text(const QDate &date, QCalendar cal, int repeat) const { if (repeat <= 1) { - return QString::number(date.day()); + return QString::number(date.day(cal)); } else if (repeat == 2) { - return formatNumber(date.day(), 2); + return formatNumber(date.day(cal), 2); } else if (repeat == 3) { - return m_locale.dayName(date.dayOfWeek(), QLocale::ShortFormat); + return m_locale.dayName(date.dayOfWeek(cal), QLocale::ShortFormat); } else /* repeat >= 4 */ { - return m_locale.dayName(date.dayOfWeek(), QLocale::LongFormat); + return m_locale.dayName(date.dayOfWeek(cal), QLocale::LongFormat); } } @@ -225,10 +222,10 @@ class QCalendarMonthValidator : public QCalendarDateSectionValidator public: QCalendarMonthValidator(); virtual Section handleKey(int key) override; - virtual QDate applyToDate(const QDate &date) const override; - virtual void setDate(const QDate &date) override; + virtual QDate applyToDate(const QDate &date, QCalendar cal) const override; + virtual void setDate(const QDate &date, QCalendar cal) override; virtual QString text() const override; - virtual QString text(const QDate &date, int repeat) const override; + virtual QString text(const QDate &date, QCalendar cal, int repeat) const override; private: int m_pos; int m_month; @@ -289,23 +286,19 @@ QCalendarDateSectionValidator::Section QCalendarMonthValidator::handleKey(int ke return QCalendarDateSectionValidator::ThisSection; } -QDate QCalendarMonthValidator::applyToDate(const QDate &date) const +QDate QCalendarMonthValidator::applyToDate(const QDate &date, QCalendar cal) 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); + auto parts = cal.partsFromDate(date); + if (!parts.isValid()) + return QDate(); + parts.month = qMin(qMax(1, m_month), cal.monthsInYear(parts.year)); + parts.day = qMin(parts.day, cal.daysInMonth(parts.year, m_month)); // m_month or parts.month ? + return cal.dateFromParts(parts); } -void QCalendarMonthValidator::setDate(const QDate &date) +void QCalendarMonthValidator::setDate(const QDate &date, QCalendar cal) { - m_month = m_oldMonth = date.month(); + m_month = m_oldMonth = date.month(cal); m_pos = 0; } @@ -314,16 +307,16 @@ QString QCalendarMonthValidator::text() const return highlightString(formatNumber(m_month, 2), m_pos); } -QString QCalendarMonthValidator::text(const QDate &date, int repeat) const +QString QCalendarMonthValidator::text(const QDate &date, QCalendar cal, int repeat) const { if (repeat <= 1) { - return QString::number(date.month()); + return QString::number(date.month(cal)); } else if (repeat == 2) { - return formatNumber(date.month(), 2); + return formatNumber(date.month(cal), 2); } else if (repeat == 3) { - return m_locale.standaloneMonthName(date.month(), QLocale::ShortFormat); + return cal.standaloneMonthName(m_locale, date.month(cal), QLocale::ShortFormat); } else /*if (repeat >= 4)*/ { - return m_locale.standaloneMonthName(date.month(), QLocale::LongFormat); + return cal.standaloneMonthName(m_locale, date.month(cal), QLocale::LongFormat); } } @@ -335,10 +328,10 @@ class QCalendarYearValidator : public QCalendarDateSectionValidator public: QCalendarYearValidator(); virtual Section handleKey(int key) override; - virtual QDate applyToDate(const QDate &date) const override; - virtual void setDate(const QDate &date) override; + virtual QDate applyToDate(const QDate &date, QCalendar cal) const override; + virtual void setDate(const QDate &date, QCalendar cal) override; virtual QString text() const override; - virtual QString text(const QDate &date, int repeat) const override; + virtual QString text(const QDate &date, QCalendar cal, int repeat) const override; private: int pow10(int n); int m_pos; @@ -349,6 +342,8 @@ private: QCalendarYearValidator::QCalendarYearValidator() : QCalendarDateSectionValidator(), m_pos(0), m_year(2000), m_oldYear(2000) { + // TODO: What to use (for non-Gregorian calendars) as default year? + // Maybe 1360 for Jalali, 1420 for Islamic, etc. } int QCalendarYearValidator::pow10(int n) @@ -397,21 +392,20 @@ QCalendarDateSectionValidator::Section QCalendarYearValidator::handleKey(int key return QCalendarDateSectionValidator::ThisSection; } -QDate QCalendarYearValidator::applyToDate(const QDate &date) const +QDate QCalendarYearValidator::applyToDate(const QDate &date, QCalendar cal) 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); + auto parts = cal.partsFromDate(date); + if (!parts.isValid()) + return QDate(); + // This widget does not support negative years (some calendars may support) + parts.year = qMax(1, m_year); + parts.day = qMin(parts.day, cal.daysInMonth(parts.year, parts.month)); + return cal.dateFromParts(parts); } -void QCalendarYearValidator::setDate(const QDate &date) +void QCalendarYearValidator::setDate(const QDate &date, QCalendar cal) { - m_year = m_oldYear = date.year(); + m_year = m_oldYear = date.year(cal); m_pos = 0; } @@ -420,11 +414,11 @@ QString QCalendarYearValidator::text() const return highlightString(formatNumber(m_year, 4), m_pos); } -QString QCalendarYearValidator::text(const QDate &date, int repeat) const +QString QCalendarYearValidator::text(const QDate &date, QCalendar cal, int repeat) const { if (repeat < 4) - return formatNumber(date.year() % 100, 2); - return QString::number(date.year()); + return formatNumber(date.year(cal) % 100, 2); + return QString::number(date.year(cal)); } /////////////////////////////////// @@ -446,18 +440,18 @@ public: QCalendarDateValidator(); ~QCalendarDateValidator(); - void handleKeyEvent(QKeyEvent *keyEvent); - QString currentText() const; + void handleKeyEvent(QKeyEvent *keyEvent, QCalendar cal); + QString currentText(QCalendar cal) const; QDate currentDate() const { return m_currentDate; } void setFormat(const QString &format); - void setInitialDate(const QDate &date); + void setInitialDate(const QDate &date, QCalendar cal); void setLocale(const QLocale &locale); private: void toNextToken(); void toPreviousToken(); - void applyToDate(); + void applyToDate(QCalendar cal); int countRepeat(const QString &str, int index) const; void clear(); @@ -507,17 +501,17 @@ int QCalendarDateValidator::countRepeat(const QString &str, int index) const return count; } -void QCalendarDateValidator::setInitialDate(const QDate &date) +void QCalendarDateValidator::setInitialDate(const QDate &date, QCalendar cal) { - m_yearValidator.setDate(date); - m_monthValidator.setDate(date); - m_dayValidator.setDate(date); + m_yearValidator.setDate(date, cal); + m_monthValidator.setDate(date, cal); + m_dayValidator.setDate(date, cal); m_initialDate = date; m_currentDate = date; m_lastSectionMove = QCalendarDateSectionValidator::ThisSection; } -QString QCalendarDateValidator::currentText() const +QString QCalendarDateValidator::currentText(QCalendar cal) const { QString str; const int numSeps = m_separators.size(); @@ -529,7 +523,7 @@ QString QCalendarDateValidator::currentText() const if (i == m_currentToken) str += token.validator->text(); else - str += token.validator->text(m_currentDate, token.repeat); + str += token.validator->text(m_currentDate, cal, token.repeat); } } return str; @@ -591,11 +585,11 @@ void QCalendarDateValidator::setFormat(const QString &format) m_separators += separator; } -void QCalendarDateValidator::applyToDate() +void QCalendarDateValidator::applyToDate(QCalendar cal) { - m_currentDate = m_yearValidator.applyToDate(m_currentDate); - m_currentDate = m_monthValidator.applyToDate(m_currentDate); - m_currentDate = m_dayValidator.applyToDate(m_currentDate); + m_currentDate = m_yearValidator.applyToDate(m_currentDate, cal); + m_currentDate = m_monthValidator.applyToDate(m_currentDate, cal); + m_currentDate = m_dayValidator.applyToDate(m_currentDate, cal); } void QCalendarDateValidator::toNextToken() @@ -614,7 +608,7 @@ void QCalendarDateValidator::toPreviousToken() m_currentToken %= m_tokens.size(); } -void QCalendarDateValidator::handleKeyEvent(QKeyEvent *keyEvent) +void QCalendarDateValidator::handleKeyEvent(QKeyEvent *keyEvent,QCalendar cal) { if (m_currentToken < 0) return; @@ -631,7 +625,7 @@ void QCalendarDateValidator::handleKeyEvent(QKeyEvent *keyEvent) m_lastSectionMove = m_tokens[m_currentToken].validator->handleKey(key); - applyToDate(); + applyToDate(cal); if (m_lastSectionMove == QCalendarDateSectionValidator::NextSection) toNextToken(); else if (m_lastSectionMove == QCalendarDateSectionValidator::PrevSection) @@ -645,7 +639,8 @@ class QCalendarTextNavigator: public QObject Q_OBJECT public: QCalendarTextNavigator(QObject *parent = 0) - : QObject(parent), m_dateText(0), m_dateFrame(0), m_dateValidator(0), m_widget(0), m_editDelay(1500), m_date(QDate::currentDate()) { } + : QObject(parent), m_dateText(0), m_dateFrame(0), m_dateValidator(0), + m_widget(0), m_editDelay(1500), m_date(QDate::currentDate()) {} QWidget *widget() const; void setWidget(QWidget *widget); @@ -676,6 +671,7 @@ private: int m_editDelay; QDate m_date; + const QCalendar m_calendar; }; QWidget *QCalendarTextNavigator::widget() const @@ -700,7 +696,7 @@ void QCalendarTextNavigator::updateDateLabel() m_acceptTimer.start(m_editDelay, this); - m_dateText->setText(m_dateValidator->currentText()); + m_dateText->setText(m_dateValidator->currentText(m_calendar)); QSize s = m_dateFrame->sizeHint(); QRect r = m_widget->geometry(); // later, just the table section @@ -740,7 +736,7 @@ void QCalendarTextNavigator::createDateLabel() 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_dateValidator->setInitialDate(m_date, m_calendar); m_dateFrame->setAutoFillBackground(true); m_dateFrame->setBackgroundRole(QPalette::Window); @@ -775,7 +771,7 @@ bool QCalendarTextNavigator::eventFilter(QObject *o, QEvent *e) #endif } else if (e->type() == QEvent::KeyPress) { createDateLabel(); - m_dateValidator->handleKeyEvent(ke); + m_dateValidator->handleKeyEvent(ke, m_calendar); updateDateLabel(); } ke->accept(); @@ -897,6 +893,9 @@ public: void showMonth(int year, int month); void setDate(const QDate &d); + void setCalendar(QCalendar c); + QCalendar calendar() const; + void setMinimumDate(const QDate &date); void setMaximumDate(const QDate &date); @@ -926,6 +925,7 @@ public: int m_firstColumn; int m_firstRow; + QCalendar m_calendar; QDate m_date; QDate m_minimumDate; QDate m_maximumDate; @@ -984,8 +984,8 @@ QCalendarModel::QCalendarModel(QObject *parent) m_date(QDate::currentDate()), m_minimumDate(QDate::fromJulianDay(1)), m_maximumDate(9999, 12, 31), - m_shownYear(m_date.year()), - m_shownMonth(m_date.month()), + m_shownYear(m_date.year(m_calendar)), + m_shownMonth(m_date.month(m_calendar)), m_firstDay(QLocale().firstDayOfWeek()), m_horizontalHeaderFormat(QCalendarWidget::ShortDayNames), m_weekNumbersShown(true), @@ -1028,9 +1028,10 @@ will be rendered in 2nd or 3rd row, showing more dates from previous month. */ QDate QCalendarModel::referenceDate() const { + // TODO: Check this int refDay = 1; while (refDay <= 31) { - QDate refDate(m_shownYear, m_shownMonth, refDay); + QDate refDate(m_shownYear, m_shownMonth, refDay, m_calendar); if (refDate.isValid()) return refDate; refDay += 1; @@ -1040,7 +1041,8 @@ QDate QCalendarModel::referenceDate() const int QCalendarModel::columnForFirstOfMonth(const QDate &date) const { - return (columnForDayOfWeek(static_cast(date.dayOfWeek())) - (date.day() % 7) + 8) % 7; + return (columnForDayOfWeek(static_cast(m_calendar.dayOfWeek(date))) + - (date.day(m_calendar) % 7) + 8) % 7; } QDate QCalendarModel::dateForCell(int row, int column) const @@ -1056,7 +1058,8 @@ QDate QCalendarModel::dateForCell(int row, int column) const if (columnForFirstOfShownMonth - m_firstColumn < MinimumDayOffset) row -= 1; - const int requestedDay = 7 * (row - m_firstRow) + column - columnForFirstOfShownMonth - refDate.day() + 1; + const int requestedDay = + 7 * (row - m_firstRow) + column - columnForFirstOfShownMonth - refDate.day(m_calendar) + 1; return refDate.addDays(requestedDay); } @@ -1075,7 +1078,8 @@ void QCalendarModel::cellForDate(const QDate &date, int *row, int *column) const return; const int columnForFirstOfShownMonth = columnForFirstOfMonth(refDate); - const int requestedPosition = refDate.daysTo(date) - m_firstColumn + columnForFirstOfShownMonth + refDate.day() - 1; + const int requestedPosition = (refDate.daysTo(date) - m_firstColumn + + columnForFirstOfShownMonth + refDate.day(m_calendar) - 1); int c = requestedPosition % 7; int r = requestedPosition / 7; @@ -1148,7 +1152,7 @@ QTextCharFormat QCalendarModel::formatForCell(int row, int col) const 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()) + if (m_shownMonth != date.month(m_calendar)) format.setForeground(pal.brush(QPalette::Disabled, QPalette::Text)); } return format; @@ -1174,7 +1178,7 @@ QVariant QCalendarModel::data(const QModelIndex &index, int role) const return dayName(dayOfWeekForColumn(column)); QDate date = dateForCell(row, column); if (date.isValid()) - return date.day(); + return date.day(m_calendar); return QString(); } @@ -1211,6 +1215,20 @@ void QCalendarModel::setDate(const QDate &d) m_date = m_maximumDate; } +void QCalendarModel::setCalendar(QCalendar c) +{ + m_calendar = c; + m_shownYear = m_date.year(c); + m_shownMonth = m_date.month(c); + internalUpdate(); + m_view->internalUpdate(); +} + +QCalendar QCalendarModel::calendar() const +{ + return m_calendar; +} + void QCalendarModel::showMonth(int year, int month) { if (m_shownYear == year && m_shownMonth == month) @@ -1341,6 +1359,8 @@ QModelIndex QCalendarView::moveCursor(CursorAction cursorAction, Qt::KeyboardMod if (!calendarModel) return QTableView::moveCursor(cursorAction, modifiers); + QCalendar cal = calendarModel->calendar(); + if (readOnly) return currentIndex(); @@ -1359,17 +1379,27 @@ QModelIndex QCalendarView::moveCursor(CursorAction cursorAction, Qt::KeyboardMod case QAbstractItemView::MoveRight: currentDate = currentDate.addDays(isRightToLeft() ? -1 : 1); break; - case QAbstractItemView::MoveHome: - currentDate = QDate(currentDate.year(), currentDate.month(), 1); + case QAbstractItemView::MoveHome: { + auto parts = cal.partsFromDate(currentDate); + if (parts.isValid()) { + parts.day = 1; + currentDate = cal.dateFromParts(parts); + } + } break; - case QAbstractItemView::MoveEnd: - currentDate = QDate(currentDate.year(), currentDate.month(), currentDate.daysInMonth()); + case QAbstractItemView::MoveEnd: { + auto parts = cal.partsFromDate(currentDate); + if (parts.isValid()) { + parts.day = cal.daysInMonth(parts.year, parts.month); + currentDate = cal.dateFromParts(parts); + } + } break; case QAbstractItemView::MovePageUp: - currentDate = currentDate.addMonths(-1); + currentDate = currentDate.addMonths(-1, cal); break; case QAbstractItemView::MovePageDown: - currentDate = currentDate.addMonths(1); + currentDate = currentDate.addMonths(1, cal); break; case QAbstractItemView::MoveNext: case QAbstractItemView::MovePrevious: @@ -1422,8 +1452,9 @@ void QCalendarView::wheelEvent(QWheelEvent *event) const int numDegrees = event->angleDelta().y() / 8; const int numSteps = numDegrees / 15; const QModelIndex index = currentIndex(); - QDate currentDate = static_cast(model())->dateForCell(index.row(), index.column()); - currentDate = currentDate.addMonths(-numSteps); + QCalendarModel *calendarModel = static_cast(model()); + QDate currentDate = calendarModel->dateForCell(index.row(), index.column()); + currentDate = currentDate.addMonths(-numSteps, calendarModel->calendar()); emit showDate(currentDate); } #endif @@ -1756,7 +1787,7 @@ void QCalendarWidgetPrivate::createNavigationBar(QWidget *widget) monthButton->setPopupMode(QToolButton::InstantPopup); monthMenu = new QMenu(monthButton); for (int i = 1; i <= 12; i++) { - QString monthName(q->locale().standaloneMonthName(i, QLocale::LongFormat)); + QString monthName(m_model->m_calendar.standaloneMonthName(q->locale(), i, QLocale::LongFormat)); QAction *act = monthMenu->addAction(monthName); act->setData(i); monthToAction[i] = act; @@ -1772,8 +1803,8 @@ void QCalendarWidgetPrivate::createNavigationBar(QWidget *widget) monthButton->setFont(font); yearButton->setFont(font); yearEdit->setFrame(false); - yearEdit->setMinimum(m_model->m_minimumDate.year()); - yearEdit->setMaximum(m_model->m_maximumDate.year()); + yearEdit->setMinimum(m_model->m_minimumDate.year(m_model->m_calendar)); + yearEdit->setMaximum(m_model->m_maximumDate.year(m_model->m_calendar)); yearEdit->hide(); spaceHolder = new QSpacerItem(0,0); @@ -1803,7 +1834,7 @@ void QCalendarWidgetPrivate::createNavigationBar(QWidget *widget) yearEdit->setObjectName(QLatin1String("qt_calendar_yearedit")); updateMonthMenu(); - showMonth(m_model->m_date.year(), m_model->m_date.month()); + showMonth(m_model->m_date.year(m_model->m_calendar), m_model->m_date.month(m_model->m_calendar)); } void QCalendarWidgetPrivate::updateButtonIcons() @@ -1815,22 +1846,24 @@ void QCalendarWidgetPrivate::updateButtonIcons() void QCalendarWidgetPrivate::updateMonthMenu() { - int beg = 1, end = 12; + int maxMonths = m_model->m_calendar.monthsInYear(m_model->m_shownYear); + int beg = 1, end = maxMonths; 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()) + QCalendar cal = m_model->calendar(); + if (m_model->m_shownYear == m_model->m_minimumDate.year(cal)) { + beg = m_model->m_minimumDate.month(cal); + if (m_model->m_shownMonth == m_model->m_minimumDate.month(cal)) 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()) + if (m_model->m_shownYear == m_model->m_maximumDate.year(cal)) { + end = m_model->m_maximumDate.month(cal); + if (m_model->m_shownMonth == m_model->m_maximumDate.month(cal)) nextEnabled = false; } prevMonth->setEnabled(prevEnabled); nextMonth->setEnabled(nextEnabled); - for (int i = 1; i <= 12; i++) { + for (int i = 1; i <= maxMonths; i++) { bool monthEnabled = true; if (i < beg || i > end) monthEnabled = false; @@ -1843,7 +1876,7 @@ void QCalendarWidgetPrivate::updateMonthMenuNames() Q_Q(QCalendarWidget); for (int i = 1; i <= 12; i++) { - QString monthName(q->locale().standaloneMonthName(i, QLocale::LongFormat)); + QString monthName(m_model->m_calendar.standaloneMonthName(q->locale(), i, QLocale::LongFormat)); monthToAction[i]->setText(monthName); } } @@ -1851,6 +1884,7 @@ void QCalendarWidgetPrivate::updateMonthMenuNames() void QCalendarWidgetPrivate::updateCurrentPage(const QDate &date) { Q_Q(QCalendarWidget); + QCalendar cal = m_model->calendar(); QDate newDate = date; QDate minDate = q->minimumDate(); @@ -1859,7 +1893,7 @@ void QCalendarWidgetPrivate::updateCurrentPage(const QDate &date) newDate = minDate; if (maxDate.isValid()&& maxDate.daysTo(newDate) > 0) newDate = maxDate; - showMonth(newDate.year(), newDate.month()); + showMonth(newDate.year(cal), newDate.month(cal)); int row = -1, col = -1; m_model->cellForDate(newDate, &row, &col); if (row != -1 && col != -1) @@ -1873,7 +1907,7 @@ void QCalendarWidgetPrivate::_q_monthChanged(QAction *act) { monthButton->setText(act->text()); QDate currentDate = getCurrentDate(); - QDate newDate = currentDate.addMonths(act->data().toInt()-currentDate.month()); + QDate newDate = currentDate.addMonths(act->data().toInt() - currentDate.month(m_model->m_calendar), m_model->m_calendar); updateCurrentPage(newDate); } @@ -1885,27 +1919,28 @@ QDate QCalendarWidgetPrivate::getCurrentDate() void QCalendarWidgetPrivate::_q_prevMonthClicked() { - QDate currentDate = getCurrentDate().addMonths(-1); + QDate currentDate = getCurrentDate().addMonths(-1, m_model->m_calendar); updateCurrentPage(currentDate); } void QCalendarWidgetPrivate::_q_nextMonthClicked() { - QDate currentDate = getCurrentDate().addMonths(1); + QDate currentDate = getCurrentDate().addMonths(1, m_model->m_calendar); updateCurrentPage(currentDate); } void QCalendarWidgetPrivate::_q_yearEditingFinished() { Q_Q(QCalendarWidget); - yearButton->setText(yearEdit->text()); + yearButton->setText(q->locale().toString(yearEdit->value())); 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()); + int newYear = q->locale().toInt(yearEdit->text()); + currentDate = currentDate.addYears(newYear - currentDate.year(m_model->m_calendar), m_model->m_calendar); updateCurrentPage(currentDate); } @@ -1944,7 +1979,7 @@ void QCalendarWidgetPrivate::updateNavigationBar() { Q_Q(QCalendarWidget); - QString monthName = q->locale().standaloneMonthName(m_model->m_shownMonth, QLocale::LongFormat); + QString monthName = m_model->m_calendar.standaloneMonthName(q->locale(), m_model->m_shownMonth, QLocale::LongFormat); monthButton->setText(monthName); yearEdit->setValue(m_model->m_shownYear); @@ -1986,7 +2021,7 @@ void QCalendarWidgetPrivate::_q_slotChangeDate(const QDate &date, bool changeMon m_model->setDate(date); QDate newDate = m_model->m_date; if (changeMonth) - showMonth(newDate.year(), newDate.month()); + showMonth(newDate.year(m_model->m_calendar), newDate.month(m_model->m_calendar)); if (oldDate != newDate) { update(); Q_Q(QCalendarWidget); @@ -2242,7 +2277,7 @@ QSize QCalendarWidget::minimumSizeHint() const QFontMetrics fm = d->monthButton->fontMetrics(); int monthW = 0; for (int i = 1; i < 12; i++) { - QString monthName = locale().standaloneMonthName(i, QLocale::LongFormat); + QString monthName = d->m_model->m_calendar.standaloneMonthName(locale(), i, QLocale::LongFormat); monthW = qMax(monthW, fm.boundingRect(monthName).width()); } const int buttonDecoMargin = d->monthButton->sizeHint().width() - fm.boundingRect(d->monthButton->text()).width(); @@ -2302,7 +2337,8 @@ void QCalendarWidget::setSelectedDate(const QDate &date) d->m_model->setDate(date); d->update(); QDate newDate = d->m_model->m_date; - d->showMonth(newDate.year(), newDate.month()); + QCalendar cal = d->m_model->m_calendar; + d->showMonth(newDate.year(cal), newDate.month(cal)); emit selectionChanged(); } @@ -2348,14 +2384,15 @@ 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(); + QCalendar cal = d->m_model->m_calendar; + int day = currentDate.day(cal); + int daysInMonths = cal.daysInMonth(year, month); if (day > daysInMonths) day = daysInMonths; d->showMonth(year, month); - QDate newDate(year, month, day); + QDate newDate(year, month, day, d->m_model->m_calendar); int row = -1, col = -1; d->m_model->cellForDate(newDate, &row, &col); if (row != -1 && col != -1) { @@ -2373,9 +2410,10 @@ void QCalendarWidget::setCurrentPage(int year, int month) void QCalendarWidget::showNextMonth() { + Q_D(const QCalendarWidget); int year = yearShown(); int month = monthShown(); - if (month == 12) { + if (month == d->m_model->m_calendar.maxMonthsInYear()) { ++year; month = 1; } else { @@ -2393,11 +2431,13 @@ void QCalendarWidget::showNextMonth() void QCalendarWidget::showPreviousMonth() { + Q_D(const QCalendarWidget); + int year = yearShown(); int month = monthShown(); if (month == 1) { --year; - month = 12; + month = d->m_model->m_calendar.maxMonthsInYear(); } else { --month; } @@ -2443,8 +2483,10 @@ void QCalendarWidget::showPreviousYear() */ void QCalendarWidget::showSelectedDate() { + Q_D(const QCalendarWidget); + QDate currentDate = selectedDate(); - setCurrentPage(currentDate.year(), currentDate.month()); + setCurrentPage(currentDate.year(d->m_model->m_calendar), currentDate.month(d->m_model->m_calendar)); } /*! @@ -2454,8 +2496,10 @@ void QCalendarWidget::showSelectedDate() */ void QCalendarWidget::showToday() { + Q_D(const QCalendarWidget); + QDate currentDate = QDate::currentDate(); - setCurrentPage(currentDate.year(), currentDate.month()); + setCurrentPage(currentDate.year(d->m_model->m_calendar), currentDate.month(d->m_model->m_calendar)); } /*! @@ -2498,12 +2542,12 @@ void QCalendarWidget::setMinimumDate(const QDate &date) QDate oldDate = d->m_model->m_date; d->m_model->setMinimumDate(date); - d->yearEdit->setMinimum(d->m_model->m_minimumDate.year()); + d->yearEdit->setMinimum(d->m_model->m_minimumDate.year(d->m_model->m_calendar)); d->updateMonthMenu(); QDate newDate = d->m_model->m_date; if (oldDate != newDate) { d->update(); - d->showMonth(newDate.year(), newDate.month()); + d->showMonth(newDate.year(d->m_model->m_calendar), newDate.month(d->m_model->m_calendar)); d->m_navigator->setDate(newDate); emit selectionChanged(); } @@ -2549,12 +2593,12 @@ void QCalendarWidget::setMaximumDate(const QDate &date) QDate oldDate = d->m_model->m_date; d->m_model->setMaximumDate(date); - d->yearEdit->setMaximum(d->m_model->m_maximumDate.year()); + d->yearEdit->setMaximum(d->m_model->m_maximumDate.year(d->m_model->m_calendar)); d->updateMonthMenu(); QDate newDate = d->m_model->m_date; if (oldDate != newDate) { d->update(); - d->showMonth(newDate.year(), newDate.month()); + d->showMonth(newDate.year(d->m_model->m_calendar), newDate.month(d->m_model->m_calendar)); d->m_navigator->setDate(newDate); emit selectionChanged(); } @@ -2589,13 +2633,13 @@ void QCalendarWidget::setDateRange(const QDate &min, const QDate &max) 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->yearEdit->setMinimum(d->m_model->m_minimumDate.year(d->m_model->m_calendar)); + d->yearEdit->setMaximum(d->m_model->m_maximumDate.year(d->m_model->m_calendar)); d->updateMonthMenu(); QDate newDate = d->m_model->m_date; if (oldDate != newDate) { d->update(); - d->showMonth(newDate.year(), newDate.month()); + d->showMonth(newDate.year(d->m_model->m_calendar), newDate.month(d->m_model->m_calendar)); d->m_navigator->setDate(newDate); emit selectionChanged(); } @@ -2702,6 +2746,22 @@ bool QCalendarWidget::isGridVisible() const return d->m_view->showGrid(); } +QCalendar QCalendarWidget::calendar() const +{ + Q_D(const QCalendarWidget); + return d->m_model->m_calendar; +} + +void QCalendarWidget::setCalendar(QCalendar c) +{ + Q_D(QCalendarWidget); + d->m_model->setCalendar(c); + d->updateMonthMenuNames(); + d->yearEdit->setMinimum(d->m_model->m_minimumDate.year(d->m_model->m_calendar)); + d->yearEdit->setMaximum(d->m_model->m_maximumDate.year(d->m_model->m_calendar)); + d->updateNavigationBar(); +} + void QCalendarWidget::setGridVisible(bool show) { Q_D(QCalendarWidget); @@ -3042,6 +3102,9 @@ bool QCalendarWidget::event(QEvent *event) d->updateMonthMenuNames(); d->updateNavigationBar(); d->m_view->updateGeometry(); + // TODO: fix this known bug of calendaring API: + // Changing locale before calendar works, but reverse order causes + // invalid month names (in C Locale apparently). break; case QEvent::FontChange: case QEvent::ApplicationFontChange: -- cgit v1.2.3