File indexing completed on 2025-02-16 04:56:07

0001 /*
0002    SPDX-FileCopyrightText: 2013-2024 Laurent Montel <montel@kde.org>
0003 
0004    SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #include "vacationeditwidget.h"
0008 #include "vacationmailactionwidget.h"
0009 #include "vacationmaillineedit.h"
0010 
0011 #include <KDateComboBox>
0012 #include <KLocalizedString>
0013 #include <KTimeComboBox>
0014 #include <QLineEdit>
0015 #include <QRegularExpressionValidator>
0016 #include <QSpinBox>
0017 
0018 #include "libksieveui_debug.h"
0019 #include <KLineEditEventHandler>
0020 #include <TextCustomEditor/PlainTextEditor>
0021 #include <TextCustomEditor/PlainTextEditorWidget>
0022 
0023 #include <KMime/HeaderParsing>
0024 
0025 #include <PimCommon/SpellCheckLineEdit>
0026 #include <QCheckBox>
0027 #include <QGridLayout>
0028 #include <QLabel>
0029 
0030 using KMime::HeaderParsing::parseAddressList;
0031 using KMime::Types::AddressList;
0032 using KMime::Types::AddrSpecList;
0033 using KMime::Types::MailboxList;
0034 
0035 using namespace KSieveUi;
0036 VacationEditWidget::VacationEditWidget(QWidget *parent)
0037     : QWidget(parent)
0038 {
0039     int row = -1;
0040 
0041     auto glay = new QGridLayout(this);
0042     glay->setContentsMargins({});
0043     glay->setColumnStretch(1, 1);
0044 
0045     // explanation label:
0046     ++row;
0047     auto configureVacationLabel = new QLabel(i18n("Configure vacation "
0048                                                   "notifications to be sent:"),
0049                                              this);
0050     configureVacationLabel->setObjectName(QLatin1StringView("configureVacationLabel"));
0051     glay->addWidget(configureVacationLabel, row, 0, 1, 2);
0052 
0053     // Activate checkbox:
0054     ++row;
0055     mActiveCheck = new QCheckBox(i18n("&Activate vacation notifications"), this);
0056     mActiveCheck->setObjectName(QLatin1StringView("mActiveCheck"));
0057     glay->addWidget(mActiveCheck, row, 0, 1, 2);
0058     connect(mActiveCheck, &QCheckBox::clicked, this, &VacationEditWidget::setWasChanged);
0059 
0060     // Message text edit:
0061     ++row;
0062     glay->setRowStretch(row, 1);
0063     mTextEdit = new TextCustomEditor::PlainTextEditorWidget(this);
0064     mTextEdit->setObjectName(QLatin1StringView("mTextEdit"));
0065     glay->addWidget(mTextEdit, row, 0, 1, 2);
0066     connect(mTextEdit->editor(), &TextCustomEditor::PlainTextEditor::textChanged, this, &VacationEditWidget::setWasChanged);
0067 
0068     // Subject
0069     ++row;
0070     mSubject = new PimCommon::SpellCheckLineEdit(this, QString());
0071     KLineEditEventHandler::catchReturnKey(mSubject);
0072     mSubject->setObjectName(QLatin1StringView("mSubject"));
0073     connect(mSubject, &PimCommon::SpellCheckLineEdit::textChanged, this, &VacationEditWidget::setWasChanged);
0074     // mSubject->setClearButtonEnabled(true);
0075     auto subjectOfVacationLabel = new QLabel(i18n("&Subject of the vacation mail:"), this);
0076     subjectOfVacationLabel->setObjectName(QLatin1StringView("subjectOfVacationLabel"));
0077     subjectOfVacationLabel->setBuddy(mSubject);
0078     glay->addWidget(subjectOfVacationLabel, row, 0);
0079     glay->addWidget(mSubject, row, 1);
0080     ++row;
0081 
0082     auto timeLayout = new QHBoxLayout;
0083     // Start date
0084     mStartDate = new KDateComboBox(this);
0085     KLineEditEventHandler::catchReturnKey(mStartDate->lineEdit());
0086     mStartDate->setObjectName(QLatin1StringView("mStartDate"));
0087     mStartDate->setOptions(KDateComboBox::EditDate | KDateComboBox::SelectDate | KDateComboBox::DatePicker | KDateComboBox::DateKeywords);
0088     connect(mStartDate, &KDateComboBox::dateChanged, this, &VacationEditWidget::setWasChanged);
0089     connect(mStartDate, &KDateComboBox::dateEdited, this, &VacationEditWidget::setWasChanged);
0090 
0091     mStartTime = new KTimeComboBox(this);
0092     KLineEditEventHandler::catchReturnKey(mStartTime->lineEdit());
0093     mStartTime->setObjectName(QLatin1StringView("mStartTime"));
0094     mStartTime->setOptions(KTimeComboBox::EditTime | KTimeComboBox::SelectTime | KTimeComboBox::WarnOnInvalid);
0095     mStartTime->setEnabled(false); // Disable by default - we need an extension to support this
0096     connect(mStartTime, &KTimeComboBox::timeChanged, this, &VacationEditWidget::setWasChanged);
0097     connect(mStartTime, &KTimeComboBox::timeEdited, this, &VacationEditWidget::setWasChanged);
0098 
0099     mStartTimeActive = new QCheckBox(this);
0100     mStartTimeActive->setObjectName(QLatin1StringView("mStartTimeActive"));
0101     connect(mStartTimeActive, &QCheckBox::toggled, mStartTime, &KTimeComboBox::setEnabled);
0102 
0103     timeLayout->addWidget(mStartDate);
0104     timeLayout->addWidget(mStartTimeActive);
0105     timeLayout->addWidget(mStartTime);
0106 
0107     mStartDateLabel = new QLabel(i18n("Start date:"), this);
0108     mStartDateLabel->setObjectName(QLatin1StringView("mStartDateLabel"));
0109     mStartDateLabel->setBuddy(mStartDate);
0110     glay->addWidget(mStartDateLabel, row, 0);
0111     glay->addLayout(timeLayout, row, 1);
0112 
0113     ++row;
0114     // End date
0115     timeLayout = new QHBoxLayout;
0116 
0117     mEndDate = new KDateComboBox(this);
0118     KLineEditEventHandler::catchReturnKey(mEndDate->lineEdit());
0119     mEndDate->setObjectName(QLatin1StringView("mEndDate"));
0120     mEndDate->setOptions(KDateComboBox::EditDate | KDateComboBox::SelectDate | KDateComboBox::DatePicker | KDateComboBox::DateKeywords);
0121     connect(mEndDate, &KDateComboBox::dateChanged, this, &VacationEditWidget::setWasChanged);
0122     connect(mEndDate, &KDateComboBox::dateEdited, this, &VacationEditWidget::setWasChanged);
0123 
0124     mEndTime = new KTimeComboBox(this);
0125     mEndTime->setObjectName(QLatin1StringView("mEndTime"));
0126     KLineEditEventHandler::catchReturnKey(mEndTime->lineEdit());
0127     mEndTime->setOptions(KTimeComboBox::EditTime | KTimeComboBox::SelectTime | KTimeComboBox::WarnOnInvalid);
0128     mEndTime->setEnabled(false); // Disable by default - we need an extension to support this
0129     connect(mEndTime, &KTimeComboBox::timeChanged, this, &VacationEditWidget::setWasChanged);
0130     connect(mEndTime, &KTimeComboBox::timeEdited, this, &VacationEditWidget::setWasChanged);
0131 
0132     mEndTimeActive = new QCheckBox(this);
0133     mEndTimeActive->setObjectName(QLatin1StringView("mEndTimeActive"));
0134     connect(mEndTimeActive, &QCheckBox::toggled, mEndTime, &KTimeComboBox::setEnabled);
0135     connect(mEndTimeActive, &QCheckBox::toggled, this, &VacationEditWidget::setWasChanged);
0136 
0137     mEndDateLabel = new QLabel(i18n("End date:"), this);
0138     mEndDateLabel->setObjectName(QLatin1StringView("mEndDateLabel"));
0139     mEndDateLabel->setBuddy(mEndDate);
0140     glay->addWidget(mEndDateLabel, row, 0);
0141 
0142     timeLayout->addWidget(mEndDate);
0143     timeLayout->addWidget(mEndTimeActive);
0144     timeLayout->addWidget(mEndTime);
0145     glay->addLayout(timeLayout, row, 1);
0146 
0147     // Hide the date edits by default - they must be enabled by caller when the
0148     // server supports this feature
0149     enableDates(false);
0150 
0151     // "Resent only after" spinbox and label:
0152     ++row;
0153     int defDayInterval = 7; // default day interval
0154     mIntervalSpin = new QSpinBox(this);
0155     mIntervalSpin->setMaximum(356);
0156     mIntervalSpin->setMinimum(1);
0157     mIntervalSpin->setSingleStep(1);
0158     mIntervalSpin->setValue(defDayInterval);
0159     mIntervalSpin->setObjectName(QLatin1StringView("mIntervalSpin"));
0160     mIntervalSpin->setSuffix(i18np(" day", " days", defDayInterval));
0161     connect(mIntervalSpin, &QSpinBox::valueChanged, this, &VacationEditWidget::slotIntervalSpinChanged);
0162     auto resendNotificationLabel = new QLabel(i18n("&Resend notification only after:"), this);
0163     resendNotificationLabel->setObjectName(QLatin1StringView("resendNotificationLabel"));
0164     resendNotificationLabel->setBuddy(mIntervalSpin);
0165     glay->addWidget(resendNotificationLabel, row, 0);
0166     glay->addWidget(mIntervalSpin, row, 1);
0167 
0168     // "Send responses for these addresses" lineedit and label:
0169     ++row;
0170     mMailAliasesEdit = new KSieveUi::VacationMailLineEdit(this);
0171     mMailAliasesEdit->setObjectName(QLatin1StringView("mMailAliasesEdit"));
0172     mMailAliasesEdit->setClearButtonEnabled(true);
0173     KLineEditEventHandler::catchReturnKey(mMailAliasesEdit);
0174     connect(mMailAliasesEdit, &KSieveUi::VacationMailLineEdit::textChanged, this, &VacationEditWidget::setWasChanged);
0175     auto sendResponseLabel = new QLabel(i18n("&Send responses for these addresses:"), this);
0176     sendResponseLabel->setObjectName(QLatin1StringView("sendResponseLabel"));
0177     sendResponseLabel->setBuddy(mMailAliasesEdit);
0178     glay->addWidget(sendResponseLabel, row, 0);
0179     glay->addWidget(mMailAliasesEdit, row, 1);
0180 
0181     // Action for incoming mails
0182     mMailAction = new QComboBox(this);
0183     for (int i = 0; i < 4; ++i) {
0184         mMailAction->addItem(KSieveCore::VacationUtils::mailAction(static_cast<KSieveCore::VacationUtils::MailAction>(i)));
0185     }
0186     mMailAction->setObjectName(QLatin1StringView("mMailAction"));
0187     connect(mMailAction, &QComboBox::currentIndexChanged, this, &VacationEditWidget::mailActionChanged);
0188 
0189     // Add imap select folder plugin here.
0190     mMailActionRecipient = new VacationMailActionWidget(this);
0191     mMailActionRecipient->setObjectName(QLatin1StringView("mMailActionRecipient"));
0192     connect(mMailActionRecipient, &VacationMailActionWidget::wasChanged, this, &VacationEditWidget::setWasChanged);
0193     // Add setChanged here too
0194 
0195     auto hLayout = new QHBoxLayout;
0196 
0197     hLayout->addWidget(mMailAction);
0198     hLayout->addWidget(mMailActionRecipient);
0199 
0200     ++row;
0201     auto actionIncomingMailsLabel = new QLabel(i18n("&Action for incoming mails:"), this);
0202     actionIncomingMailsLabel->setBuddy(mMailAction);
0203     actionIncomingMailsLabel->setObjectName(QLatin1StringView("actionIncomingMailsLabel"));
0204     glay->addWidget(actionIncomingMailsLabel, row, 0);
0205     glay->addLayout(hLayout, row, 1);
0206 
0207     // "Send responses also to SPAM mail" checkbox:
0208     ++row;
0209     mSpamCheck = new QCheckBox(i18n("Do not send vacation replies to spam messages"), this);
0210     mSpamCheck->setObjectName(QLatin1StringView("mSpamCheck"));
0211     mSpamCheck->setChecked(true);
0212     glay->addWidget(mSpamCheck, row, 0, 1, 2);
0213     connect(mSpamCheck, &QCheckBox::clicked, this, &VacationEditWidget::setWasChanged);
0214 
0215     //  domain checkbox and linedit:
0216     ++row;
0217     mDomainCheck = new QCheckBox(i18n("Only react to mail coming from domain:"), this);
0218     mDomainCheck->setObjectName(QLatin1StringView("mDomainCheck"));
0219     mDomainCheck->setChecked(false);
0220     connect(mDomainCheck, &QCheckBox::clicked, this, &VacationEditWidget::setWasChanged);
0221 
0222     mDomainEdit = new QLineEdit(this);
0223     KLineEditEventHandler::catchReturnKey(mDomainEdit);
0224     mDomainEdit->setObjectName(QLatin1StringView("mDomainEdit"));
0225     mDomainEdit->setClearButtonEnabled(true);
0226     mDomainEdit->setEnabled(false);
0227     mDomainEdit->setValidator(new QRegularExpressionValidator(QRegularExpression(QStringLiteral("[a-zA-Z0-9+-]+(?:\\.[a-zA-Z0-9+-]+)*")), mDomainEdit));
0228     glay->addWidget(mDomainCheck, row, 0);
0229     glay->addWidget(mDomainEdit, row, 1);
0230     connect(mDomainCheck, &QCheckBox::toggled, mDomainEdit, &QLineEdit::setEnabled);
0231     connect(mDomainEdit, &QLineEdit::textChanged, this, &VacationEditWidget::setWasChanged);
0232 }
0233 
0234 VacationEditWidget::~VacationEditWidget() = default;
0235 
0236 bool VacationEditWidget::activateVacation() const
0237 {
0238     return mActiveCheck->isChecked();
0239 }
0240 
0241 void VacationEditWidget::setActivateVacation(bool activate)
0242 {
0243     mActiveCheck->setChecked(activate);
0244 }
0245 
0246 QString VacationEditWidget::messageText() const
0247 {
0248     return mTextEdit->toPlainText().trimmed();
0249 }
0250 
0251 void VacationEditWidget::setMessageText(const QString &text)
0252 {
0253     mTextEdit->setPlainText(text);
0254     const int height = (mTextEdit->fontMetrics().lineSpacing() + 1) * 11;
0255     mTextEdit->setMinimumHeight(height);
0256 }
0257 
0258 int VacationEditWidget::notificationInterval() const
0259 {
0260     return mIntervalSpin->value();
0261 }
0262 
0263 void VacationEditWidget::setNotificationInterval(int days)
0264 {
0265     mIntervalSpin->setValue(days);
0266 }
0267 
0268 AddrSpecList VacationEditWidget::mailAliases(bool &ok) const
0269 {
0270     QByteArray text = mMailAliasesEdit->text().toLatin1(); // ### IMAA: !ok
0271     AddressList al;
0272     const char *s = text.cbegin();
0273     AddrSpecList asl;
0274     if (parseAddressList(s, text.cend(), al)) {
0275         AddressList::const_iterator end(al.constEnd());
0276         for (AddressList::const_iterator it = al.constBegin(); it != end; ++it) {
0277             const MailboxList &mbl = (*it).mailboxList;
0278             MailboxList::const_iterator endJt = mbl.constEnd();
0279             for (MailboxList::const_iterator jt = mbl.constBegin(); jt != endJt; ++jt) {
0280                 asl.push_back((*jt).addrSpec());
0281             }
0282         }
0283         ok = true;
0284     } else {
0285         qCWarning(LIBKSIEVEUI_LOG) << "Impossible to parse email!" << text;
0286         ok = false;
0287     }
0288     mMailAliasesEdit->setInvalidEmail(!ok);
0289     return asl;
0290 }
0291 
0292 void VacationEditWidget::setMailAliases(const AddrSpecList &aliases)
0293 {
0294     QStringList sl;
0295     sl.reserve(aliases.count());
0296     for (const auto &str : aliases) {
0297         sl.push_back(str.asString());
0298     }
0299     mMailAliasesEdit->setText(sl.join(QLatin1StringView(", ")));
0300 }
0301 
0302 void VacationEditWidget::setMailAliases(const QString &aliases)
0303 {
0304     mMailAliasesEdit->setText(aliases);
0305 }
0306 
0307 void VacationEditWidget::slotIntervalSpinChanged(int value)
0308 {
0309     mIntervalSpin->setSuffix(i18np(" day", " days", value));
0310     setWasChanged();
0311 }
0312 
0313 QString VacationEditWidget::domainName() const
0314 {
0315     return mDomainCheck->isChecked() ? mDomainEdit->text() : QString();
0316 }
0317 
0318 void VacationEditWidget::setDomainName(const QString &domain)
0319 {
0320     if (!domain.isEmpty()) {
0321         mDomainEdit->setText(domain);
0322         mDomainCheck->setChecked(true);
0323     }
0324 }
0325 
0326 bool VacationEditWidget::domainCheck() const
0327 {
0328     return mDomainCheck->isChecked();
0329 }
0330 
0331 void VacationEditWidget::setDomainCheck(bool check)
0332 {
0333     mDomainCheck->setChecked(check);
0334 }
0335 
0336 bool VacationEditWidget::sendForSpam() const
0337 {
0338     return !mSpamCheck->isChecked();
0339 }
0340 
0341 void VacationEditWidget::setSendForSpam(bool enable)
0342 {
0343     mSpamCheck->setChecked(!enable);
0344 }
0345 
0346 QDate VacationEditWidget::endDate() const
0347 {
0348     if (mEndDate->isEnabled()) {
0349         return mEndDate->date();
0350     } else {
0351         return {};
0352     }
0353 }
0354 
0355 void VacationEditWidget::setEndDate(QDate endDate)
0356 {
0357     mEndDate->setDate(endDate);
0358 }
0359 
0360 QTime VacationEditWidget::endTime() const
0361 {
0362     if (mEndTime->isEnabled()) {
0363         return mEndTime->time();
0364     } else {
0365         return {};
0366     }
0367 }
0368 
0369 void VacationEditWidget::setEndTime(QTime endTime)
0370 {
0371     mEndTimeActive->setChecked(endTime.isValid());
0372     mEndTime->setEnabled(endTime.isValid());
0373     mEndTime->setTime(endTime);
0374 }
0375 
0376 QDate VacationEditWidget::startDate() const
0377 {
0378     if (mStartDate->isEnabled()) {
0379         return mStartDate->date();
0380     } else {
0381         return {};
0382     }
0383 }
0384 
0385 void VacationEditWidget::setStartDate(QDate startDate)
0386 {
0387     mStartDate->setDate(startDate);
0388 }
0389 
0390 QTime VacationEditWidget::startTime() const
0391 {
0392     if (mStartTime->isEnabled()) {
0393         return mStartTime->time();
0394     } else {
0395         return {};
0396     }
0397 }
0398 
0399 void VacationEditWidget::setStartTime(QTime startTime)
0400 {
0401     mStartTimeActive->setChecked(startTime.isValid());
0402     mStartTime->setEnabled(startTime.isValid());
0403     mStartTime->setTime(startTime);
0404 }
0405 
0406 void VacationEditWidget::setSubject(const QString &subject)
0407 {
0408     mSubject->setText(subject);
0409 }
0410 
0411 QString VacationEditWidget::subject() const
0412 {
0413     if (mSubject->isEnabled()) {
0414         return mSubject->toPlainText();
0415     } else {
0416         return {};
0417     }
0418 }
0419 
0420 void VacationEditWidget::enableDates(bool enable)
0421 {
0422     mStartDate->setVisible(enable);
0423     mStartDateLabel->setVisible(enable);
0424     mEndDate->setVisible(enable);
0425     mEndDateLabel->setVisible(enable);
0426     mStartTime->setVisible(enable);
0427     mStartTimeActive->setVisible(enable);
0428     mEndTime->setVisible(enable);
0429     mEndTimeActive->setVisible(enable);
0430 }
0431 
0432 void VacationEditWidget::mailActionChanged(int action)
0433 {
0434     mMailActionRecipient->mailActionChanged(static_cast<KSieveCore::VacationUtils::MailAction>(action));
0435     setWasChanged();
0436 }
0437 
0438 void VacationEditWidget::setWasChanged()
0439 {
0440     mChanged = true;
0441 }
0442 
0443 bool VacationEditWidget::changed() const
0444 {
0445     return mChanged;
0446 }
0447 
0448 void VacationEditWidget::setChanged(bool changed)
0449 {
0450     mChanged = changed;
0451 }
0452 
0453 void VacationEditWidget::setMailAction(KSieveCore::VacationUtils::MailAction action, const QString &recipient)
0454 {
0455     mMailAction->setCurrentIndex(action);
0456     mMailActionRecipient->setMailAction(action, recipient);
0457 }
0458 
0459 void VacationEditWidget::setSieveImapAccountSettings(const KSieveCore::SieveImapAccountSettings &account)
0460 {
0461     mMailActionRecipient->setSieveImapAccountSettings(account);
0462 }
0463 
0464 KSieveCore::VacationUtils::MailAction VacationEditWidget::mailAction() const
0465 {
0466     return static_cast<KSieveCore::VacationUtils::MailAction>(mMailAction->currentIndex());
0467 }
0468 
0469 QString VacationEditWidget::mailActionRecipient(bool &valid) const
0470 {
0471     return mMailActionRecipient->mailActionRecipient(valid);
0472 }
0473 
0474 void VacationEditWidget::enableDomainAndSendForSpam(bool enable)
0475 {
0476     mDomainCheck->setEnabled(enable);
0477     mDomainEdit->setEnabled(enable && mDomainCheck->isChecked());
0478     mSpamCheck->setEnabled(enable);
0479 }
0480 
0481 void VacationEditWidget::setDefault()
0482 {
0483     setActivateVacation(true);
0484     setMessageText(KSieveCore::VacationUtils::defaultMessageText());
0485     setSubject(KSieveCore::VacationUtils::defaultSubject());
0486     setNotificationInterval(KSieveCore::VacationUtils::defaultNotificationInterval());
0487     setMailAliases(KSieveCore::VacationUtils::defaultMailAliases());
0488     setSendForSpam(KSieveCore::VacationUtils::defaultSendForSpam());
0489     setDomainName(KSieveCore::VacationUtils::defaultDomainName());
0490     setMailAction(KSieveCore::VacationUtils::defaultMailAction(), QString());
0491     mStartTimeActive->setChecked(false);
0492     mEndTimeActive->setChecked(false);
0493     mStartTime->setTime(QTime());
0494     mEndTime->setTime(QTime());
0495     mStartDate->setDate(QDate());
0496     mEndDate->setDate(QDate());
0497     setDomainCheck(false);
0498     mDomainEdit->clear();
0499 }
0500 
0501 #include "moc_vacationeditwidget.cpp"