Libksieve

sievescriptblockwidget.cpp
1 /*
2  SPDX-FileCopyrightText: 2013-2021 Laurent Montel <[email protected]>
3 
4  SPDX-License-Identifier: LGPL-2.0-or-later
5 */
6 
7 #include "sievescriptblockwidget.h"
8 #include "autocreatescriptutil_p.h"
9 #include "sieveactionwidgetlister.h"
10 #include "sieveconditionwidgetlister.h"
11 
12 #include <KLocalizedString>
13 #include <QComboBox>
14 #include <QIcon>
15 #include <QPushButton>
16 
17 #include "libksieve_debug.h"
18 #include <QButtonGroup>
19 #include <QGroupBox>
20 #include <QLabel>
21 #include <QRadioButton>
22 #include <QVBoxLayout>
23 #include <QXmlStreamReader>
24 
25 using namespace KSieveUi;
26 
27 SieveScriptBlockWidget::SieveScriptBlockWidget(SieveEditorGraphicalModeWidget *graphicalModeWidget, QWidget *parent)
28  : SieveWidgetPageAbstract(parent)
29  , mSieveGraphicalModeWidget(graphicalModeWidget)
30 {
31  auto topLayout = new QVBoxLayout(this);
32  topLayout->setContentsMargins({});
33 
34  mConditions = new QGroupBox(i18n("Conditions"), this);
35  auto vbox = new QVBoxLayout;
36 
37  mAllMessageRBtn = new QRadioButton(i18n("Match all messages"), this);
38  mMatchAll = new QRadioButton(i18n("Match a&ll of the following"), this);
39  mMatchAny = new QRadioButton(i18n("Match an&y of the following"), this);
40 
41  vbox->addWidget(mMatchAll);
42  vbox->addWidget(mMatchAny);
43  vbox->addWidget(mAllMessageRBtn);
44  mMatchAll->setChecked(true);
45  mMatchAny->setChecked(false);
46  mAllMessageRBtn->setChecked(false);
47 
48  auto bg = new QButtonGroup(this);
49  bg->addButton(mMatchAll);
50  bg->addButton(mMatchAny);
51  bg->addButton(mAllMessageRBtn);
52 
53  connect(bg, QOverload<QAbstractButton *>::of(&QButtonGroup::buttonClicked), this, &SieveScriptBlockWidget::slotRadioClicked);
54  mConditions->setLayout(vbox);
55 
56  mScriptConditionLister = new SieveConditionWidgetLister(mSieveGraphicalModeWidget, this);
57  connect(mScriptConditionLister, &SieveConditionWidgetLister::valueChanged, this, &SieveScriptBlockWidget::valueChanged);
58  vbox->addWidget(mScriptConditionLister);
59 
60  topLayout->addWidget(mConditions, 0, Qt::AlignTop);
61 
62  auto actions = new QGroupBox(i18n("Actions"), this);
63  vbox = new QVBoxLayout;
64  actions->setLayout(vbox);
65  mScriptActionLister = new SieveActionWidgetLister(mSieveGraphicalModeWidget, this);
66  connect(mScriptActionLister, &SieveActionWidgetLister::valueChanged, this, &SieveScriptBlockWidget::valueChanged);
67  vbox->addWidget(mScriptActionLister, 0, Qt::AlignTop);
68  topLayout->addWidget(actions);
69 
70  auto newBlockLayout = new QHBoxLayout;
71  auto lab = new QLabel(i18n("Add new block:"));
72  newBlockLayout->addWidget(lab);
73  mNewBlockType = new QComboBox(this);
74  newBlockLayout->addWidget(mNewBlockType);
75  mNewBlockType->addItem(i18n("\"elsif\" block"));
76  mNewBlockType->addItem(i18n("\"else\" block"));
77 
78  mAddBlockType = new QPushButton(this);
79  mAddBlockType->setIcon(QIcon::fromTheme(QStringLiteral("list-add")));
80  mAddBlockType->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed));
81  newBlockLayout->addWidget(mAddBlockType);
82  connect(mAddBlockType, &QPushButton::clicked, this, &SieveScriptBlockWidget::slotAddBlock);
83 
84  topLayout->addLayout(newBlockLayout);
85 }
86 
87 SieveScriptBlockWidget::~SieveScriptBlockWidget()
88 {
89 }
90 
91 void SieveScriptBlockWidget::slotAddBlock()
92 {
93  KSieveUi::SieveWidgetPageAbstract::PageType type = BlockElsIf;
94  switch (mNewBlockType->currentIndex()) {
95  case 0:
96  type = BlockElsIf;
97  break;
98  case 1:
99  type = BlockElse;
100  break;
101  }
102 
103  Q_EMIT valueChanged();
104  Q_EMIT addNewBlock(this, type);
105 }
106 
107 void SieveScriptBlockWidget::setPageType(PageType type)
108 {
109  if (pageType() != type) {
110  SieveWidgetPageAbstract::setPageType(type);
111  switch (type) {
112  case BlockIf:
113  mAllMessageRBtn->show();
114  mConditions->show();
115  mAddBlockType->setEnabled(true);
116  mNewBlockType->setEnabled(true);
117  break;
118  case BlockElsIf:
119  mAllMessageRBtn->hide();
120  mConditions->show();
121  mAddBlockType->setEnabled(true);
122  mNewBlockType->setEnabled(true);
123  break;
124  case BlockElse:
125  mAllMessageRBtn->hide();
126  mConditions->hide();
127  mAddBlockType->setEnabled(false);
128  mNewBlockType->setEnabled(false);
129  break;
130  default:
131  break;
132  }
133  }
134 }
135 
136 SieveScriptBlockWidget::MatchCondition SieveScriptBlockWidget::matchCondition() const
137 {
138  return mMatchCondition;
139 }
140 
141 void SieveScriptBlockWidget::slotRadioClicked(QAbstractButton *button)
142 {
143  if (button == mMatchAll) {
144  mMatchCondition = AndCondition;
145  } else if (button == mMatchAny) {
146  mMatchCondition = OrCondition;
147  } else {
148  mMatchCondition = AllCondition;
149  }
150  Q_EMIT valueChanged();
151  updateWidget();
152 }
153 
154 void SieveScriptBlockWidget::updateWidget()
155 {
156  mScriptConditionLister->setEnabled(mMatchCondition != AllCondition);
157  mNewBlockType->setEnabled(mMatchCondition != AllCondition);
158  mAddBlockType->setEnabled(mMatchCondition != AllCondition);
159 }
160 
161 void SieveScriptBlockWidget::generatedScript(QString &script, QStringList &required, bool inForEveryPartLoop)
162 {
163  QString indentation;
164  if (inForEveryPartLoop) {
165  indentation = AutoCreateScriptUtil::indentation();
166  }
167  bool onlyActions = false;
168  if (mMatchCondition == AllCondition) {
169  onlyActions = true;
170  // Just actions type
171  } else if (pageType() == BlockElse) {
172  script += QLatin1String("else {\n");
173  } else {
174  QString conditionStr;
175  int numberOfCondition = 0;
176  mScriptConditionLister->generatedScript(conditionStr, numberOfCondition, required, inForEveryPartLoop);
177  const bool hasUniqCondition = (numberOfCondition == 1);
178  QString filterStr;
179  QString blockStr;
180  switch (pageType()) {
181  case BlockIf:
182  blockStr = indentation + QStringLiteral("if ");
183  break;
184  case BlockElsIf:
185  blockStr = QStringLiteral("elsif ");
186  break;
187  case BlockElse:
188  break;
189  default:
190  // We can got here.
191  break;
192  }
193 
194  if (hasUniqCondition == 1) {
195  filterStr += blockStr;
196  } else if (mMatchCondition == AndCondition) {
197  filterStr += blockStr + QLatin1String("allof (");
198  } else if (mMatchCondition == OrCondition) {
199  filterStr += blockStr + QLatin1String("anyof (");
200  }
201 
202  if (conditionStr.isEmpty()) {
203  return;
204  } else {
205  script += filterStr + conditionStr;
206  }
207  if (hasUniqCondition) {
208  script += indentation + QLatin1String("{\n");
209  } else {
210  script += indentation + QStringLiteral(")\n%1{\n").arg(indentation);
211  }
212  }
213  mScriptActionLister->generatedScript(script, required, onlyActions, inForEveryPartLoop);
214  if (!onlyActions) {
215  script += indentation + QLatin1String("} ");
216  }
217 }
218 
219 void SieveScriptBlockWidget::updateCondition()
220 {
221  switch (mMatchCondition) {
222  case AndCondition:
223  mMatchAll->setChecked(true);
224  break;
225  case OrCondition:
226  mMatchAny->setChecked(true);
227  break;
228  case AllCondition:
229  mAllMessageRBtn->setChecked(true);
230  break;
231  }
232  updateWidget();
233 }
234 
235 void SieveScriptBlockWidget::loadLocalVariable(const SieveGlobalVariableActionWidget::VariableElement &var)
236 {
237  mScriptActionLister->loadLocalVariable(var);
238  mMatchCondition = AllCondition;
239  updateCondition();
240 }
241 
242 void SieveScriptBlockWidget::loadScript(QXmlStreamReader &element, bool onlyActions, QString &error)
243 {
244  if (onlyActions) {
245  mScriptActionLister->loadScript(element, true, error);
246  mMatchCondition = AllCondition;
247  updateCondition();
248  } else {
249  bool uniqueTest = false;
250  while (element.readNextStartElement()) {
251  const QStringRef tagName = element.name();
252  if (tagName == QLatin1String("test")) {
253  bool notCondition = false;
254  if (element.attributes().hasAttribute(QLatin1String("name"))) {
255  const QString typeCondition = element.attributes().value(QLatin1String("name")).toString();
256  if (typeCondition == QLatin1String("anyof")) {
257  mMatchCondition = OrCondition;
258  } else if (typeCondition == QLatin1String("allof")) {
259  mMatchAll->setChecked(true);
260  } else {
261  if (typeCondition == QLatin1String("not")) {
262  notCondition = true;
263  }
264  uniqueTest = true;
265  mMatchCondition = OrCondition;
266  }
267  updateCondition();
268  }
269  mScriptConditionLister->loadScript(element, uniqueTest, notCondition, error);
270  } else if (tagName == QLatin1String("block")) {
271  mScriptActionLister->loadScript(element, false, error);
272  } else {
273  if (tagName != QLatin1String("crlf")) {
274  qCDebug(LIBKSIEVE_LOG) << " e.tag" << tagName;
275  } else {
276  element.skipCurrentElement();
277  }
278  }
279  }
280  }
281 }
bool readNextStartElement()
void buttonClicked(QAbstractButton *button)
QString toString() const const
QStringRef value(const QString &namespaceUri, const QString &name) const const
AlignTop
void skipCurrentElement()
Type type(const QSqlDatabase &db)
bool isEmpty() const const
void clicked(bool checked)
bool hasAttribute(const QString &qualifiedName) const const
QString i18n(const char *text, const TYPE &arg...)
QString arg(qlonglong a, int fieldWidth, int base, QChar fillChar) const const
QXmlStreamAttributes attributes() const const
QIcon fromTheme(const QString &name)
QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
QStringRef name() const const
Q_EMITQ_EMIT
This file is part of the KDE documentation.
Documentation copyright © 1996-2021 The KDE developers.
Generated on Sun Apr 11 2021 23:09:36 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.