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 <edward.welbourne@qt.io>
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
bb10
Soroush Rabiei 2019-08-08 15:19:18 +02:00 committed by Edward Welbourne
parent 7026645712
commit 2dee006216
5 changed files with 242 additions and 158 deletions

View File

@ -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 <private/qapplication_p.h>
#include <qbasictimer.h>
#include <qstylepainter.h>
#include <qcalendar.h>
#include <vector>
@ -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<Qt::DayOfWeek>(date.dayOfWeek())) - (date.day() % 7) + 8) % 7;
return (columnForDayOfWeek(static_cast<Qt::DayOfWeek>(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<QCalendarModel*>(model())->dateForCell(index.row(), index.column());
currentDate = currentDate.addMonths(-numSteps);
QCalendarModel *calendarModel = static_cast<QCalendarModel*>(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:

View File

@ -1,6 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Copyright (C) 2018 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtWidgets module of the Qt Toolkit.
@ -112,6 +112,9 @@ public:
bool isNavigationBarVisible() const;
bool isGridVisible() const;
QCalendar calendar() const;
void setCalendar(QCalendar calendar);
SelectionMode selectionMode() const;
void setSelectionMode(SelectionMode mode);

View File

@ -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.
@ -312,6 +312,22 @@ void QDateTimeEdit::setTime(const QTime &time)
}
QCalendar QDateTimeEdit::calendar() const
{
Q_D(const QDateTimeEdit);
return d->calendar;
}
void QDateTimeEdit::setCalendar(QCalendar calendar)
{
Q_D(QDateTimeEdit);
// Set invalid date time to prevent runtime crashes on calendar change
QDateTime previousValue = d->value.toDateTime();
setDateTime(QDateTime());
d->setCalendar(calendar);
setDateTime(previousValue);
}
/*!
\property QDateTimeEdit::minimumDateTime
\since 4.4
@ -1344,7 +1360,7 @@ void QDateTimeEdit::stepBy(int steps)
QString QDateTimeEdit::textFromDateTime(const QDateTime &dateTime) const
{
Q_D(const QDateTimeEdit);
return locale().toString(dateTime, d->displayFormat);
return locale().toString(dateTime, d->displayFormat, d->calendar);
}
@ -1636,7 +1652,7 @@ QDateEdit::~QDateEdit()
QDateTimeEditPrivate::QDateTimeEditPrivate()
: QDateTimeParser(QVariant::DateTime, QDateTimeParser::DateTimeEdit)
: QDateTimeParser(QVariant::DateTime, QDateTimeParser::DateTimeEdit, QCalendar())
{
hasHadFocus = false;
formatExplicitlySet = false;
@ -1661,10 +1677,6 @@ QDateTimeEditPrivate::QDateTimeEditPrivate()
#endif
}
QDateTimeEditPrivate::~QDateTimeEditPrivate()
{
}
void QDateTimeEditPrivate::updateTimeSpec()
{
minimum = minimum.toDateTime().toTimeSpec(spec);
@ -2008,8 +2020,7 @@ QDateTime QDateTimeEditPrivate::stepBy(int sectionIndex, int steps, bool test) c
val = (wrapping ? min + val - max - 1 : max);
}
const int oldDay = v.date().day();
const int oldDay = v.date().day(calendar);
setDigit(v, sectionIndex, val);
// if this sets year or month it will make
@ -2028,10 +2039,10 @@ QDateTime QDateTimeEditPrivate::stepBy(int sectionIndex, int steps, bool test) c
if (steps > 0) {
setDigit(v, sectionIndex, min);
if (!(sn.type & DaySectionMask) && sections & DateSectionMask) {
const int daysInMonth = v.date().daysInMonth();
if (v.date().day() < oldDay && v.date().day() < daysInMonth) {
const int daysInMonth = v.date().daysInMonth(calendar);
if (v.date().day(calendar) < oldDay && v.date().day(calendar) < daysInMonth) {
const int adds = qMin(oldDay, daysInMonth);
v = v.addDays(adds - v.date().day());
v = v.addDays(adds - v.date().day(calendar));
}
}
@ -2043,10 +2054,10 @@ QDateTime QDateTimeEditPrivate::stepBy(int sectionIndex, int steps, bool test) c
} else {
setDigit(v, sectionIndex, max);
if (!(sn.type & DaySectionMask) && sections & DateSectionMask) {
const int daysInMonth = v.date().daysInMonth();
if (v.date().day() < oldDay && v.date().day() < daysInMonth) {
const int daysInMonth = v.date().daysInMonth(calendar);
if (v.date().day(calendar) < oldDay && v.date().day(calendar) < daysInMonth) {
const int adds = qMin(oldDay, daysInMonth);
v = v.addDays(adds - v.date().day());
v = v.addDays(adds - v.date().day(calendar));
}
}
@ -2060,7 +2071,7 @@ QDateTime QDateTimeEditPrivate::stepBy(int sectionIndex, int steps, bool test) c
setDigit(v, sectionIndex, (steps > 0 ? localmax : localmin));
}
}
if (!test && oldDay != v.date().day() && !(sn.type & DaySectionMask)) {
if (!test && oldDay != v.date().day(calendar) && !(sn.type & DaySectionMask)) {
// this should not happen when called from stepEnabled
cachedDay = qMax<int>(oldDay, cachedDay);
}
@ -2513,7 +2524,7 @@ void QDateTimeEditPrivate::initCalendarPopup(QCalendarWidget *cw)
{
Q_Q(QDateTimeEdit);
if (!monthCalendar) {
monthCalendar = new QCalendarPopup(q, cw);
monthCalendar = new QCalendarPopup(q, cw, calendar);
monthCalendar->setObjectName(QLatin1String("qt_datetimedit_calendar"));
QObject::connect(monthCalendar, SIGNAL(newDateSelected(QDate)), q, SLOT(setDate(QDate)));
QObject::connect(monthCalendar, SIGNAL(hidingCalendar(QDate)), q, SLOT(setDate(QDate)));
@ -2574,8 +2585,8 @@ void QDateTimeEditPrivate::syncCalendarWidget()
}
}
QCalendarPopup::QCalendarPopup(QWidget * parent, QCalendarWidget *cw)
: QWidget(parent, Qt::Popup)
QCalendarPopup::QCalendarPopup(QWidget *parent, QCalendarWidget *cw, QCalendar ca)
: QWidget(parent, Qt::Popup), calendarSystem(ca)
{
setAttribute(Qt::WA_WindowPropagation);
@ -2591,6 +2602,7 @@ QCalendarWidget *QCalendarPopup::verifyCalendarInstance()
{
if (calendar.isNull()) {
QCalendarWidget *cw = new QCalendarWidget(this);
cw->setCalendar(calendarSystem);
cw->setVerticalHeaderFormat(QCalendarWidget::NoVerticalHeader);
#ifdef QT_KEYPAD_NAVIGATION
if (QApplicationPrivate::keypadNavigationEnabled())

View File

@ -42,6 +42,7 @@
#include <QtWidgets/qtwidgetsglobal.h>
#include <QtCore/qdatetime.h>
#include <QtCore/qcalendar.h>
#include <QtCore/qvariant.h>
#include <QtWidgets/qabstractspinbox.h>
@ -102,6 +103,9 @@ public:
QDate date() const;
QTime time() const;
QCalendar calendar() const;
void setCalendar(QCalendar calendar);
QDateTime minimumDateTime() const;
void clearMinimumDateTime();
void setMinimumDateTime(const QDateTime &dt);

View File

@ -1,6 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Copyright (C) 2018 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtWidgets module of the Qt Toolkit.
@ -52,6 +52,7 @@
//
#include <QtWidgets/private/qtwidgetsglobal_p.h>
#include <QtCore/qcalendar.h>
#include "QtWidgets/qcalendarwidget.h"
#include "QtWidgets/qspinbox.h"
#include "QtWidgets/qtoolbutton.h"
@ -70,7 +71,6 @@ class Q_AUTOTEST_EXPORT QDateTimeEditPrivate : public QAbstractSpinBoxPrivate, p
Q_DECLARE_PUBLIC(QDateTimeEdit)
public:
QDateTimeEditPrivate();
~QDateTimeEditPrivate();
void init(const QVariant &var);
void readLocaleSettings();
@ -145,7 +145,8 @@ class QCalendarPopup : public QWidget
{
Q_OBJECT
public:
explicit QCalendarPopup(QWidget *parent = nullptr, QCalendarWidget *cw = nullptr);
explicit QCalendarPopup(QWidget *parent = nullptr, QCalendarWidget *cw = nullptr,
QCalendar ca = QCalendar());
QDate selectedDate() { return verifyCalendarInstance()->selectedDate(); }
void setDate(const QDate &date);
void setDateRange(const QDate &min, const QDate &max);
@ -174,6 +175,7 @@ private:
QPointer<QCalendarWidget> calendar;
QDate oldDate;
bool dateChanged;
QCalendar calendarSystem;
};
QT_END_NAMESPACE