12#include "kdatepicker.h"
13#include "kdatepicker_p.h"
15#include "common_helpers_p.h"
16#include "kdatetable_p.h"
17#include <kpopupframe.h>
19#include <QApplication>
22#include <QFontDatabase>
29#include "loggingcategory.h"
30#include "moc_kdatepicker.cpp"
31#include "moc_kdatepicker_p.cpp"
56 QStringLiteral(
"yyyy-MM-dd"),
60 for (
const auto &format : formats) {
67 qCDebug(KWidgetsAddonsLog) <<
"Could not parse text as date:" << text;
79KDatePickerPrivateYearSelector::KDatePickerPrivateYearSelector(
const QDate ¤tDate,
QWidget *parent)
83 , oldDate{currentDate}
97void KDatePickerPrivateYearSelector::yearEnteredSlot()
103 newYear = text().
toInt(&ok);
110 if (
QDate(newYear, oldDate.month(), oldDate.day()).
isValid()) {
118int KDatePickerPrivateYearSelector::year()
123void KDatePickerPrivateYearSelector::setYear(
const QDate &year)
125 setText(locale().
toString(year, QStringLiteral(
"yyyy")).rightJustified(4,
QLatin1Char(
'0')));
128class KDatePickerPrivate
138 void fillWeeksCombo();
139 QDate validDateInYearMonth(
int year,
int month);
164 DatePickerValidator *val =
nullptr;
166 KDateTable *table =
nullptr;
174void KDatePickerPrivate::fillWeeksCombo()
182 const QDate thisDate = q->date();
183 const int thisYear = thisDate.
year();
192 for (; day.isValid() && day <= lastDayOfYear; day = day.addDays(7)) {
195 int weekYear = thisYear;
196 const int week = day.weekNumber(&weekYear);
200 if (weekYear != thisYear) {
207 selectWeek->
addItem(weekString, targetDate);
211 if (day < lastDayOfYear
212 && day.daysTo(lastDayOfYear) < 7
213 && lastDayOfYear.
weekNumber() != day.weekNumber()) {
214 day = lastDayOfYear.
addDays(-7);
219QDate KDatePickerPrivate::validDateInYearMonth(
int year,
int month)
226 newDate =
QDate(year, month, 1);
238 , d(new KDatePickerPrivate(this))
245 , d(new KDatePickerPrivate(this))
250void KDatePicker::initWidget(
const QDate &date_)
259 d->navigationLayout->setSpacing(0);
260 d->navigationLayout->setContentsMargins(0, 0, 0, 0);
261 topLayout->
addLayout(d->navigationLayout);
262 d->navigationLayout->addStretch();
264 d->yearBackward->setAutoRaise(
true);
265 d->navigationLayout->addWidget(d->yearBackward);
267 d->monthBackward->setAutoRaise(
true);
268 d->navigationLayout->addWidget(d->monthBackward);
269 d->navigationLayout->addSpacing(horizontalSpacing);
272 d->selectMonth->setAutoRaise(
true);
273 d->navigationLayout->addWidget(d->selectMonth);
275 d->selectYear->setCheckable(
true);
276 d->selectYear->setAutoRaise(
true);
277 d->navigationLayout->addWidget(d->selectYear);
278 d->navigationLayout->addSpacing(horizontalSpacing);
281 d->monthForward->setAutoRaise(
true);
282 d->navigationLayout->addWidget(d->monthForward);
284 d->yearForward->setAutoRaise(
true);
285 d->navigationLayout->addWidget(d->yearForward);
286 d->navigationLayout->addStretch();
289 d->val =
new DatePickerValidator(
this);
290 d->table =
new KDateTable(
this);
294 if (d->fontsize == -1) {
305 d->yearForward->setToolTip(
tr(
"Next year",
"@info:tooltip"));
306 d->yearBackward->setToolTip(
tr(
"Previous year",
"@info:tooltip"));
307 d->monthForward->setToolTip(
tr(
"Next month",
"@info:tooltip"));
308 d->monthBackward->setToolTip(
tr(
"Previous month",
"@info:tooltip"));
309 d->selectWeek->setToolTip(
tr(
"Select a week",
"@info:tooltip"));
310 d->selectMonth->setToolTip(
tr(
"Select a month",
"@info:tooltip"));
311 d->selectYear->setToolTip(
tr(
"Select a year",
"@info:tooltip"));
312 d->todayButton->setToolTip(
tr(
"Select the current day",
"@info:tooltip"));
316 d->line->setValidator(d->val);
317 d->line->installEventFilter(
this);
319 d->yearForward->setIcon(
QIcon::fromTheme(QStringLiteral(
"arrow-left-double")));
320 d->yearBackward->setIcon(
QIcon::fromTheme(QStringLiteral(
"arrow-right-double")));
324 d->yearForward->setIcon(
QIcon::fromTheme(QStringLiteral(
"arrow-right-double")));
325 d->yearBackward->setIcon(
QIcon::fromTheme(QStringLiteral(
"arrow-left-double")));
330 connect(d->table, &KDateTable::dateChanged,
this, &KDatePicker::dateChangedSlot);
331 connect(d->table, &KDateTable::tableClicked,
this, &KDatePicker::tableClickedSlot);
353 d->table->setDate(date_);
354 dateChangedSlot(date_);
369 d->table->setFocus();
381void KDatePicker::dateChangedSlot(
const QDate &date_)
393 d->selectWeek->setCurrentIndex((date_.
dayOfYear() + firstDay.dayOfWeek() - 2) / 7);
394 d->selectYear->setText(
locale().toString(date_, QStringLiteral(
"yyyy")).rightJustified(4,
QLatin1Char(
'0')));
399void KDatePicker::tableClickedSlot()
406const QDate &KDatePicker::date()
const
408 return d->table->date();
415 return d->table->setDate(date_);
418void KDatePicker::monthForwardClicked()
420 if (!
setDate(date().addMonths(1))) {
423 d->table->setFocus();
426void KDatePicker::monthBackwardClicked()
428 if (!
setDate(date().addMonths(-1))) {
431 d->table->setFocus();
434void KDatePicker::yearForwardClicked()
436 if (!
setDate(d->table->date().addYears(1))) {
439 d->table->setFocus();
442void KDatePicker::yearBackwardClicked()
444 if (!
setDate(d->table->date().addYears(-1))) {
447 d->table->setFocus();
450void KDatePicker::weekSelected(
int index)
452 QDate targetDay = d->selectWeek->itemData(index).toDateTime().date();
457 d->table->setFocus();
460void KDatePicker::selectMonthClicked()
462 QDate thisDate(date());
463 d->table->setFocus();
465 QMenu popup(d->selectMonth);
469 for (
int m = 1; m <= monthsInYear; m++) {
470 popup.addAction(
locale().standaloneMonthName(m))->setData(m);
476 popup.setActiveAction(item);
480 if ((item = popup.exec(d->selectMonth->mapToGlobal(
QPoint(0, 0)), item)) ==
nullptr) {
498void KDatePicker::selectYearClicked()
500 if (!d->selectYear->isChecked()) {
504 QDate thisDate(date());
507 KDatePickerPrivateYearSelector *picker =
new KDatePickerPrivateYearSelector(date(), popup);
508 picker->resize(picker->sizeHint());
509 picker->setYear(thisDate);
515 if (popup->
exec(d->selectYear->mapToGlobal(
QPoint(0, d->selectMonth->height())))) {
518 QDate newDate(picker->year(), thisDate.
month(), 1);
531 d->selectYear->setChecked(
false);
534void KDatePicker::uncheckYearSelector()
536 d->selectYear->setChecked(
false);
537 d->selectYear->update();
540void KDatePicker::changeEvent(
QEvent *event)
544 d->table->setFocus();
549KDateTable *KDatePicker::dateTable()
const
554void KDatePicker::lineEnterPressed()
556 const QDate newDate = d->val->toDate(d->line->text());
561 d->table->setFocus();
567void KDatePicker::todayButtonClicked()
570 d->table->setFocus();
588 for (
QWidget *button : buttons) {
589 font = button->font();
590 font.setPointSize(s);
591 button->setFont(
font);
593 d->table->setFontSize(s);
598 for (
int i = 1;; ++i) {
605 if (r.
width() > d->maxMonthRect.width()) {
606 d->maxMonthRect.setWidth(r.
width());
609 if (r.
height() > d->maxMonthRect.height()) {
610 d->maxMonthRect.setHeight(r.
height());
616 opt.text = longestMonth;
621 int w = textSize.
width();
622 int h = textSize.
height();
623 opt.rect.setHeight(h);
627 d->selectMonth->setMinimumSize(metricBound);
630int KDatePicker::fontSize()
const
637 if (enable == (d->closeButton !=
nullptr)) {
643 d->closeButton->setAutoRaise(
true);
645 d->navigationLayout->addSpacing(horizontalSpacing);
646 d->navigationLayout->addWidget(d->closeButton);
647 d->closeButton->setToolTip(
tr(
"Close",
"@action:button"));
651 delete d->closeButton;
652 d->closeButton =
nullptr;
660 return (d->closeButton);
663#include "kdatepicker.moc"
KDatePicker(QWidget *parent=nullptr)
The constructor.
bool setDate(const QDate &date)
Sets the date.
void dateEntered(const QDate &date)
This signal is emitted when enter is pressed and a VALID date has been entered before into the line e...
bool eventFilter(QObject *o, QEvent *e) override
to catch move keyEvents when QLineEdit has keyFocus
bool hasCloseButton() const
void dateSelected(const QDate &date)
This signal is emitted each time a day has been selected by clicking on the table (hitting a day in t...
void setFontSize(int)
Sets the font size of the widgets elements.
QSize sizeHint() const override
The size hint for date pickers.
~KDatePicker() override
The destructor.
void dateChanged(const QDate &date)
This signal is emitted each time the selected date is changed.
void setCloseButton(bool enable)
By calling this method with enable = true, KDatePicker will show a little close-button in the upper b...
void resizeEvent(QResizeEvent *) override
the resize event
void tableClicked()
This signal is emitted when the day has been selected by clicking on it in the table.
char * toString(const EngineQuery &query)
bool isValid(QStringView ifopt)
KGuiItem ok()
Returns the 'Ok' gui item.
QVariant data() const const
void addLayout(QLayout *layout, int stretch)
virtual void setSpacing(int spacing) override
void activated(int index)
void addItem(const QIcon &icon, const QString &text, const QVariant &userData)
bool sendEvent(QObject *receiver, QEvent *event)
QDate addDays(qint64 ndays) const const
int dayOfWeek() const const
int dayOfYear() const const
int daysInMonth() const const
QDate fromJulianDay(qint64 jd)
bool isValid(int year, int month, int day)
bool setDate(int year, int month, int day)
int weekNumber(int *yearNumber) const const
int pointSize() const const
QFont systemFont(SystemFont type)
int pointSize() const const
QRect boundingRect(QChar ch) const const
int horizontalAdvance(QChar ch) const const
QSize size(int flags, const QString &text, int tabStops, int *tabArray) const const
virtual bool event(QEvent *e) override
QIcon fromTheme(const QString &name)
void setContentsMargins(const QMargins &margins)
QDate toDate(const QString &string, FormatType format) const const
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
virtual bool eventFilter(QObject *watched, QEvent *event)
QObject * parent() const const
QString tr(const char *sourceText, const char *disambiguation, int n)
QString arg(Args &&... args) const const
bool isNull() const const
int toInt(bool *ok, int base) const const
PM_LayoutHorizontalSpacing
virtual int pixelMetric(PixelMetric metric, const QStyleOption *option, const QWidget *widget) const const=0
virtual QSize sizeFromContents(ContentsType type, const QStyleOption *option, const QSize &contentsSize, const QWidget *widget) const const=0
void initFrom(const QWidget *widget)
QFuture< ArgsType< Signal > > connect(Sender *sender, Signal signal)
QLocale locale() const const
int toInt(bool *ok) const const