File indexing completed on 2025-02-02 14:20:00
0001 /* 0002 SPDX-FileCopyrightText: 2004 Bram Schoenmakers <bramschoenmakers@kde.nl> 0003 SPDX-License-Identifier: LGPL-2.0-or-later 0004 */ 0005 0006 #include "kdatepickerpopup.h" 0007 #include "kdatepicker.h" 0008 #include "kdaterangecontrol_p.h" 0009 0010 #include <QDateTime> 0011 #include <QLocale> 0012 #include <QWidgetAction> 0013 0014 class KDatePickerAction : public QWidgetAction 0015 { 0016 public: 0017 KDatePickerAction(KDatePicker *widget, QObject *parent) 0018 : QWidgetAction(parent) 0019 , mDatePicker(widget) 0020 , mOriginalParent(widget->parentWidget()) 0021 { 0022 } 0023 0024 protected: 0025 QWidget *createWidget(QWidget *parent) override 0026 { 0027 mDatePicker->setParent(parent); 0028 return mDatePicker; 0029 } 0030 0031 void deleteWidget(QWidget *widget) override 0032 { 0033 if (widget != mDatePicker) { 0034 return; 0035 } 0036 0037 mDatePicker->setParent(mOriginalParent); 0038 } 0039 0040 private: 0041 KDatePicker *const mDatePicker; 0042 QWidget *const mOriginalParent; 0043 }; 0044 0045 class KDatePickerPopupPrivate : public KDateRangeControlPrivate 0046 { 0047 public: 0048 explicit KDatePickerPopupPrivate(KDatePickerPopup *qq) 0049 : q(qq) 0050 { 0051 } 0052 0053 void addMenuAction(const QString &text, const QDate &date); 0054 void buildMenu(); 0055 void menuActionTriggered(QAction *action); 0056 void slotDateChanged(QDate); 0057 0058 KDatePickerPopup *const q; 0059 KDatePicker *mDatePicker = nullptr; 0060 KDatePickerPopup::Modes mModes; 0061 QMap<QDate, QString> m_dateMap; 0062 }; 0063 0064 void KDatePickerPopupPrivate::addMenuAction(const QString &text, const QDate &date) 0065 { 0066 // skip out-of-range dates 0067 // an invalid date is ok though, that's for the "No Date" action 0068 if (date.isValid() && !isInDateRange(date)) { 0069 return; 0070 } 0071 0072 QAction *action = new QAction(q); 0073 action->setText(text); 0074 action->setData(date); 0075 QObject::connect(action, &QAction::triggered, q, [this, action]() { 0076 Q_EMIT q->dateChanged(action->data().toDate()); 0077 }); 0078 q->addAction(action); 0079 } 0080 0081 void KDatePickerPopupPrivate::buildMenu() 0082 { 0083 q->clear(); 0084 0085 if (mModes & KDatePickerPopup::DatePicker) { 0086 q->addAction(new KDatePickerAction(mDatePicker, q)); 0087 0088 if ((mModes & KDatePickerPopup::NoDate) || (mModes & KDatePickerPopup::Words)) { 0089 q->addSeparator(); 0090 } 0091 } 0092 0093 if (mModes & KDatePickerPopup::Words) { 0094 if (m_dateMap.isEmpty()) { 0095 const QDate today = QDate::currentDate(); 0096 addMenuAction(KDatePickerPopup::tr("Next Year", "@option next year"), today.addYears(1)); 0097 addMenuAction(KDatePickerPopup::tr("Next Month", "@option next month"), today.addMonths(1)); 0098 addMenuAction(KDatePickerPopup::tr("Next Week", "@option next week"), today.addDays(7)); 0099 addMenuAction(KDatePickerPopup::tr("Tomorrow", "@option tomorrow"), today.addDays(1)); 0100 addMenuAction(KDatePickerPopup::tr("Today", "@option today"), today); 0101 addMenuAction(KDatePickerPopup::tr("Yesterday", "@option yesterday"), today.addDays(-1)); 0102 addMenuAction(KDatePickerPopup::tr("Last Week", "@option last week"), today.addDays(-7)); 0103 addMenuAction(KDatePickerPopup::tr("Last Month", "@option last month"), today.addMonths(-1)); 0104 addMenuAction(KDatePickerPopup::tr("Last Year", "@option last year"), today.addYears(-1)); 0105 } else { 0106 for (auto it = m_dateMap.constBegin(); it != m_dateMap.constEnd(); ++it) { 0107 if (it.value().isEmpty()) { 0108 addMenuAction(QLocale().toString(it.key()), it.key()); 0109 } else if (it.value().toLower() == QLatin1String("separator")) { 0110 q->addSeparator(); 0111 } else { 0112 addMenuAction(it.value(), it.key()); 0113 } 0114 } 0115 } 0116 0117 if (mModes & KDatePickerPopup::NoDate) { 0118 q->addSeparator(); 0119 } 0120 } 0121 0122 if (mModes & KDatePickerPopup::NoDate) { 0123 addMenuAction(KDatePickerPopup::tr("No Date", "@option do not specify a date"), QDate()); 0124 } 0125 } 0126 0127 void KDatePickerPopupPrivate::slotDateChanged(QDate date) 0128 { 0129 Q_EMIT q->dateChanged(date); 0130 q->hide(); 0131 } 0132 0133 KDatePickerPopup::KDatePickerPopup(Modes modes, QDate date, QWidget *parent) 0134 : QMenu(parent) 0135 , d(new KDatePickerPopupPrivate(this)) 0136 { 0137 d->mModes = modes; 0138 0139 d->mDatePicker = new KDatePicker(this); 0140 d->mDatePicker->setCloseButton(false); 0141 0142 connect(d->mDatePicker, &KDatePicker::dateEntered, this, [this](QDate date) { 0143 d->slotDateChanged(date); 0144 }); 0145 connect(d->mDatePicker, &KDatePicker::dateSelected, this, [this](QDate date) { 0146 d->slotDateChanged(date); 0147 }); 0148 0149 d->mDatePicker->setDate(date); 0150 0151 connect(this, &QMenu::aboutToShow, this, [this]() { 0152 d->buildMenu(); 0153 }); 0154 } 0155 0156 KDatePickerPopup::~KDatePickerPopup() = default; 0157 0158 KDatePicker *KDatePickerPopup::datePicker() const 0159 { 0160 return d->mDatePicker; 0161 } 0162 0163 void KDatePickerPopup::setDate(QDate date) 0164 { 0165 d->mDatePicker->setDate(date); 0166 } 0167 0168 KDatePickerPopup::Modes KDatePickerPopup::modes() const 0169 { 0170 return d->mModes; 0171 } 0172 0173 void KDatePickerPopup::setModes(KDatePickerPopup::Modes modes) 0174 { 0175 d->mModes = modes; 0176 } 0177 0178 void KDatePickerPopup::setDateRange(const QDate &minDate, const QDate &maxDate) 0179 { 0180 d->setDateRange(minDate, maxDate); 0181 } 0182 0183 QMap<QDate, QString> KDatePickerPopup::dateMap() const 0184 { 0185 return d->m_dateMap; 0186 } 0187 0188 void KDatePickerPopup::setDateMap(const QMap<QDate, QString> &dateMap) 0189 { 0190 d->m_dateMap = dateMap; 0191 } 0192 0193 #include "moc_kdatepickerpopup.cpp"