7#include "sievescriptlistbox.h"
8#include "sieveeditorgraphicalmodewidget.h"
9#include "sieveforeverypartwidget.h"
10#include "sieveglobalvariablewidget.h"
11#include "sieveincludewidget.h"
12#include "sievescriptdescriptiondialog.h"
13#include "sievescriptpage.h"
14#include <KLocalizedString>
18#include <QInputDialog>
20#include <QXmlStreamReader>
22#include "libksieveui_debug.h"
30inline const QString defaultScriptName()
32 return QStringLiteral(
"SCRIPTNAME: ");
35inline const QString roundcubeRuleName()
37 return QStringLiteral(
" rule:");
41using namespace KSieveUi;
48SieveScriptListItem::~SieveScriptListItem() =
default;
50void SieveScriptListItem::setDescription(
const QString &desc)
55QString SieveScriptListItem::description()
const
60SieveScriptPage *SieveScriptListItem::scriptPage()
const
65void SieveScriptListItem::setScriptPage(SieveScriptPage *page)
84 mScriptPage->generatedScript(script, required);
89SieveScriptListBox::SieveScriptListBox(
const QString &title,
QWidget *parent)
99 layout->addWidget(mSieveListScript);
104 hbHBoxLayout->setContentsMargins({});
105 hbHBoxLayout->setSpacing(4);
108 hbHBoxLayout->addWidget(mBtnTop);
110 mBtnTop->setMinimumSize(mBtnTop->sizeHint() * 1.2);
113 hbHBoxLayout->addWidget(mBtnUp);
114 mBtnUp->setAutoRepeat(
true);
116 mBtnUp->setMinimumSize(mBtnUp->sizeHint() * 1.2);
118 hbHBoxLayout->addWidget(mBtnDown);
119 mBtnDown->setAutoRepeat(
true);
121 mBtnDown->setMinimumSize(mBtnDown->sizeHint() * 1.2);
124 hbHBoxLayout->addWidget(mBtnBottom);
126 mBtnBottom->setMinimumSize(mBtnBottom->sizeHint() * 1.2);
128 mBtnUp->setToolTip(
i18nc(
"Move selected filter up.",
"Up"));
129 mBtnDown->setToolTip(
i18nc(
"Move selected filter down.",
"Down"));
130 mBtnTop->setToolTip(
i18nc(
"Move selected filter to the top.",
"Top"));
131 mBtnBottom->setToolTip(
i18nc(
"Move selected filter to the bottom.",
"Bottom"));
133 layout->addWidget(hb);
137 hbHBoxLayout->setContentsMargins({});
138 hbHBoxLayout->setSpacing(4);
141 hbHBoxLayout->addWidget(mBtnNew);
143 mBtnNew->setToolTip(
i18nc(
"@info:tooltip",
"New Script"));
144 mBtnNew->setMinimumSize(mBtnNew->sizeHint() * 1.2);
147 hbHBoxLayout->addWidget(mBtnDelete);
149 mBtnDelete->setToolTip(
i18nc(
"@info:tooltip",
"Delete Script"));
150 mBtnDelete->setMinimumSize(mBtnDelete->sizeHint() * 1.2);
153 mBtnRename->setToolTip(
i18nc(
"@info:tooltip",
"Rename Script"));
155 mBtnRename->setMinimumSize(mBtnRename->sizeHint() * 1.2);
156 hbHBoxLayout->addWidget(mBtnRename);
159 mBtnDescription->setToolTip(
i18nc(
"@info:tooltip",
"Edit Script Description"));
161 mBtnDescription->setMinimumSize(mBtnDescription->sizeHint() * 1.2);
163 hbHBoxLayout->addWidget(mBtnDescription);
165 layout->addWidget(hb);
183SieveScriptListBox::~SieveScriptListBox() =
default;
185void SieveScriptListBox::slotCustomMenuRequested(
const QPoint &pos)
188 QAction *newScriptAction = menu.addAction(
i18nc(
"@action:inmenu",
"New Script"));
193 QAction *renameScriptAction = menu.addAction(
i18nc(
"@action:inmenu",
"Rename Script"));
198 QAction *editScriptDescriptionAction = menu.addAction(
i18nc(
"@action:inmenu",
"Edit Script Description"));
203 QAction *deleteScriptAction = menu.addAction(
i18nc(
"@action:inmenu",
"Delete Script"));
210void SieveScriptListBox::setSieveEditorGraphicalModeWidget(SieveEditorGraphicalModeWidget *graphicalModeWidget)
212 mSieveGraphicalModeWidget = graphicalModeWidget;
218 auto itemScript =
static_cast<SieveScriptListItem *
>(item);
219 Q_EMIT activatePage(itemScript->scriptPage());
223void SieveScriptListBox::updateButtons()
225 const int currentIndex = mSieveListScript->
currentRow();
226 const bool theFirst = (currentIndex == 0);
227 const int numberOfElement(mSieveListScript->
count());
228 const bool theLast = (currentIndex >= numberOfElement - 1);
240SieveScriptPage *SieveScriptListBox::createNewScript(
const QString &newName,
const QString &description)
242 auto item =
new SieveScriptListItem(newName, mSieveListScript);
243 item->setDescription(description);
244 auto page =
new SieveScriptPage(mSieveGraphicalModeWidget);
245 page->setListOfIncludeFile(mSieveGraphicalModeWidget->listOfIncludeFile());
246 item->setScriptPage(page);
248 Q_EMIT enableButtonOk(
true);
254void SieveScriptListBox::slotNew()
259 createNewScript(newName);
264void SieveScriptListBox::slotDelete()
269 i18n(
"Do you want to delete \"%1\" script?", item->
text()),
270 i18nc(
"@title:window",
"Delete Script"),
273 if (answer == KMessageBox::ButtonCode::PrimaryAction) {
274 auto itemScript =
static_cast<SieveScriptListItem *
>(item);
275 Q_EMIT removePage(itemScript->scriptPage());
277 Q_EMIT enableButtonOk(mSieveListScript->
count() > 0);
284void SieveScriptListBox::slotRename()
301void SieveScriptListBox::slotEditDescription()
305 auto sieveItem =
static_cast<SieveScriptListItem *
>(item);
307 dlg->setDescription(sieveItem->description());
309 sieveItem->setDescription(dlg->description());
316void SieveScriptListBox::slotTop()
320 const int currentIndex = mSieveListScript->
currentRow();
321 if (currentIndex != 0) {
322 item = mSieveListScript->
takeItem(currentIndex);
330void SieveScriptListBox::slotBottom()
334 const int currentIndex = mSieveListScript->
currentRow();
335 if (currentIndex != mSieveListScript->
count() - 1) {
336 item = mSieveListScript->
takeItem(currentIndex);
344void SieveScriptListBox::slotDown()
348 const int currentIndex = mSieveListScript->
currentRow();
349 if (currentIndex < mSieveListScript->count() - 1) {
350 item = mSieveListScript->
takeItem(currentIndex);
351 mSieveListScript->
insertItem(currentIndex + 1, item);
358void SieveScriptListBox::slotUp()
362 const int currentIndex = mSieveListScript->
currentRow();
363 if (currentIndex >= 1) {
364 item = mSieveListScript->
takeItem(currentIndex);
365 mSieveListScript->
insertItem(currentIndex - 1, item);
376 const int numberOfScripts(mSieveListScript->
count());
377 for (
int i = 0; i < numberOfScripts; ++i) {
378 auto item =
static_cast<SieveScriptListItem *
>(mSieveListScript->
item(i));
383 resultScript += item->generatedScript(lstRequires);
390 for (
const QString &r : std::as_const(lstRequires)) {
393 requireModules += QStringLiteral(
"require \"%1\";").arg(r);
400void SieveScriptListBox::clear()
403 Q_EMIT enableButtonOk(
false);
405 mSieveListScript->
clear();
409void SieveScriptListBox::loadScript(
const QString &doc,
QString &error)
413 if (streamReader.readNextStartElement()) {
415 SieveScriptPage *currentPage =
nullptr;
416 ParseSieveScriptTypeBlock typeBlock = TypeUnknown;
417 loadBlock(streamReader, currentPage, typeBlock, error);
422void SieveScriptListBox::loadBlock(
QXmlStreamReader &n, SieveScriptPage *currentPage, ParseSieveScriptTypeBlock typeBlock,
QString &error)
426 bool hasCreatedAIfBlock =
false;
427 bool previousElementWasAComment =
false;
432 previousElementWasAComment =
false;
434 if (typeBlock == TypeBlockAction) {
435 currentPage =
nullptr;
441 typeBlock = TypeBlockIf;
442 if (!currentPage || hasCreatedAIfBlock) {
443 currentPage = createNewScript(scriptName.
isEmpty() ? createUniqName() : scriptName, comment);
445 hasCreatedAIfBlock =
true;
447 currentPage->blockIfWidget()->loadScript(n,
false, error);
449 typeBlock = TypeBlockElsif;
451 qCDebug(LIBKSIEVEUI_LOG) <<
" script is not correct missing if block";
452 currentPage = createNewScript(scriptName.
isEmpty() ? createUniqName() : scriptName, comment);
454 SieveScriptBlockWidget *blockWidget = currentPage->addScriptBlock(KSieveUi::SieveWidgetPageAbstract::BlockElsIf);
456 blockWidget->loadScript(n,
false, error);
459 typeBlock = TypeBlockElse;
461 currentPage = createNewScript(scriptName.
isEmpty() ? createUniqName() : scriptName, comment);
462 qCDebug(LIBKSIEVEUI_LOG) <<
" script is not correct missing if block";
464 SieveScriptBlockWidget *blockWidget = currentPage->addScriptBlock(KSieveUi::SieveWidgetPageAbstract::BlockElse);
466 blockWidget->loadScript(n,
false, error);
469 currentPage =
nullptr;
471 typeBlock = TypeBlockForeachBlock;
473 currentPage = createNewScript(scriptName.
isEmpty() ? createUniqName() : scriptName, comment);
476 if (currentPage->forEveryPartWidget()) {
477 currentPage->forEveryPartWidget()->loadScript(n, error);
482#ifdef QDOMELEMENT_FIXME
484 loadBlock(block, currentPage, typeBlock, error);
490 qCDebug(LIBKSIEVEUI_LOG) <<
" unknown controlType :" << controlType;
494 previousElementWasAComment =
true;
496 if (e.hasAttribute(QStringLiteral(
"hash"))) {
498 }
else if (e.hasAttribute(QStringLiteral(
"bracket"))) {
503 if (str.contains(defaultScriptName())) {
504 scriptName = str.
remove(defaultScriptName());
505 }
else if (str.contains(roundcubeRuleName())) {
506 scriptName = str.
remove(roundcubeRuleName());
519 previousElementWasAComment =
false;
523 if (!currentPage || (typeBlock == TypeBlockIf) || (typeBlock == TypeBlockElse) || (typeBlock == TypeBlockElsif)) {
524 currentPage = createNewScript(scriptName.
isEmpty() ? createUniqName() : scriptName, comment);
527 typeBlock = TypeBlockInclude;
528 if (currentPage->includeWidget()) {
529 currentPage->includeWidget()->loadScript(n, error);
531 qCDebug(LIBKSIEVEUI_LOG) <<
" include not supported";
534 if (!currentPage || (typeBlock == TypeBlockIf) || (typeBlock == TypeBlockElse) || (typeBlock == TypeBlockElsif)) {
535 currentPage = createNewScript(scriptName.
isEmpty() ? createUniqName() : scriptName, comment);
538 typeBlock = TypeBlockGlobal;
539 if (currentPage->globalVariableWidget()) {
540 currentPage->globalVariableWidget()->loadScript(n, error);
542 qCDebug(LIBKSIEVEUI_LOG) <<
" globalVariable not supported";
544 }
else if (actionName ==
QLatin1StringView(
"set") && (typeBlock == TypeBlockGlobal)) {
546 if (currentPage->globalVariableWidget()) {
547 const SieveGlobalVariableActionWidget::VariableElement var = currentPage->globalVariableWidget()->loadSetVariable(n, error);
549 qCDebug(LIBKSIEVEUI_LOG) <<
"It's not a global variable";
550 if ((typeBlock == TypeBlockIf) || (typeBlock == TypeBlockElse) || (typeBlock == TypeBlockElsif)) {
551 currentPage = createNewScript(scriptName.
isEmpty() ? createUniqName() : scriptName, comment);
553 typeBlock = TypeBlockAction;
555 currentPage->blockIfWidget()->loadLocalVariable(var);
558 qCDebug(LIBKSIEVEUI_LOG) <<
" set not supported";
561 if (!currentPage || (typeBlock == TypeBlockIf) || (typeBlock == TypeBlockElse) || (typeBlock == TypeBlockElsif)) {
562 currentPage = createNewScript(scriptName.
isEmpty() ? createUniqName() : scriptName, comment);
564 typeBlock = TypeBlockAction;
566 currentPage->blockIfWidget()->loadScript(n,
true, error);
571 if (previousElementWasAComment) {
576 qCDebug(LIBKSIEVEUI_LOG) <<
" unknown tagname" << tagName;
581QString SieveScriptListBox::createUniqName()
583 const QString pattern =
i18n(
"Script part %1", mScriptNumber);
588#include "moc_sievescriptlistbox.cpp"
QString i18nc(const char *context, const char *text, const TYPE &arg...)
QString i18n(const char *text, const TYPE &arg...)
ButtonCode warningTwoActions(QWidget *parent, const QString &text, const QString &title, const KGuiItem &primaryAction, const KGuiItem &secondaryAction, const QString &dontAskAgainName=QString(), Options options=Options(Notify|Dangerous))
void error(QWidget *parent, const QString &text, const QString &title, const KGuiItem &buttonOk, Options options=Notify)
void setIcon(const QIcon &icon)
void triggered(bool checked)
QDomNode firstChild() const const
QDomElement firstChildElement(const QString &tagName, const QString &namespaceURI) const const
QIcon fromTheme(const QString &name)
QString getText(QWidget *parent, const QString &title, const QString &label, QLineEdit::EchoMode mode, const QString &text, bool *ok, Qt::WindowFlags flags, Qt::InputMethodHints inputMethodHints)
void append(QList< T > &&value)
qsizetype count() const const
bool isEmpty() const const
void setText(const QString &text)
QString text() const const
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
bool endsWith(QChar c, Qt::CaseSensitivity cs) const const
bool isEmpty() const const
qsizetype length() const const
QString & remove(QChar ch, Qt::CaseSensitivity cs)
QString & removeAt(qsizetype pos)
bool startsWith(QChar c, Qt::CaseSensitivity cs) const const
QString trimmed() const const
bool contains(QLatin1StringView str, Qt::CaseSensitivity cs) const const
QList< QStringView > split(QChar sep, Qt::SplitBehavior behavior, Qt::CaseSensitivity cs) const const
QString toString() const const
QFuture< ArgsType< Signal > > connect(Sender *sender, Signal signal)
bool hasAttribute(QAnyStringView namespaceUri, QAnyStringView name) const const
QStringView value(QAnyStringView namespaceUri, QAnyStringView name) const const
QXmlStreamAttributes attributes() const const
QStringView name() const const
QString readElementText(ReadElementTextBehaviour behaviour)
bool readNextStartElement()
void skipCurrentElement()