File indexing completed on 2024-12-29 04:54:44

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 "sieveglobalvariablewidget.h"
0008 #include "autocreatescriptutil_p.h"
0009 #include "commonwidgets/sievehelpbutton.h"
0010 #include "editor/sieveeditorutil.h"
0011 #include "sievescriptblockwidget.h"
0012 #include "widgets/lineeditvalidator.h"
0013 
0014 #include <KLineEditEventHandler>
0015 #include <KLocalizedString>
0016 #include <QIcon>
0017 #include <QLineEdit>
0018 #include <QPushButton>
0019 
0020 #include "libksieveui_debug.h"
0021 #include <QCheckBox>
0022 #include <QGridLayout>
0023 #include <QLabel>
0024 #include <QScrollArea>
0025 #include <QWhatsThis>
0026 #include <QXmlStreamReader>
0027 
0028 using namespace KSieveUi;
0029 static const int MINIMUMGLOBALVARIABLEACTION = 1;
0030 static const int MAXIMUMGLOBALVARIABLEACTION = 15;
0031 
0032 SieveGlobalVariableActionWidget::SieveGlobalVariableActionWidget(QWidget *parent)
0033     : QWidget(parent)
0034 {
0035     initWidget();
0036 }
0037 
0038 SieveGlobalVariableActionWidget::~SieveGlobalVariableActionWidget() = default;
0039 
0040 void SieveGlobalVariableActionWidget::generatedScript(QString &script)
0041 {
0042     const QString variableName = mVariableName->text();
0043     if (variableName.trimmed().isEmpty()) {
0044         return;
0045     }
0046     script += QLatin1StringView("global ");
0047     script += QStringLiteral("\"%1\";\n").arg(variableName);
0048     if (mSetValueTo->isChecked() && !mVariableValue->text().isEmpty()) {
0049         script += QStringLiteral("set \"%1\" \"%2\";\n").arg(variableName, mVariableValue->text());
0050     }
0051 }
0052 
0053 void SieveGlobalVariableActionWidget::initWidget()
0054 {
0055     mLayout = new QGridLayout(this);
0056     mLayout->setContentsMargins({});
0057 
0058     auto lab = new QLabel(i18n("Variable name:"), this);
0059     mLayout->addWidget(lab, 1, 0);
0060 
0061     mVariableName = new LineEditValidator(this);
0062     connect(mVariableName, &QLineEdit::textChanged, this, &SieveGlobalVariableActionWidget::valueChanged);
0063     mLayout->addWidget(mVariableName, 1, 1);
0064 
0065     mSetValueTo = new QCheckBox(i18n("Set value to:"), this);
0066     connect(mSetValueTo, &QCheckBox::toggled, this, &SieveGlobalVariableActionWidget::valueChanged);
0067     mLayout->addWidget(mSetValueTo, 1, 2);
0068     mSetValueTo->setChecked(false);
0069 
0070     mVariableValue = new QLineEdit(this);
0071     KLineEditEventHandler::catchReturnKey(mVariableValue);
0072     connect(mVariableValue, &QLineEdit::textChanged, this, &SieveGlobalVariableActionWidget::valueChanged);
0073     mVariableValue->setEnabled(false);
0074     mLayout->addWidget(mVariableValue, 1, 3);
0075 
0076     connect(mSetValueTo, &QCheckBox::clicked, mVariableValue, &QLineEdit::setEnabled);
0077 
0078     mAdd = new QPushButton(this);
0079     mAdd->setIcon(QIcon::fromTheme(QStringLiteral("list-add")));
0080     mAdd->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed));
0081 
0082     mRemove = new QPushButton(this);
0083     mRemove->setIcon(QIcon::fromTheme(QStringLiteral("list-remove")));
0084     mRemove->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed));
0085     mLayout->addWidget(mAdd, 1, 4);
0086     mLayout->addWidget(mRemove, 1, 5);
0087 
0088     connect(mAdd, &QPushButton::clicked, this, &SieveGlobalVariableActionWidget::slotAddWidget);
0089     connect(mRemove, &QPushButton::clicked, this, &SieveGlobalVariableActionWidget::slotRemoveWidget);
0090 }
0091 
0092 void SieveGlobalVariableActionWidget::clear()
0093 {
0094     mVariableName->clear();
0095     mSetValueTo->setChecked(false);
0096     mVariableValue->setEnabled(false);
0097     mVariableValue->clear();
0098 }
0099 
0100 bool SieveGlobalVariableActionWidget::isInitialized() const
0101 {
0102     return !mVariableName->text().isEmpty();
0103 }
0104 
0105 QString SieveGlobalVariableActionWidget::variableName() const
0106 {
0107     const QString varName = mVariableName->text();
0108     if (varName.trimmed().isEmpty()) {
0109         return {};
0110     }
0111     return varName;
0112 }
0113 
0114 void SieveGlobalVariableActionWidget::setVariableValue(const QString &name)
0115 {
0116     mSetValueTo->setChecked(true);
0117     mVariableValue->setText(name);
0118     mVariableValue->setEnabled(true);
0119 }
0120 
0121 void SieveGlobalVariableActionWidget::loadScript(QXmlStreamReader &element, QString &error)
0122 {
0123     while (element.readNextStartElement()) {
0124         const QStringView tagName = element.name();
0125         if (tagName == QLatin1StringView("str")) {
0126             mVariableName->setText(element.readElementText());
0127         } else {
0128             const QString result = tagName.toString();
0129             error += i18n("Unknown tag \"%1\" during loading of variables.", result) + QLatin1Char('\n');
0130             qCDebug(LIBKSIEVEUI_LOG) << " SieveGlobalVariableActionWidget::loadScript unknown tagName " << tagName;
0131         }
0132     }
0133 }
0134 
0135 void SieveGlobalVariableActionWidget::slotAddWidget()
0136 {
0137     Q_EMIT addWidget(this);
0138     Q_EMIT valueChanged();
0139 }
0140 
0141 void SieveGlobalVariableActionWidget::slotRemoveWidget()
0142 {
0143     Q_EMIT removeWidget(this);
0144     Q_EMIT valueChanged();
0145 }
0146 
0147 void SieveGlobalVariableActionWidget::updateAddRemoveButton(bool addButtonEnabled, bool removeButtonEnabled)
0148 {
0149     mAdd->setEnabled(addButtonEnabled);
0150     mRemove->setEnabled(removeButtonEnabled);
0151 }
0152 
0153 SieveGlobalVariableWidget::SieveGlobalVariableWidget(QWidget *parent)
0154     : SieveWidgetPageAbstract(parent)
0155 {
0156     auto lay = new QVBoxLayout(this);
0157     mHelpButton = new SieveHelpButton(this);
0158     lay->addWidget(mHelpButton);
0159     connect(mHelpButton, &SieveHelpButton::clicked, this, &SieveGlobalVariableWidget::slotHelp);
0160 
0161     mGlobalVariableLister = new SieveGlobalVariableLister(this);
0162     connect(mGlobalVariableLister, &SieveGlobalVariableLister::valueChanged, this, &SieveGlobalVariableWidget::valueChanged);
0163 
0164     auto scrollArea = new QScrollArea(this);
0165     scrollArea->setAutoFillBackground(false);
0166     scrollArea->setWidget(mGlobalVariableLister);
0167     scrollArea->setWidgetResizable(true);
0168     scrollArea->setAlignment(Qt::AlignTop);
0169     lay->addWidget(scrollArea);
0170 
0171     setPageType(KSieveUi::SieveScriptBlockWidget::GlobalVariable);
0172 }
0173 
0174 SieveGlobalVariableWidget::~SieveGlobalVariableWidget() = default;
0175 
0176 void SieveGlobalVariableWidget::slotHelp()
0177 {
0178     const QString help = i18n(
0179         "A variable has global scope in all scripts that have declared it with the \"global\" command.  If a script uses that variable name without declaring "
0180         "it global, the name specifies a separate, non-global variable within that script.");
0181     const QUrl href = KSieveUi::SieveEditorUtil::helpUrl(KSieveUi::SieveEditorUtil::GlobalVariable);
0182     const QString fullWhatsThis = AutoCreateScriptUtil::createFullWhatsThis(help, href.toString());
0183     QWhatsThis::showText(QCursor::pos(), fullWhatsThis, mHelpButton);
0184 }
0185 
0186 void SieveGlobalVariableWidget::generatedScript(QString &script, QStringList &requireModules, bool inForEveryPartLoop)
0187 {
0188     Q_UNUSED(inForEveryPartLoop)
0189     QString result;
0190     QStringList lst;
0191     mGlobalVariableLister->generatedScript(result, lst);
0192     if (!result.isEmpty()) {
0193         script += result;
0194         requireModules << lst;
0195     }
0196 }
0197 
0198 void SieveGlobalVariableWidget::loadScript(QXmlStreamReader &element, QString &error)
0199 {
0200     mGlobalVariableLister->loadScript(element, error);
0201 }
0202 
0203 SieveGlobalVariableActionWidget::VariableElement SieveGlobalVariableWidget::loadSetVariable(QXmlStreamReader &element, QString &error)
0204 {
0205     return mGlobalVariableLister->loadSetVariable(element, error);
0206 }
0207 
0208 SieveGlobalVariableLister::SieveGlobalVariableLister(QWidget *parent)
0209     : KPIM::KWidgetLister(false, MINIMUMGLOBALVARIABLEACTION, MAXIMUMGLOBALVARIABLEACTION, parent)
0210 {
0211     slotClear();
0212     updateAddRemoveButton();
0213 }
0214 
0215 SieveGlobalVariableLister::~SieveGlobalVariableLister() = default;
0216 
0217 void SieveGlobalVariableLister::slotAddWidget(QWidget *w)
0218 {
0219     addWidgetAfterThisWidget(w);
0220     updateAddRemoveButton();
0221 }
0222 
0223 void SieveGlobalVariableLister::slotRemoveWidget(QWidget *w)
0224 {
0225     removeWidget(w);
0226     updateAddRemoveButton();
0227 }
0228 
0229 void SieveGlobalVariableLister::updateAddRemoveButton()
0230 {
0231     QList<QWidget *> widgetList = widgets();
0232     const int numberOfWidget(widgetList.count());
0233     bool addButtonEnabled = false;
0234     bool removeButtonEnabled = false;
0235     if (numberOfWidget <= widgetsMinimum()) {
0236         addButtonEnabled = true;
0237         removeButtonEnabled = false;
0238     } else if (numberOfWidget >= widgetsMaximum()) {
0239         addButtonEnabled = false;
0240         removeButtonEnabled = true;
0241     } else {
0242         addButtonEnabled = true;
0243         removeButtonEnabled = true;
0244     }
0245     QList<QWidget *>::ConstIterator wIt = widgetList.constBegin();
0246     QList<QWidget *>::ConstIterator wEnd = widgetList.constEnd();
0247     for (; wIt != wEnd; ++wIt) {
0248         auto w = qobject_cast<SieveGlobalVariableActionWidget *>(*wIt);
0249         w->updateAddRemoveButton(addButtonEnabled, removeButtonEnabled);
0250     }
0251 }
0252 
0253 void SieveGlobalVariableLister::generatedScript(QString &script, QStringList &requireModules)
0254 {
0255     requireModules << QStringLiteral("include");
0256     const QList<QWidget *> widgetList = widgets();
0257     QList<QWidget *>::ConstIterator wIt = widgetList.constBegin();
0258     QList<QWidget *>::ConstIterator wEnd = widgetList.constEnd();
0259     for (; wIt != wEnd; ++wIt) {
0260         auto w = qobject_cast<SieveGlobalVariableActionWidget *>(*wIt);
0261         w->generatedScript(script);
0262     }
0263 }
0264 
0265 void SieveGlobalVariableLister::reconnectWidget(SieveGlobalVariableActionWidget *w)
0266 {
0267     connect(w, &SieveGlobalVariableActionWidget::addWidget, this, &SieveGlobalVariableLister::slotAddWidget, Qt::UniqueConnection);
0268     connect(w, &SieveGlobalVariableActionWidget::removeWidget, this, &SieveGlobalVariableLister::slotRemoveWidget, Qt::UniqueConnection);
0269     connect(w, &SieveGlobalVariableActionWidget::valueChanged, this, &SieveGlobalVariableLister::valueChanged, Qt::UniqueConnection);
0270 }
0271 
0272 void SieveGlobalVariableLister::clearWidget(QWidget *aWidget)
0273 {
0274     if (aWidget) {
0275         auto widget = static_cast<SieveGlobalVariableActionWidget *>(aWidget);
0276         widget->clear();
0277         updateAddRemoveButton();
0278     }
0279     Q_EMIT valueChanged();
0280 }
0281 
0282 QWidget *SieveGlobalVariableLister::createWidget(QWidget *parent)
0283 {
0284     auto w = new SieveGlobalVariableActionWidget(parent);
0285     reconnectWidget(w);
0286     return w;
0287 }
0288 
0289 void SieveGlobalVariableLister::loadScript(QXmlStreamReader &element, QString &error)
0290 {
0291     SieveGlobalVariableActionWidget *w = static_cast<SieveGlobalVariableActionWidget *>(widgets().constLast());
0292     if (w->isInitialized()) {
0293         addWidgetAfterThisWidget(widgets().constLast());
0294         w = static_cast<SieveGlobalVariableActionWidget *>(widgets().constLast());
0295     }
0296     w->loadScript(element, error);
0297 }
0298 
0299 SieveGlobalVariableActionWidget::VariableElement SieveGlobalVariableLister::loadSetVariable(QXmlStreamReader &element, QString & /*error*/)
0300 {
0301     SieveGlobalVariableActionWidget::VariableElement var;
0302     QString variableName;
0303     QString variableValue;
0304     int index = 0;
0305     while (element.readNextStartElement()) {
0306         const QStringView tagName = element.name();
0307         if (tagName == QLatin1StringView("str")) {
0308             if (index == 0) {
0309                 variableName = element.readElementText();
0310             } else if (index == 1) {
0311                 variableValue = element.readElementText();
0312             } else {
0313                 qCDebug(LIBKSIEVEUI_LOG) << " SieveGlobalVariableLister::loadSetVariable too many argument:" << index;
0314             }
0315             ++index;
0316         } else {
0317             qCDebug(LIBKSIEVEUI_LOG) << " SieveGlobalVariableLister::loadSetVariable unknown tagName " << tagName;
0318         }
0319     }
0320 
0321     const QList<QWidget *> lstWidget = widgets();
0322     bool globalVariableFound = false;
0323     for (QWidget *widget : lstWidget) {
0324         auto w = static_cast<SieveGlobalVariableActionWidget *>(widget);
0325         if (w->variableName() == variableName) {
0326             w->setVariableValue(variableValue);
0327             globalVariableFound = true;
0328         }
0329     }
0330     if (!globalVariableFound) {
0331         var.variableName = variableName;
0332         var.variableValue = variableValue;
0333     }
0334     return var;
0335 }
0336 
0337 #include "moc_sieveglobalvariablewidget.cpp"