Libksieve

sieveincludewidget.cpp
1 /*
2  Copyright (C) 2013-2020 Laurent Montel <[email protected]>
3 
4  This library is free software; you can redistribute it and/or
5  modify it under the terms of the GNU Library General Public
6  License as published by the Free Software Foundation; either
7  version 2 of the License, or (at your option) any later version.
8 
9  This library is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  Library General Public License for more details.
13 
14  You should have received a copy of the GNU Library General Public License
15  along with this library; see the file COPYING.LIB. If not, write to
16  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17  Boston, MA 02110-1301, USA.
18 */
19 
20 #include "sieveincludewidget.h"
21 #include "sievescriptblockwidget.h"
22 #include "autocreatescriptutil_p.h"
23 #include "commonwidgets/sievehelpbutton.h"
24 #include "autocreatescripts/autocreatescriptutil_p.h"
25 #include "editor/sieveeditorutil.h"
26 #include "widgets/includefilelineedit.h"
27 
28 #include <QPushButton>
29 #include <KLocalizedString>
30 #include <QIcon>
31 
32 #include <QGridLayout>
33 #include <QCheckBox>
34 #include <QLabel>
35 #include <QWhatsThis>
36 #include <QXmlStreamReader>
37 #include "libksieve_debug.h"
38 
39 using namespace KSieveUi;
40 
41 static const int MINIMUMINCLUDEACTION = 1;
42 static const int MAXIMUMINCLUDEACTION = 20;
43 
44 SieveIncludeLocation::SieveIncludeLocation(QWidget *parent)
45  : QComboBox(parent)
46 {
47  initialize();
48  connect(this, QOverload<int>::of(&SieveIncludeLocation::activated), this, &SieveIncludeLocation::valueChanged);
49 }
50 
51 SieveIncludeLocation::~SieveIncludeLocation()
52 {
53 }
54 
55 void SieveIncludeLocation::initialize()
56 {
57  addItem(i18n("personal"), QStringLiteral(":personal"));
58  addItem(i18n("global"), QStringLiteral(":global"));
59 }
60 
61 QString SieveIncludeLocation::code() const
62 {
63  return itemData(currentIndex()).toString();
64 }
65 
66 void SieveIncludeLocation::setCode(const QString &code, QString &error)
67 {
68  const int index = findData(code);
69  if (index != -1) {
70  setCurrentIndex(index);
71  } else {
72  error += i18n("Unknown location type \"%1\" during parsing includes", code) + QLatin1Char('\n');
73  setCurrentIndex(0);
74  }
75 }
76 
77 SieveIncludeActionWidget::SieveIncludeActionWidget(QWidget *parent)
78  : QWidget(parent)
79 {
80  initWidget();
81 }
82 
83 SieveIncludeActionWidget::~SieveIncludeActionWidget()
84 {
85 }
86 
87 void SieveIncludeActionWidget::clear()
88 {
89  mOptional->setChecked(false);
90  mOnce->setChecked(false);
91  mLocation->setCurrentIndex(0);
92  mIncludeFileName->clear();
93 }
94 
95 void SieveIncludeActionWidget::setListOfIncludeFile(const QStringList &listOfIncludeFile)
96 {
97  mIncludeFileName->setListOfIncludeFile(listOfIncludeFile);
98 }
99 
100 void SieveIncludeActionWidget::loadScript(QXmlStreamReader &element, QString &error)
101 {
102  while (element.readNextStartElement()) {
103  const QStringRef tagName = element.name();
104  if (tagName == QLatin1String("tag")) {
105  const QString tagValue = element.readElementText();
106  if (tagValue == QLatin1String("personal")
107  || tagValue == QLatin1String("global")) {
108  mLocation->setCode(AutoCreateScriptUtil::tagValue(tagValue), error);
109  } else if (tagValue == QLatin1String("optional")) {
110  mOptional->setChecked(true);
111  } else if (tagValue == QLatin1String("once")) {
112  mOnce->setChecked(true);
113  } else {
114  qCDebug(LIBKSIEVE_LOG) << " SieveIncludeActionWidget::loadScript unknown tagValue " << tagValue;
115  }
116  } else if (tagName == QLatin1String("str")) {
117  mIncludeFileName->setText(element.readElementText());
118  } else {
119  qCDebug(LIBKSIEVE_LOG) << " SieveIncludeActionWidget::loadScript unknown tagName " << tagName;
120  }
121  }
122 }
123 
124 void SieveIncludeActionWidget::generatedScript(QString &script)
125 {
126  const QString includeName = mIncludeFileName->text();
127  if (includeName.trimmed().isEmpty()) {
128  return;
129  }
130  script += QLatin1String("include ");
131  script += mLocation->code() + QLatin1Char(' ');
132  if (mOptional->isChecked()) {
133  script += QLatin1String(":optional ");
134  }
135  if (mOnce->isChecked()) {
136  script += QLatin1String(":once ");
137  }
138  script += QStringLiteral("\"%1\";\n").arg(includeName);
139 }
140 
141 void SieveIncludeActionWidget::initWidget()
142 {
143  mLayout = new QGridLayout(this);
144  mLayout->setContentsMargins(0, 0, 0, 0);
145 
146  QLabel *lab = new QLabel(i18n("Include:"));
147  mLayout->addWidget(lab, 1, 0);
148  mLocation = new SieveIncludeLocation(this);
149  connect(mLocation, &SieveIncludeLocation::valueChanged, this, &SieveIncludeActionWidget::valueChanged);
150  mLayout->addWidget(mLocation, 1, 1);
151 
152  lab = new QLabel(i18n("Name:"));
153  mLayout->addWidget(lab, 1, 2);
154 
155  mIncludeFileName = new IncludeFileLineEdit(this);
156  mIncludeFileName->setClearButtonEnabled(true);
157  connect(mIncludeFileName, &QLineEdit::textChanged, this, &SieveIncludeActionWidget::valueChanged);
158  mLayout->addWidget(mIncludeFileName, 1, 3);
159 
160  mOptional = new QCheckBox(i18n("Optional"));
161  connect(mOptional, &QCheckBox::toggled, this, &SieveIncludeActionWidget::valueChanged);
162  mLayout->addWidget(mOptional, 1, 4);
163 
164  mOnce = new QCheckBox(i18n("Once"));
165  connect(mOnce, &QCheckBox::toggled, this, &SieveIncludeActionWidget::valueChanged);
166  mLayout->addWidget(mOnce, 1, 5);
167 
168  mAdd = new QPushButton(this);
169  mAdd->setIcon(QIcon::fromTheme(QStringLiteral("list-add")));
170  mAdd->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed));
171 
172  mRemove = new QPushButton(this);
173  mRemove->setIcon(QIcon::fromTheme(QStringLiteral("list-remove")));
174  mRemove->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed));
175  mLayout->addWidget(mAdd, 1, 6);
176  mLayout->addWidget(mRemove, 1, 7);
177 
178  connect(mAdd, &QPushButton::clicked, this, &SieveIncludeActionWidget::slotAddWidget);
179  connect(mRemove, &QPushButton::clicked, this, &SieveIncludeActionWidget::slotRemoveWidget);
180 }
181 
182 void SieveIncludeActionWidget::slotAddWidget()
183 {
184  Q_EMIT valueChanged();
185  Q_EMIT addWidget(this);
186 }
187 
188 void SieveIncludeActionWidget::slotRemoveWidget()
189 {
190  Q_EMIT valueChanged();
191  Q_EMIT removeWidget(this);
192 }
193 
194 bool SieveIncludeActionWidget::isInitialized() const
195 {
196  return !mIncludeFileName->text().isEmpty();
197 }
198 
199 void SieveIncludeActionWidget::updateAddRemoveButton(bool addButtonEnabled, bool removeButtonEnabled)
200 {
201  mAdd->setEnabled(addButtonEnabled);
202  mRemove->setEnabled(removeButtonEnabled);
203 }
204 
205 SieveIncludeWidget::SieveIncludeWidget(QWidget *parent)
206  : SieveWidgetPageAbstract(parent)
207 {
208  QVBoxLayout *lay = new QVBoxLayout(this);
209  mHelpButton = new SieveHelpButton(this);
210  lay->addWidget(mHelpButton);
211  connect(mHelpButton, &SieveHelpButton::clicked, this, &SieveIncludeWidget::slotHelp);
212 
213  mIncludeLister = new SieveIncludeWidgetLister(this);
214  connect(mIncludeLister, &SieveIncludeWidgetLister::valueChanged, this, &SieveIncludeWidget::valueChanged);
215  lay->addWidget(mIncludeLister, 0, Qt::AlignTop);
216  setPageType(KSieveUi::SieveScriptBlockWidget::Include);
217 }
218 
219 SieveIncludeWidget::~SieveIncludeWidget()
220 {
221 }
222 
223 void SieveIncludeWidget::setListOfIncludeFile(const QStringList &lst)
224 {
225  mIncludeLister->setListOfIncludeFile(lst);
226 }
227 
228 void SieveIncludeWidget::slotHelp()
229 {
230  const QString help = i18n(
231  "The \"include\" command takes an optional \"location\" parameter, an optional \":once\" parameter, an optional \":optional\" parameter, and a single string argument representing the name of the script to include for processing at that point.");
232  const QString href = QStringLiteral("https://tools.ietf.org/html/rfc6609#page-4");
233  const QString fullWhatsThis = AutoCreateScriptUtil::createFullWhatsThis(help, href);
234  QWhatsThis::showText(QCursor::pos(), fullWhatsThis, mHelpButton);
235 }
236 
237 void SieveIncludeWidget::generatedScript(QString &script, QStringList &requireModules, bool inForEveryPartLoop)
238 {
239  Q_UNUSED(inForEveryPartLoop);
240  QString result;
241  QStringList lst;
242  mIncludeLister->generatedScript(result, lst);
243  if (!result.isEmpty()) {
244  script += result;
245  requireModules << lst;
246  }
247 }
248 
249 void SieveIncludeWidget::loadScript(QXmlStreamReader &element, QString &error)
250 {
251  mIncludeLister->loadScript(element, error);
252 }
253 
254 SieveIncludeWidgetLister::SieveIncludeWidgetLister(QWidget *parent)
255  : KPIM::KWidgetLister(false, MINIMUMINCLUDEACTION, MAXIMUMINCLUDEACTION, parent)
256 {
257  slotClear();
258  updateAddRemoveButton();
259 }
260 
261 SieveIncludeWidgetLister::~SieveIncludeWidgetLister()
262 {
263 }
264 
265 void SieveIncludeWidgetLister::slotAddWidget(QWidget *w)
266 {
267  addWidgetAfterThisWidget(w);
268  updateAddRemoveButton();
269 }
270 
271 void SieveIncludeWidgetLister::slotRemoveWidget(QWidget *w)
272 {
273  removeWidget(w);
274  updateAddRemoveButton();
275 }
276 
277 void SieveIncludeWidgetLister::updateAddRemoveButton()
278 {
279  QList<QWidget *> widgetList = widgets();
280  const int numberOfWidget(widgetList.count());
281  bool addButtonEnabled = false;
282  bool removeButtonEnabled = false;
283  if (numberOfWidget <= widgetsMinimum()) {
284  addButtonEnabled = true;
285  removeButtonEnabled = false;
286  } else if (numberOfWidget >= widgetsMaximum()) {
287  addButtonEnabled = false;
288  removeButtonEnabled = true;
289  } else {
290  addButtonEnabled = true;
291  removeButtonEnabled = true;
292  }
293  QList<QWidget *>::ConstIterator wIt = widgetList.constBegin();
294  QList<QWidget *>::ConstIterator wEnd = widgetList.constEnd();
295  for (; wIt != wEnd; ++wIt) {
296  SieveIncludeActionWidget *w = qobject_cast<SieveIncludeActionWidget *>(*wIt);
297  w->updateAddRemoveButton(addButtonEnabled, removeButtonEnabled);
298  }
299 }
300 
301 void SieveIncludeWidgetLister::setListOfIncludeFile(const QStringList &listOfIncludeFile)
302 {
303  mListOfIncludeFile = listOfIncludeFile;
304  //Update all lineedit
305  const QList<QWidget *> widgetList = widgets();
306  QList<QWidget *>::ConstIterator wIt = widgetList.constBegin();
307  QList<QWidget *>::ConstIterator wEnd = widgetList.constEnd();
308  for (; wIt != wEnd; ++wIt) {
309  SieveIncludeActionWidget *w = qobject_cast<SieveIncludeActionWidget *>(*wIt);
310  w->setListOfIncludeFile(mListOfIncludeFile);
311  }
312 }
313 
314 void SieveIncludeWidgetLister::generatedScript(QString &script, QStringList &requireModules)
315 {
316  requireModules << QStringLiteral("include");
317  const QList<QWidget *> widgetList = widgets();
318  QList<QWidget *>::ConstIterator wIt = widgetList.constBegin();
319  QList<QWidget *>::ConstIterator wEnd = widgetList.constEnd();
320  for (; wIt != wEnd; ++wIt) {
321  SieveIncludeActionWidget *w = qobject_cast<SieveIncludeActionWidget *>(*wIt);
322  w->generatedScript(script);
323  }
324 }
325 
326 void SieveIncludeWidgetLister::reconnectWidget(SieveIncludeActionWidget *w)
327 {
328  connect(w, &SieveIncludeActionWidget::addWidget, this, &SieveIncludeWidgetLister::slotAddWidget, Qt::UniqueConnection);
329  connect(w, &SieveIncludeActionWidget::removeWidget, this, &SieveIncludeWidgetLister::slotRemoveWidget, Qt::UniqueConnection);
330  connect(w, &SieveIncludeActionWidget::valueChanged, this, &SieveIncludeWidgetLister::valueChanged, Qt::UniqueConnection);
331 }
332 
333 void SieveIncludeWidgetLister::clearWidget(QWidget *aWidget)
334 {
335  if (aWidget) {
336  SieveIncludeActionWidget *widget = static_cast<SieveIncludeActionWidget *>(aWidget);
337  widget->clear();
338  }
339  Q_EMIT valueChanged();
340 }
341 
342 QWidget *SieveIncludeWidgetLister::createWidget(QWidget *parent)
343 {
344  SieveIncludeActionWidget *w = new SieveIncludeActionWidget(parent);
345  w->setListOfIncludeFile(mListOfIncludeFile);
346  reconnectWidget(w);
347  return w;
348 }
349 
350 void SieveIncludeWidgetLister::loadScript(QXmlStreamReader &element, QString &error)
351 {
352  if (widgets().count() == MAXIMUMINCLUDEACTION) {
353  error += QLatin1Char('\n') + i18n("We can not add more includes elements.") + QLatin1Char('\n');
354  return;
355  }
356  SieveIncludeActionWidget *w = static_cast<SieveIncludeActionWidget *>(widgets().constLast());
357  if (w->isInitialized()) {
358  addWidgetAfterThisWidget(widgets().constLast());
359  w = static_cast<SieveIncludeActionWidget *>(widgets().constLast());
360  }
361  w->loadScript(element, error);
362 }
void showText(const QPoint &pos, const QString &text, QWidget *w)
bool readNextStartElement()
KCRASH_EXPORT void initialize()
void textChanged(const QString &text)
AlignTop
void addWidget(QWidget *widget, int stretch, Qt::Alignment alignment)
int count(const T &value) const const
const QList< QKeySequence > & help()
QString readElementText(QXmlStreamReader::ReadElementTextBehaviour behaviour)
bool isEmpty() const const
QString trimmed() const const
void clicked(bool checked)
QString i18n(const char *text, const TYPE &arg...)
QPoint pos()
QString arg(qlonglong a, int fieldWidth, int base, QChar fillChar) const const
void toggled(bool checked)
QIcon fromTheme(const QString &name)
QList::const_iterator constEnd() const const
QList::const_iterator constBegin() const const
UniqueConnection
QStringRef name() const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Mon Aug 10 2020 23:12:59 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.