Libksieve

sieveglobalvariablewidget.cpp
1/*
2 SPDX-FileCopyrightText: 2013-2024 Laurent Montel <montel@kde.org>
3
4 SPDX-License-Identifier: LGPL-2.0-or-later
5*/
6
7#include "sieveglobalvariablewidget.h"
8#include "autocreatescriptutil_p.h"
9#include "commonwidgets/sievehelpbutton.h"
10#include "editor/sieveeditorutil.h"
11#include "sievescriptblockwidget.h"
12#include "widgets/lineeditvalidator.h"
13
14#include <KLineEditEventHandler>
15#include <KLocalizedString>
16#include <QIcon>
17#include <QLineEdit>
18#include <QPushButton>
19
20#include "libksieveui_debug.h"
21#include <QCheckBox>
22#include <QGridLayout>
23#include <QLabel>
24#include <QScrollArea>
25#include <QWhatsThis>
26#include <QXmlStreamReader>
27
28using namespace KSieveUi;
29static const int MINIMUMGLOBALVARIABLEACTION = 1;
30static const int MAXIMUMGLOBALVARIABLEACTION = 15;
31
32SieveGlobalVariableActionWidget::SieveGlobalVariableActionWidget(QWidget *parent)
33 : QWidget(parent)
34{
35 initWidget();
36}
37
38SieveGlobalVariableActionWidget::~SieveGlobalVariableActionWidget() = default;
39
40void SieveGlobalVariableActionWidget::generatedScript(QString &script)
41{
42 const QString variableName = mVariableName->text();
43 if (variableName.trimmed().isEmpty()) {
44 return;
45 }
46 script += QLatin1StringView("global ");
47 script += QStringLiteral("\"%1\";\n").arg(variableName);
48 if (mSetValueTo->isChecked() && !mVariableValue->text().isEmpty()) {
49 script += QStringLiteral("set \"%1\" \"%2\";\n").arg(variableName, mVariableValue->text());
50 }
51}
52
53void SieveGlobalVariableActionWidget::initWidget()
54{
55 mLayout = new QGridLayout(this);
56 mLayout->setContentsMargins({});
57
58 auto lab = new QLabel(i18nc("@label:textbox", "Variable name:"), this);
59 mLayout->addWidget(lab, 1, 0);
60
61 mVariableName = new LineEditValidator(this);
62 connect(mVariableName, &QLineEdit::textChanged, this, &SieveGlobalVariableActionWidget::valueChanged);
63 mLayout->addWidget(mVariableName, 1, 1);
64
65 mSetValueTo = new QCheckBox(i18nc("@option:check", "Set value to:"), this);
66 connect(mSetValueTo, &QCheckBox::toggled, this, &SieveGlobalVariableActionWidget::valueChanged);
67 mLayout->addWidget(mSetValueTo, 1, 2);
68 mSetValueTo->setChecked(false);
69
70 mVariableValue = new QLineEdit(this);
72 connect(mVariableValue, &QLineEdit::textChanged, this, &SieveGlobalVariableActionWidget::valueChanged);
73 mVariableValue->setEnabled(false);
74 mLayout->addWidget(mVariableValue, 1, 3);
75
76 connect(mSetValueTo, &QCheckBox::clicked, mVariableValue, &QLineEdit::setEnabled);
77
78 mAdd = new QPushButton(this);
79 mAdd->setIcon(QIcon::fromTheme(QStringLiteral("list-add")));
81
82 mRemove = new QPushButton(this);
83 mRemove->setIcon(QIcon::fromTheme(QStringLiteral("list-remove")));
85 mLayout->addWidget(mAdd, 1, 4);
86 mLayout->addWidget(mRemove, 1, 5);
87
88 connect(mAdd, &QPushButton::clicked, this, &SieveGlobalVariableActionWidget::slotAddWidget);
89 connect(mRemove, &QPushButton::clicked, this, &SieveGlobalVariableActionWidget::slotRemoveWidget);
90}
91
92void SieveGlobalVariableActionWidget::clear()
93{
94 mVariableName->clear();
95 mSetValueTo->setChecked(false);
96 mVariableValue->setEnabled(false);
97 mVariableValue->clear();
98}
99
100bool SieveGlobalVariableActionWidget::isInitialized() const
101{
102 return !mVariableName->text().isEmpty();
103}
104
105QString SieveGlobalVariableActionWidget::variableName() const
106{
107 const QString varName = mVariableName->text();
108 if (varName.trimmed().isEmpty()) {
109 return {};
110 }
111 return varName;
112}
113
114void SieveGlobalVariableActionWidget::setVariableValue(const QString &name)
115{
116 mSetValueTo->setChecked(true);
117 mVariableValue->setText(name);
118 mVariableValue->setEnabled(true);
119}
120
121void SieveGlobalVariableActionWidget::loadScript(QXmlStreamReader &element, QString &error)
122{
123 while (element.readNextStartElement()) {
124 const QStringView tagName = element.name();
125 if (tagName == QLatin1StringView("str")) {
126 mVariableName->setText(element.readElementText());
127 } else {
128 const QString result = tagName.toString();
129 error += i18n("Unknown tag \"%1\" during loading of variables.", result) + QLatin1Char('\n');
130 qCDebug(LIBKSIEVEUI_LOG) << " SieveGlobalVariableActionWidget::loadScript unknown tagName " << tagName;
131 }
132 }
133}
134
135void SieveGlobalVariableActionWidget::slotAddWidget()
136{
137 Q_EMIT addWidget(this);
138 Q_EMIT valueChanged();
139}
140
141void SieveGlobalVariableActionWidget::slotRemoveWidget()
142{
143 Q_EMIT removeWidget(this);
144 Q_EMIT valueChanged();
145}
146
147void SieveGlobalVariableActionWidget::updateAddRemoveButton(bool addButtonEnabled, bool removeButtonEnabled)
148{
149 mAdd->setEnabled(addButtonEnabled);
150 mRemove->setEnabled(removeButtonEnabled);
151}
152
153SieveGlobalVariableWidget::SieveGlobalVariableWidget(QWidget *parent)
154 : SieveWidgetPageAbstract(parent)
155{
156 auto lay = new QVBoxLayout(this);
157 mHelpButton = new SieveHelpButton(this);
158 lay->addWidget(mHelpButton);
159 connect(mHelpButton, &SieveHelpButton::clicked, this, &SieveGlobalVariableWidget::slotHelp);
160
161 mGlobalVariableLister = new SieveGlobalVariableLister(this);
162 connect(mGlobalVariableLister, &SieveGlobalVariableLister::valueChanged, this, &SieveGlobalVariableWidget::valueChanged);
163
164 auto scrollArea = new QScrollArea(this);
165 scrollArea->setAutoFillBackground(false);
166 scrollArea->setWidget(mGlobalVariableLister);
167 scrollArea->setWidgetResizable(true);
168 scrollArea->setAlignment(Qt::AlignTop);
169 lay->addWidget(scrollArea);
170
171 setPageType(KSieveUi::SieveScriptBlockWidget::GlobalVariable);
172}
173
174SieveGlobalVariableWidget::~SieveGlobalVariableWidget() = default;
175
176void SieveGlobalVariableWidget::slotHelp()
177{
178 const QString help = i18n(
179 "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 "
180 "it global, the name specifies a separate, non-global variable within that script.");
181 const QUrl href = KSieveUi::SieveEditorUtil::helpUrl(KSieveUi::SieveEditorUtil::GlobalVariable);
182 const QString fullWhatsThis = AutoCreateScriptUtil::createFullWhatsThis(help, href.toString());
183 QWhatsThis::showText(QCursor::pos(), fullWhatsThis, mHelpButton);
184}
185
186void SieveGlobalVariableWidget::generatedScript(QString &script, QStringList &requireModules, bool inForEveryPartLoop)
187{
188 Q_UNUSED(inForEveryPartLoop)
189 QString result;
190 QStringList lst;
191 mGlobalVariableLister->generatedScript(result, lst);
192 if (!result.isEmpty()) {
193 script += result;
194 requireModules << lst;
195 }
196}
197
198void SieveGlobalVariableWidget::loadScript(QXmlStreamReader &element, QString &error)
199{
200 mGlobalVariableLister->loadScript(element, error);
201}
202
203SieveGlobalVariableActionWidget::VariableElement SieveGlobalVariableWidget::loadSetVariable(QXmlStreamReader &element, QString &error)
204{
205 return mGlobalVariableLister->loadSetVariable(element, error);
206}
207
208SieveGlobalVariableLister::SieveGlobalVariableLister(QWidget *parent)
209 : KPIM::KWidgetLister(false, MINIMUMGLOBALVARIABLEACTION, MAXIMUMGLOBALVARIABLEACTION, parent)
210{
211 slotClear();
212 updateAddRemoveButton();
213}
214
215SieveGlobalVariableLister::~SieveGlobalVariableLister() = default;
216
217void SieveGlobalVariableLister::slotAddWidget(QWidget *w)
218{
220 updateAddRemoveButton();
221}
222
223void SieveGlobalVariableLister::slotRemoveWidget(QWidget *w)
224{
225 removeWidget(w);
226 updateAddRemoveButton();
227}
228
229void SieveGlobalVariableLister::updateAddRemoveButton()
230{
231 QList<QWidget *> widgetList = widgets();
232 const int numberOfWidget(widgetList.count());
233 bool addButtonEnabled = false;
234 bool removeButtonEnabled = false;
235 if (numberOfWidget <= widgetsMinimum()) {
236 addButtonEnabled = true;
237 removeButtonEnabled = false;
238 } else if (numberOfWidget >= widgetsMaximum()) {
239 addButtonEnabled = false;
240 removeButtonEnabled = true;
241 } else {
242 addButtonEnabled = true;
243 removeButtonEnabled = true;
244 }
246 QList<QWidget *>::ConstIterator wEnd = widgetList.constEnd();
247 for (; wIt != wEnd; ++wIt) {
249 w->updateAddRemoveButton(addButtonEnabled, removeButtonEnabled);
250 }
251}
252
253void SieveGlobalVariableLister::generatedScript(QString &script, QStringList &requireModules)
254{
255 requireModules << QStringLiteral("include");
256 const QList<QWidget *> widgetList = widgets();
258 QList<QWidget *>::ConstIterator wEnd = widgetList.constEnd();
259 for (; wIt != wEnd; ++wIt) {
261 w->generatedScript(script);
262 }
263}
264
265void SieveGlobalVariableLister::reconnectWidget(SieveGlobalVariableActionWidget *w)
266{
267 connect(w, &SieveGlobalVariableActionWidget::addWidget, this, &SieveGlobalVariableLister::slotAddWidget, Qt::UniqueConnection);
268 connect(w, &SieveGlobalVariableActionWidget::removeWidget, this, &SieveGlobalVariableLister::slotRemoveWidget, Qt::UniqueConnection);
269 connect(w, &SieveGlobalVariableActionWidget::valueChanged, this, &SieveGlobalVariableLister::valueChanged, Qt::UniqueConnection);
270}
271
272void SieveGlobalVariableLister::clearWidget(QWidget *aWidget)
273{
274 if (aWidget) {
275 auto widget = static_cast<SieveGlobalVariableActionWidget *>(aWidget);
276 widget->clear();
277 updateAddRemoveButton();
278 }
279 Q_EMIT valueChanged();
280}
281
282QWidget *SieveGlobalVariableLister::createWidget(QWidget *parent)
283{
284 auto w = new SieveGlobalVariableActionWidget(parent);
285 reconnectWidget(w);
286 return w;
287}
288
289void SieveGlobalVariableLister::loadScript(QXmlStreamReader &element, QString &error)
290{
291 SieveGlobalVariableActionWidget *w = static_cast<SieveGlobalVariableActionWidget *>(widgets().constLast());
292 if (w->isInitialized()) {
293 addWidgetAfterThisWidget(widgets().constLast());
294 w = static_cast<SieveGlobalVariableActionWidget *>(widgets().constLast());
295 }
296 w->loadScript(element, error);
297}
298
299SieveGlobalVariableActionWidget::VariableElement SieveGlobalVariableLister::loadSetVariable(QXmlStreamReader &element, QString & /*error*/)
300{
301 SieveGlobalVariableActionWidget::VariableElement var;
302 QString variableName;
303 QString variableValue;
304 int index = 0;
305 while (element.readNextStartElement()) {
306 const QStringView tagName = element.name();
307 if (tagName == QLatin1StringView("str")) {
308 if (index == 0) {
309 variableName = element.readElementText();
310 } else if (index == 1) {
311 variableValue = element.readElementText();
312 } else {
313 qCDebug(LIBKSIEVEUI_LOG) << " SieveGlobalVariableLister::loadSetVariable too many argument:" << index;
314 }
315 ++index;
316 } else {
317 qCDebug(LIBKSIEVEUI_LOG) << " SieveGlobalVariableLister::loadSetVariable unknown tagName " << tagName;
318 }
319 }
320
321 const QList<QWidget *> lstWidget = widgets();
322 bool globalVariableFound = false;
323 for (QWidget *widget : lstWidget) {
324 auto w = static_cast<SieveGlobalVariableActionWidget *>(widget);
325 if (w->variableName() == variableName) {
326 w->setVariableValue(variableValue);
327 globalVariableFound = true;
328 }
329 }
330 if (!globalVariableFound) {
331 var.variableName = variableName;
332 var.variableValue = variableValue;
333 }
334 return var;
335}
336
337#include "moc_sieveglobalvariablewidget.cpp"
virtual void addWidgetAfterThisWidget(QWidget *currentWidget, QWidget *widget=nullptr)
virtual void removeWidget(QWidget *widget)
int widgetsMaximum() const
QList< QWidget * > widgets() const
int widgetsMinimum() const
QString i18nc(const char *context, const char *text, const TYPE &arg...)
QString i18n(const char *text, const TYPE &arg...)
void catchReturnKey(QObject *lineEdit)
void error(QWidget *parent, const QString &text, const QString &title, const KGuiItem &buttonOk, Options options=Notify)
const QList< QKeySequence > & help()
bool isChecked() const const
void clicked(bool checked)
void setIcon(const QIcon &icon)
void toggled(bool checked)
QPoint pos()
void addWidget(QWidget *widget, int fromRow, int fromColumn, int rowSpan, int columnSpan, Qt::Alignment alignment)
QIcon fromTheme(const QString &name)
void setContentsMargins(const QMargins &margins)
void clear()
void textChanged(const QString &text)
const_iterator constBegin() const const
const_iterator constEnd() const const
qsizetype count() const const
Q_EMITQ_EMIT
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
QObject * parent() const const
T qobject_cast(QObject *object)
QString arg(Args &&... args) const const
bool isEmpty() const const
QString trimmed() const const
QString toString() const const
AlignTop
UniqueConnection
QFuture< ArgsType< Signal > > connect(Sender *sender, Signal signal)
QString toString(FormattingOptions options) const const
void showText(const QPoint &pos, const QString &text, QWidget *w)
void setEnabled(bool)
void setSizePolicy(QSizePolicy)
QStringView name() const const
QString readElementText(ReadElementTextBehaviour behaviour)
bool readNextStartElement()
This file is part of the KDE documentation.
Documentation copyright © 1996-2024 The KDE developers.
Generated on Mon Nov 18 2024 12:14:30 by doxygen 1.12.0 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.