File indexing completed on 2024-11-10 04:50:03

0001 /*
0002  * SPDX-FileCopyrightText: 1996-1998 Stefan Taferner <taferner@kde.org>
0003  *
0004  * SPDX-License-Identifier: GPL-2.0-or-later
0005  *
0006  */
0007 
0008 #include "filteractionforward.h"
0009 #include "mailcommon_debug.h"
0010 
0011 #include "filter/dialog/filteractionmissingtemplatedialog.h"
0012 #include "kernel/mailkernel.h"
0013 
0014 #include <Akonadi/EmailAddressRequester>
0015 #include <MessageComposer/MessageFactoryNG>
0016 #include <MessageComposer/MessageSender>
0017 #include <MessageCore/StringUtil>
0018 #include <TemplateParser/CustomTemplates>
0019 #include <templateparser/customtemplates_kfg.h>
0020 
0021 #include <KComboBox>
0022 #include <KLineEdit>
0023 #include <KLocalizedString>
0024 
0025 #include <QHBoxLayout>
0026 
0027 using namespace MailCommon;
0028 
0029 FilterAction *FilterActionForward::newAction()
0030 {
0031     return new FilterActionForward;
0032 }
0033 
0034 FilterActionForward::FilterActionForward(QObject *parent)
0035     : FilterActionWithAddress(QStringLiteral("forward"), i18nc("Forward directly not with a command", "Forward To"), parent)
0036 {
0037 }
0038 
0039 FilterAction::ReturnCode FilterActionForward::process(ItemContext &context, bool) const
0040 {
0041     if (mParameter.isEmpty()) {
0042         return ErrorButGoOn;
0043     }
0044 
0045     const auto msg = context.item().payload<KMime::Message::Ptr>();
0046     // avoid endless loops when this action is used in a filter
0047     // which applies to sent messages
0048     if (MessageCore::StringUtil::addressIsInAddressList(mParameter, QStringList(msg->to()->asUnicodeString()))) {
0049         qCWarning(MAILCOMMON_LOG) << "Attempt to forward to recipient of original message, ignoring.";
0050         return ErrorButGoOn;
0051     }
0052 #if 0 // PORT ME TO ASync
0053     MessageComposer::MessageFactoryNG factory(msg, context.item().id());
0054     factory.setIdentityManager(KernelIf->identityManager());
0055     factory.setFolderIdentity(Util::folderIdentity(context.item()));
0056     factory.setTemplate(mTemplate);
0057 
0058     KMime::Message::Ptr fwdMsg = factory.createForward();
0059     fwdMsg->to()->fromUnicodeString(fwdMsg->to()->asUnicodeString() + QLatin1Char(',') + mParameter, "utf-8");
0060     if (!KernelIf->msgSender()->send(fwdMsg, MessageComposer::MessageSender::SendDefault)) {
0061         qCWarning(MAILCOMMON_LOG) << "FilterAction: could not forward message (sending failed)";
0062         return ErrorButGoOn; // error: couldn't send
0063     } else {
0064         sendMDN(context.item(), KMime::MDN::Dispatched);
0065     }
0066 #endif
0067     // (the msgSender takes ownership of the message, so don't delete it here)
0068     return GoOn;
0069 }
0070 
0071 SearchRule::RequiredPart FilterActionForward::requiredPart() const
0072 {
0073     return SearchRule::CompleteMessage;
0074 }
0075 
0076 QWidget *FilterActionForward::createParamWidget(QWidget *parent) const
0077 {
0078     auto addressAndTemplate = new QWidget(parent);
0079     auto layout = new QHBoxLayout(addressAndTemplate);
0080     layout->setContentsMargins({});
0081 
0082     QWidget *addressEdit = FilterActionWithAddress::createParamWidget(addressAndTemplate);
0083     addressEdit->setObjectName(QLatin1StringView("addressEdit"));
0084     layout->addWidget(addressEdit);
0085 
0086     auto addressRequester = qobject_cast<Akonadi::EmailAddressRequester *>(addressEdit);
0087     Q_ASSERT(addressRequester);
0088     KLineEdit *lineEdit = addressRequester->lineEdit();
0089     lineEdit->setClearButtonEnabled(true);
0090     lineEdit->setTrapReturnKey(true);
0091     lineEdit->setToolTip(i18n("The addressee to whom the message will be forwarded."));
0092     lineEdit->setWhatsThis(i18n("The filter will forward the message to the addressee entered here."));
0093 
0094     auto templateCombo = new KComboBox(addressAndTemplate);
0095     templateCombo->setMinimumWidth(50);
0096     templateCombo->setObjectName(QLatin1StringView("templateCombo"));
0097     layout->addWidget(templateCombo);
0098 
0099     templateCombo->addItem(i18n("Default Template"));
0100 
0101     const QStringList templateNames = SettingsIf->customTemplates();
0102     for (const QString &templateName : templateNames) {
0103         TemplateParser::CTemplates templat(templateName);
0104         if (templat.type() == TemplateParser::CustomTemplates::TForward || templat.type() == TemplateParser::CustomTemplates::TUniversal) {
0105             templateCombo->addItem(templateName);
0106         }
0107     }
0108 
0109     templateCombo->setEnabled(templateCombo->count() > 1);
0110     templateCombo->setToolTip(i18n("The template used when forwarding"));
0111     templateCombo->setWhatsThis(i18n("Set the forwarding template that will be used with this filter."));
0112     connect(templateCombo, &KComboBox::currentIndexChanged, this, &FilterActionForward::filterActionModified);
0113     connect(addressRequester, &Akonadi::EmailAddressRequester::textChanged, this, &FilterActionForward::filterActionModified);
0114 
0115     return addressAndTemplate;
0116 }
0117 
0118 void FilterActionForward::applyParamWidgetValue(QWidget *paramWidget)
0119 {
0120     auto addressEdit = paramWidget->findChild<QWidget *>(QStringLiteral("addressEdit"));
0121     Q_ASSERT(addressEdit);
0122     FilterActionWithAddress::applyParamWidgetValue(addressEdit);
0123 
0124     const auto templateCombo = paramWidget->findChild<KComboBox *>(QStringLiteral("templateCombo"));
0125     Q_ASSERT(templateCombo);
0126 
0127     if (templateCombo->currentIndex() == 0) {
0128         // Default template, so don't use a custom one
0129         mTemplate.clear();
0130     } else {
0131         mTemplate = templateCombo->currentText();
0132     }
0133 }
0134 
0135 void FilterActionForward::setParamWidgetValue(QWidget *paramWidget) const
0136 {
0137     auto addressEdit = paramWidget->findChild<QWidget *>(QStringLiteral("addressEdit"));
0138     Q_ASSERT(addressEdit);
0139     FilterActionWithAddress::setParamWidgetValue(addressEdit);
0140 
0141     const auto templateCombo = paramWidget->findChild<KComboBox *>(QStringLiteral("templateCombo"));
0142     Q_ASSERT(templateCombo);
0143 
0144     if (mTemplate.isEmpty()) {
0145         templateCombo->setCurrentIndex(0);
0146     } else {
0147         int templateIndex = templateCombo->findText(mTemplate);
0148         if (templateIndex != -1) {
0149             templateCombo->setCurrentIndex(templateIndex);
0150         } else {
0151             mTemplate.clear();
0152         }
0153     }
0154 }
0155 
0156 void FilterActionForward::clearParamWidget(QWidget *paramWidget) const
0157 {
0158     auto addressEdit = paramWidget->findChild<QWidget *>(QStringLiteral("addressEdit"));
0159     Q_ASSERT(addressEdit);
0160     FilterActionWithAddress::clearParamWidget(addressEdit);
0161 
0162     const auto templateCombo = paramWidget->findChild<KComboBox *>(QStringLiteral("templateCombo"));
0163     Q_ASSERT(templateCombo);
0164 
0165     templateCombo->setCurrentIndex(0);
0166 }
0167 
0168 // We simply place a "@$$@" between the two parameters. The template is the last
0169 // parameter in the string, for compatibility reasons.
0170 namespace
0171 {
0172 inline const QString forwardFilterArgsSeperator()
0173 {
0174     return QStringLiteral("@$$@");
0175 }
0176 }
0177 void FilterActionForward::argsFromString(const QString &argsStr)
0178 {
0179     const int seperatorPos = argsStr.indexOf(forwardFilterArgsSeperator());
0180 
0181     if (seperatorPos == -1) {
0182         // Old config, assume that the whole string is the addressee
0183         FilterActionWithAddress::argsFromString(argsStr);
0184     } else {
0185         const QString addressee = argsStr.left(seperatorPos);
0186         mTemplate = argsStr.mid(seperatorPos + forwardFilterArgsSeperator().length());
0187         FilterActionWithAddress::argsFromString(addressee);
0188     }
0189 }
0190 
0191 bool FilterActionForward::argsFromStringInteractive(const QString &argsStr, const QString &filterName)
0192 {
0193     bool needUpdate = false;
0194     argsFromString(argsStr);
0195     if (!mTemplate.isEmpty()) {
0196         const QStringList templateNames = SettingsIf->customTemplates();
0197         QStringList currentTemplateList;
0198         currentTemplateList << i18n("Default Template");
0199         for (const QString &templateName : templateNames) {
0200             TemplateParser::CTemplates templat(templateName);
0201             if (templat.type() == TemplateParser::CustomTemplates::TForward || templat.type() == TemplateParser::CustomTemplates::TUniversal) {
0202                 if (templateName == mTemplate) {
0203                     return false;
0204                 }
0205                 currentTemplateList << templateName;
0206             }
0207         }
0208         QPointer<MailCommon::FilterActionMissingTemplateDialog> dlg = new MailCommon::FilterActionMissingTemplateDialog(currentTemplateList, filterName);
0209         if (dlg->exec()) {
0210             mTemplate = dlg->selectedTemplate();
0211             needUpdate = true;
0212         }
0213         delete dlg;
0214     }
0215     return needUpdate;
0216 }
0217 
0218 QString FilterActionForward::argsAsString() const
0219 {
0220     return FilterActionWithAddress::argsAsString() + forwardFilterArgsSeperator() + mTemplate;
0221 }
0222 
0223 QString FilterActionForward::displayString() const
0224 {
0225     if (mTemplate.isEmpty()) {
0226         return i18n("Forward to %1 with default template", mParameter);
0227     } else {
0228         return i18n("Forward to %1 with template %2", mParameter, mTemplate);
0229     }
0230 }
0231 
0232 QString FilterActionForward::informationAboutNotValidAction() const
0233 {
0234     return i18n("Email address was not defined.");
0235 }
0236 
0237 #include "moc_filteractionforward.cpp"