Improve keyboard navigation in calendar

This commit is contained in:
Eric Kotato 2020-08-03 09:25:19 +03:00
parent d8ea4c933e
commit fcd1495f6b

View file

@ -45,6 +45,7 @@ public:
void skipMonth(int skip); void skipMonth(int skip);
void showMonth(QDate month); void showMonth(QDate month);
void skipDays(int skip);
int highlightedIndex() const { int highlightedIndex() const {
return _highlightedIndex; return _highlightedIndex;
@ -64,6 +65,9 @@ public:
bool atBeginning() const { bool atBeginning() const {
return _highlighted == _min; return _highlighted == _min;
} }
QDate highlighted() const {
return _highlighted;
}
const base::Variable<QDate> &month() { const base::Variable<QDate> &month() {
return _month; return _month;
@ -77,6 +81,7 @@ private:
static int daysShiftForMonth(QDate month); static int daysShiftForMonth(QDate month);
static int rowsCountForMonth(QDate month); static int rowsCountForMonth(QDate month);
void setHighlightedDate(QDate highlighted);
bool _beginningButton = false; bool _beginningButton = false;
@ -147,6 +152,36 @@ void CalendarBox::Context::skipMonth(int skip) {
showMonth(QDate(year, month, 1)); showMonth(QDate(year, month, 1));
} }
void CalendarBox::Context::skipDays(int skip) {
auto date = _highlighted;
if (_month.value().month() == _highlighted.month()
&& _month.value().year() == _highlighted.year()) {
date = date.addDays(skip);
} else if (skip < 0) {
date = QDate(
_month.value().year(),
_month.value().month(),
_month.value().daysInMonth());
} else {
date = QDate(
_month.value().year(),
_month.value().month(),
1);
}
if (date.isValid() && date >= _min && date <= _max) {
auto needMonthChange = (date.month() != _highlighted.month()
|| date.year() != _highlighted.year());
setHighlightedDate(date);
if (needMonthChange) {
showMonth(date);
}
}
}
int CalendarBox::Context::daysShiftForMonth(QDate month) { int CalendarBox::Context::daysShiftForMonth(QDate month) {
Assert(!month.isNull()); Assert(!month.isNull());
constexpr auto kMaxRows = 6; constexpr auto kMaxRows = 6;
@ -165,6 +200,12 @@ int CalendarBox::Context::rowsCountForMonth(QDate month) {
return result; return result;
} }
void CalendarBox::Context::setHighlightedDate(QDate highlighted) {
_highlighted = highlighted;
_highlightedIndex = _month.value().daysTo(_highlighted);
applyMonth(_month.value(), true);
}
QDate CalendarBox::Context::dateFromIndex(int index) const { QDate CalendarBox::Context::dateFromIndex(int index) const {
constexpr auto kMonthsCount = 12; constexpr auto kMonthsCount = 12;
auto month = _month.value().month(); auto month = _month.value().month();
@ -207,6 +248,7 @@ public:
void setDateChosenCallback(Fn<void(QDate)> callback); void setDateChosenCallback(Fn<void(QDate)> callback);
void selectBeginning(); void selectBeginning();
void selectEnd(); void selectEnd();
void selectHighlighted();
~Inner(); ~Inner();
@ -442,6 +484,10 @@ void CalendarBox::Inner::selectEnd() {
_dateChosenCallback(_context->dateFromIndex(_context->maxDayIndex())); _dateChosenCallback(_context->dateFromIndex(_context->maxDayIndex()));
} }
void CalendarBox::Inner::selectHighlighted() {
_dateChosenCallback(_context->highlighted());
}
CalendarBox::Inner::~Inner() = default; CalendarBox::Inner::~Inner() = default;
class CalendarBox::Title : public TWidget, private base::Subscriber { class CalendarBox::Title : public TWidget, private base::Subscriber {
@ -595,10 +641,20 @@ void CalendarBox::keyPressEvent(QKeyEvent *e) {
_inner->selectBeginning(); _inner->selectBeginning();
} else if (e->key() == Qt::Key_End) { } else if (e->key() == Qt::Key_End) {
_inner->selectEnd(); _inner->selectEnd();
} else if (e->key() == Qt::Key_Left) { } else if (e->key() == Qt::Key_PageUp) {
goPreviousMonth(); goPreviousMonth();
} else if (e->key() == Qt::Key_Right) { } else if (e->key() == Qt::Key_PageDown) {
goNextMonth(); goNextMonth();
} else if (e->key() == Qt::Key_Left) {
_context->skipDays(-1);
} else if (e->key() == Qt::Key_Right) {
_context->skipDays(1);
} else if (e->key() == Qt::Key_Up) {
_context->skipDays(-7);
} else if (e->key() == Qt::Key_Down) {
_context->skipDays(7);
} else if (e->key() == Qt::Key_Return || e->key() == Qt::Key_Enter) {
_inner->selectHighlighted();
} }
} }