managesievewidget.cpp 21.1 KB
Newer Older
1
/*
2
  SPDX-FileCopyrightText: 2014-2020 Laurent Montel <montel@kde.org>
3

4
  SPDX-License-Identifier: GPL-2.0-only
5
6
7
8
9
*/

#include "managesievewidget.h"
#include "managesievetreeview.h"
#include "widgets/sievetreewidgetitem.h"
Laurent Montel's avatar
Laurent Montel committed
10
#include "managescriptsjob/renamescriptjob.h"
11
#include "libksieve_debug.h"
12
13
14
15

#include <kmanagesieve/sievejob.h>
#include <managescriptsjob/parseuserscriptjob.h>
#include <managescriptsjob/generateglobalscriptjob.h>
Laurent Montel's avatar
Laurent Montel committed
16
#include <PimCommon/NetworkManager>
17

Laurent Montel's avatar
Laurent Montel committed
18
#include "util/util_p.h"
19

20
21
22
23
24
25
26
27
28
#include <QInputDialog>
#include <KStandardGuiItem>
#include <KLocalizedString>
#include <KMessageBox>

#include <QHBoxLayout>
#include <QMenu>
#include <QTimer>
#include <QMetaType>
29
#include <QNetworkConfigurationManager>
Laurent Montel's avatar
Laurent Montel committed
30
//#define USE_RENAME_SIEVE_METHOD 1
31
32
33
34
35
36
37
using namespace KSieveUi;
Q_DECLARE_METATYPE(QTreeWidgetItem *)

class KSieveUi::ManageSieveWidgetPrivate
{
public:
    ManageSieveWidgetPrivate()
Laurent Montel's avatar
Laurent Montel committed
38
        : mClearAll(false)
Laurent Montel's avatar
Laurent Montel committed
39
        , mBlockSignal(false)
40
41
    {
    }
Laurent Montel's avatar
Laurent Montel committed
42

43
44
45
46
47
48
    ~ManageSieveWidgetPrivate()
    {
    }

    // Maps top-level items to their child which has the radio button selection
    QMap<QTreeWidgetItem *, QTreeWidgetItem *> mSelectedItems;
Laurent Montel's avatar
Laurent Montel committed
49
    ManageSieveTreeView *mTreeView = nullptr;
50
51
52
53
54
    bool mClearAll : 1;
    bool mBlockSignal : 1;
};

ManageSieveWidget::ManageSieveWidget(QWidget *parent)
Laurent Montel's avatar
Laurent Montel committed
55
56
    : QWidget(parent)
    , d(new KSieveUi::ManageSieveWidgetPrivate)
57
{
58
    auto *lay = new QHBoxLayout(this);
Laurent Montel's avatar
Laurent Montel committed
59
    lay->setContentsMargins({});
60

Laurent Montel's avatar
Laurent Montel committed
61
    d->mTreeView = new ManageSieveTreeView(this);
62
63
64
65
66
67
#ifndef QT_NO_CONTEXTMENU
    connect(d->mTreeView, &ManageSieveTreeView::customContextMenuRequested, this, &ManageSieveWidget::slotContextMenuRequested);
#endif
    connect(d->mTreeView, &ManageSieveTreeView::itemDoubleClicked, this, &ManageSieveWidget::slotDoubleClicked);
    connect(d->mTreeView, &ManageSieveTreeView::itemSelectionChanged, this, &ManageSieveWidget::slotUpdateButtons);
    connect(d->mTreeView, &ManageSieveTreeView::itemChanged, this, &ManageSieveWidget::slotItemChanged);
68
    connect(this, &ManageSieveWidget::updateSieveSettingsDone, this, &ManageSieveWidget::updateSieveSettingsFinished);
69

Laurent Montel's avatar
Laurent Montel committed
70
    connect(PimCommon::NetworkManager::self()->networkConfigureManager(), &QNetworkConfigurationManager::onlineStateChanged, this, &ManageSieveWidget::slotSystemNetworkOnlineStateChanged);
71
72
73
74
75
76
77

    lay->addWidget(d->mTreeView);
    QTimer::singleShot(0, this, &ManageSieveWidget::slotCheckNetworkStatus);
}

ManageSieveWidget::~ManageSieveWidget()
{
78
    disconnect(d->mTreeView, &ManageSieveTreeView::itemSelectionChanged, this, &ManageSieveWidget::slotUpdateButtons);
79
80
81
82
83
84
    clear();
    delete d;
}

void ManageSieveWidget::slotCheckNetworkStatus()
{
Laurent Montel's avatar
Laurent Montel committed
85
    slotSystemNetworkOnlineStateChanged(PimCommon::NetworkManager::self()->networkConfigureManager()->isOnline());
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
}

void ManageSieveWidget::slotSystemNetworkOnlineStateChanged(bool state)
{
    if (state) {
        d->mTreeView->setEnabled(true);
        slotRefresh();
    } else {
        d->mTreeView->setEnabled(false);
        d->mTreeView->setNetworkDown(false);
    }
}

ManageSieveTreeView *ManageSieveWidget::treeView() const
{
    return d->mTreeView;
}

void ManageSieveWidget::killAllJobs()
{
    d->mClearAll = true;
    QMap<KManageSieve::SieveJob *, QTreeWidgetItem *>::const_iterator it = mJobs.constBegin();
    while (it != mJobs.constEnd()) {
        it.key()->kill();
        ++it;
    }
    d->mClearAll = false;
    mJobs.clear();
}

bool ManageSieveWidget::serverHasError(QTreeWidgetItem *item) const
{
    const QVariant variant = item->data(0, SIEVE_SERVER_ERROR);
    if (variant.isValid() && variant.toBool() == true) {
        return true;
    }
    return false;
}

void ManageSieveWidget::slotItemChanged(QTreeWidgetItem *item, int col)
{
    if (!item || d->mBlockSignal || (col != 0)) {
        return;
    }
    if (!isFileNameItem(item)) {
        return;
    }
    QTreeWidgetItem *parent = item->parent();
    if ((d->mSelectedItems[parent] != item) && itemIsActived(item)) {
        d->mSelectedItems[parent] = item;
        changeActiveScript(parent, true);
    } else {
        d->mSelectedItems[parent] = item;
        changeActiveScript(parent, false);
    }
}

void ManageSieveWidget::slotContextMenuRequested(const QPoint &p)
{
    QTreeWidgetItem *item = d->mTreeView->itemAt(p);
    if (!item) {
        return;
    }
    QMenu menu;
    if (isFileNameItem(item)) {
        // script items:
Laurent Montel's avatar
Laurent Montel committed
152
        menu.addAction(i18n("Edit Script..."), this, &ManageSieveWidget::slotEditScript);
Laurent Montel's avatar
Laurent Montel committed
153
154
        menu.addAction(QIcon::fromTheme(QStringLiteral("edit-rename")), i18n("Rename Script..."), this, &ManageSieveWidget::slotRenameScript);
        menu.addSeparator();
Laurent Montel's avatar
Laurent Montel committed
155
        menu.addAction(QIcon::fromTheme(QStringLiteral("edit-delete")), i18n("Delete Script"), this, &ManageSieveWidget::slotDeleteScript);
156
157
        if (itemIsActived(item)) {
            menu.addSeparator();
Laurent Montel's avatar
Laurent Montel committed
158
            menu.addAction(i18n("Deactivate Script"), this, &ManageSieveWidget::slotDeactivateScript);
159
160
161
        }
    } else if (!item->parent()) {
        // top-levels:
Laurent Montel's avatar
Laurent Montel committed
162
        const bool jobsListIsEmpty = mJobs.keys(item).isEmpty();
163
        if (canAddNewScript(item, jobsListIsEmpty)) {
Laurent Montel's avatar
Laurent Montel committed
164
            menu.addAction(QIcon::fromTheme(QStringLiteral("document-new")), i18n("New Script..."), this, &ManageSieveWidget::slotNewScript);
Laurent Montel's avatar
Laurent Montel committed
165
        } else if (!jobsListIsEmpty) { //In Progress
Laurent Montel's avatar
Laurent Montel committed
166
            menu.addAction(KStandardGuiItem::cancel().icon(), KStandardGuiItem::cancel().text(), this, &ManageSieveWidget::slotCancelFetch);
167
168
169
170
171
172
173
        }
    }
    if (!menu.actions().isEmpty()) {
        menu.exec(d->mTreeView->viewport()->mapToGlobal(p));
    }
}

174
175
176
177
178
179
180
181
182
183
bool ManageSieveWidget::canAddNewScript(QTreeWidgetItem *item, bool jobsListIsEmpty)
{
    if (!serverHasError(item) && jobsListIsEmpty) {
        if (item->parent()) {
            item = item->parent();
        }
        if (!item) {
            return false;
        }

184
        if (!mUrls.contains(item)) {
185
186
187
188
189
190
191
            return false;
        }
        return true;
    }
    return false;
}

192
193
194
195
void ManageSieveWidget::slotCancelFetch()
{
    QTreeWidgetItem *item = d->mTreeView->currentItem();
    if (item) {
Laurent Montel's avatar
Laurent Montel committed
196
        const QList<KManageSieve::SieveJob *> jobs = mJobs.keys(item);
Laurent Montel's avatar
Laurent Montel committed
197
        for (KManageSieve::SieveJob *job : jobs) {
198
            job->kill(KJob::EmitResult);
199
        }
200
201
    } else {
        qCWarning(LIBKSIEVE_LOG) << "ManageSieveWidget::slotCancelFetch(): item is not selected";
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
    }
}

void ManageSieveWidget::slotNewScript()
{
    QTreeWidgetItem *currentItem = d->mTreeView->currentItem();
    if (!currentItem) {
        return;
    }
    if (currentItem->parent()) {
        currentItem = currentItem->parent();
    }
    if (!currentItem) {
        return;
    }

218
    if (!mUrls.contains(currentItem)) {
219
220
221
222
223
224
225
226
227
        return;
    }

    QUrl u = mUrls[currentItem];
    if (u.isEmpty()) {
        return;
    }

    bool ok = false;
Laurent Montel's avatar
Laurent Montel committed
228
    QString name = QInputDialog::getText(this, i18n("New Sieve Script"),
Laurent Montel's avatar
Laurent Montel committed
229
230
                                         i18n("Please enter a name for the new Sieve script:"), QLineEdit::Normal,
                                         i18n("unnamed"), &ok);
Laurent Montel's avatar
Laurent Montel committed
231
232
    name = name.trimmed();
    if (!ok || name.isEmpty()) {
233
234
235
        if (ok && name.isEmpty()) {
            KMessageBox::error(this, i18n("Empty name is not a valid name"), i18n("New Script"));
        }
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
        return;
    }

    if (Util::isKep14ProtectedName(name)) {
        KMessageBox::error(this, i18n("You cannot use protected name."), i18n("New Script"));
        return;
    }

    u = u.adjusted(QUrl::RemoveFilename);
    u.setPath(u.path() + QLatin1Char('/') + name);

    QTreeWidgetItem *parentItem = currentItem;
    if (parentItem) {
        const int numberOfElement(parentItem->childCount());
        for (int i = 0; i < numberOfElement; ++i) {
            if (parentItem->child(i)->text(0) == name) {
                KMessageBox::error(
                    this,
                    i18n("Script name already used \"%1\".", name),
                    i18n("New Script"));
                return;
            }
        }
    }

    const QStringList currentCapabilities = currentItem->data(0, SIEVE_SERVER_CAPABILITIES).toStringList();
262
    const KSieveUi::SieveImapAccountSettings sieveimapaccountsettings = currentItem->data(0, SIEVE_SERVER_IMAP_SETTINGS).value<KSieveUi::SieveImapAccountSettings>();
263
    const QStringList listscript = currentItem->data(0, SIEVE_SERVER_LIST_SCRIPT).toStringList();
264
265

    d->mBlockSignal = true;
266
    auto *newItem = new QTreeWidgetItem(currentItem);
267
268
269
270
    newItem->setFlags(newItem->flags() & (Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsSelectable));
    newItem->setText(0, name);
    newItem->setCheckState(0, Qt::Unchecked);
    d->mBlockSignal = false;
271
272
273
274
275
276
277
278

    ScriptInfo info;
    info.currentCapabilities = currentCapabilities;
    info.currentUrl = u;
    info.sieveImapAccountSettings = sieveimapaccountsettings;
    info.scriptList = listscript;

    Q_EMIT newScript(info);
279
280
281
282
283
284
285
286
287
}

void ManageSieveWidget::slotEditScript()
{
    QTreeWidgetItem *currentItem = d->mTreeView->currentItem();
    if (!isFileNameItem(currentItem)) {
        return;
    }
    QTreeWidgetItem *parent = currentItem->parent();
288
    if (!mUrls.contains(parent)) {
289
290
291
292
293
294
295
296
        return;
    }
    QUrl url = mUrls[parent];
    if (url.isEmpty()) {
        return;
    }
    url = url.adjusted(QUrl::RemoveFilename);
    url.setPath(url.path() +  QLatin1Char('/') + currentItem->text(0));
297
    const KSieveUi::SieveImapAccountSettings sieveimapaccountsettings = parent->data(0, SIEVE_SERVER_IMAP_SETTINGS).value<KSieveUi::SieveImapAccountSettings>();
298
    const QStringList currentCapabilities = parent->data(0, SIEVE_SERVER_CAPABILITIES).toStringList();
299
300
301
302
303
304
305
306
307
    const QStringList listscript = parent->data(0, SIEVE_SERVER_LIST_SCRIPT).toStringList();

    ScriptInfo info;
    info.currentCapabilities = currentCapabilities;
    info.currentUrl = url;
    info.sieveImapAccountSettings = sieveimapaccountsettings;
    info.scriptList = listscript;

    Q_EMIT editScript(info);
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
}

void ManageSieveWidget::slotDeactivateScript()
{
    QTreeWidgetItem *item = d->mTreeView->currentItem();
    if (!isFileNameItem(item)) {
        return;
    }
    QTreeWidgetItem *parent = item->parent();
    if (itemIsActived(item)) {
        d->mSelectedItems[parent] = item;
        changeActiveScript(parent, false);
    }
}

void ManageSieveWidget::changeActiveScript(QTreeWidgetItem *item, bool activate)
{
    if (!item) {
        return;
    }
328
    if (!mUrls.contains(item)) {
329
330
        return;
    }
331
    if (!d->mSelectedItems.contains(item)) {
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
        return;
    }
    QUrl u = mUrls[item];
    if (u.isEmpty()) {
        return;
    }

    if (item->data(0, SIEVE_SERVER_MODE).toInt() == Kep14EditorMode) {
        QStringList activeScripts;
        for (int i = 0; i < item->childCount(); ++i) {
            QTreeWidgetItem *j = item->child(i);
            if (itemIsActived(j)) {
                activeScripts << j->text(0);
            }
        }
347
        auto *job = new GenerateGlobalScriptJob(u);
348
349
        job->addUserActiveScripts(activeScripts);
        connect(job, &GenerateGlobalScriptJob::success, this, &ManageSieveWidget::slotRefresh);
Laurent Montel's avatar
Laurent Montel committed
350
        connect(job, &GenerateGlobalScriptJob::error, this, &ManageSieveWidget::slotGenerateGlobalScriptError);
351
352
353
354
355
356
357
358
359
360
361
        job->start();
        return;
    }

    QTreeWidgetItem *selected = d->mSelectedItems[item];
    if (!selected) {
        return;
    }
    u = u.adjusted(QUrl::RemoveFilename);
    u.setPath(u.path() +  QLatin1Char('/') + selected->text(0));

Laurent Montel's avatar
Laurent Montel committed
362
    KManageSieve::SieveJob *job = nullptr;
363
364
365
366
367
368
369
370
371
    if (activate) {
        job = KManageSieve::SieveJob::activate(u);
    } else {
        job = KManageSieve::SieveJob::deactivate(u);
    }
    d->mBlockSignal = true;
    connect(job, &KManageSieve::SieveJob::result, this, &ManageSieveWidget::slotRefresh);
}

Laurent Montel's avatar
Laurent Montel committed
372
373
374
375
376
377
void ManageSieveWidget::slotGenerateGlobalScriptError(const QString &errorStr)
{
    qCWarning(LIBKSIEVE_LOG) << "MManageSieveWidget::slotGenerateGlobalScriptError: error: " << errorStr;
    slotRefresh();
}

378
379
380
bool ManageSieveWidget::itemIsActived(QTreeWidgetItem *item) const
{
    Q_ASSERT(item && item->parent());
Laurent Montel's avatar
Laurent Montel committed
381
    return item->checkState(0) == Qt::Checked;
382
383
384
385
386
387
388
}

bool ManageSieveWidget::isFileNameItem(QTreeWidgetItem *item) const
{
    if (!item || !item->parent()) {
        return false;
    }
Laurent Montel's avatar
Laurent Montel committed
389
    return item->flags() & Qt::ItemIsEnabled;
390
391
392
393
394
395
396
397
398
399
}

void ManageSieveWidget::clear()
{
    killAllJobs();
    d->mSelectedItems.clear();
    mUrls.clear();
    d->mTreeView->clear();
}

400
401
void ManageSieveWidget::slotRenameScript()
{
Laurent Montel's avatar
Laurent Montel committed
402
    QTreeWidgetItem *currentItem = d->mTreeView->currentItem();
403
404
405
406
407
408
409
410
    if (!isFileNameItem(currentItem)) {
        return;
    }
    QTreeWidgetItem *parent = currentItem->parent();
    if (!parent) {
        return;
    }

411
    if (!mUrls.contains(parent)) {
412
413
414
415
416
417
418
        return;
    }

    QUrl u = mUrls[parent];
    if (u.isEmpty()) {
        return;
    }
Laurent Montel's avatar
Laurent Montel committed
419

Laurent Montel's avatar
Laurent Montel committed
420
    const QString newName = QInputDialog::getText(this, i18n("Rename Script"), i18n("Script Name:"), QLineEdit::Normal, currentItem->text(0));
421
    if (newName.trimmed().isEmpty()) {
Laurent Montel's avatar
Laurent Montel committed
422
423
424
        return;
    }

425
426
    if (newName == currentItem->text(0)) {
        return;
Laurent Montel's avatar
Laurent Montel committed
427
428
429
430
    }

    u = u.adjusted(QUrl::RemoveFilename);
    u.setPath(u.path() +  QLatin1Char('/') + currentItem->text(0));
Laurent Montel's avatar
Laurent Montel committed
431
#ifdef USE_RENAME_SIEVE_METHOD
Laurent Montel's avatar
Laurent Montel committed
432
433
    KManageSieve::SieveJob *job = KManageSieve::SieveJob::rename(u, newName);
    connect(job, &KManageSieve::SieveJob::result, this, &ManageSieveWidget::slotRenameResult);
Laurent Montel's avatar
Laurent Montel committed
434
#else
435
    auto *job = new KSieveUi::RenameScriptJob(this);
Laurent Montel's avatar
Laurent Montel committed
436
437
438
439
440
    job->setOldUrl(u);
    job->setIsActive(itemIsActived(currentItem));
    job->setNewName(newName);
    connect(job, &RenameScriptJob::finished, this, &ManageSieveWidget::slotRenameFinished);
    job->start();
Laurent Montel's avatar
Laurent Montel committed
441
#endif
Laurent Montel's avatar
Laurent Montel committed
442
443
}

444
void ManageSieveWidget::slotRenameFinished(const QUrl &oldUrl, const QUrl &newUrl, const QString &errorStr, bool success)
Laurent Montel's avatar
Laurent Montel committed
445
{
446
    qCDebug(LIBKSIEVE_LOG) << " void ManageSieveWidget::slotRenameResult(KManageSieve::SieveJob *job, bool success)" << success;
Laurent Montel's avatar
Laurent Montel committed
447
448
    if (!success) {
        KMessageBox::error(this, errorStr, i18n("Rename Script"));
449
450
    } else {
        Q_EMIT scriptRenamed(oldUrl, newUrl);
Laurent Montel's avatar
Laurent Montel committed
451
    }
Laurent Montel's avatar
Laurent Montel committed
452
453
454
    slotRefresh();
}

Laurent Montel's avatar
Laurent Montel committed
455
456
void ManageSieveWidget::slotRenameResult(KManageSieve::SieveJob *job, bool success)
{
457
    Q_UNUSED(job);
Laurent Montel's avatar
Laurent Montel committed
458
    qCDebug(LIBKSIEVE_LOG) << " void ManageSieveWidget::slotRenameResult(KManageSieve::SieveJob *job, bool success)" << success;
Laurent Montel's avatar
Laurent Montel committed
459
    slotRefresh();
460
461
}

462
463
void ManageSieveWidget::slotDeleteScript()
{
Laurent Montel's avatar
Laurent Montel committed
464
    QTreeWidgetItem *currentItem = d->mTreeView->currentItem();
465
466
467
468
469
470
471
472
473
    if (!isFileNameItem(currentItem)) {
        return;
    }

    QTreeWidgetItem *parent = currentItem->parent();
    if (!parent) {
        return;
    }

474
    if (!mUrls.contains(parent)) {
475
476
477
478
479
480
481
482
        return;
    }

    QUrl u = mUrls[parent];
    if (u.isEmpty()) {
        return;
    }

Laurent Montel's avatar
Laurent Montel committed
483
    if (KMessageBox::warningContinueCancel(this, i18n("Really delete script \"%1\" from the server?", currentItem->text(0)),
484
485
                                           i18n("Delete Sieve Script Confirmation"),
                                           KStandardGuiItem::del())
Laurent Montel's avatar
Laurent Montel committed
486
        != KMessageBox::Continue) {
487
488
        return;
    }
Laurent Montel's avatar
Laurent Montel committed
489
490
491
492

    u = u.adjusted(QUrl::RemoveFilename);
    u.setPath(u.path() +  QLatin1Char('/') + currentItem->text(0));

493
    KManageSieve::SieveJob *job = KManageSieve::SieveJob::del(u);
494
    connect(job, &KManageSieve::SieveJob::result, this, &ManageSieveWidget::slotDeleteResult);
495
496
497
    Q_EMIT scriptDeleted(u);
}

498
499
500
501
502
503
504
505
506
void ManageSieveWidget::slotDeleteResult(KManageSieve::SieveJob *job, bool success)
{
    if (!success) {
        KMessageBox::error(this, i18n("Deleting the script failed.\n"
                                      "The server responded:\n%1", job->errorString()), i18n("Sieve Error"));
    }
    slotRefresh();
}

507
508
509
510
void ManageSieveWidget::slotRefresh()
{
    d->mBlockSignal = true;
    clear();
511
512
513
514
515
    updateSieveSettings();
}

void ManageSieveWidget::updateSieveSettingsFinished()
{
516
    clear();
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
    const bool noImapFound = refreshList();
    slotUpdateButtons();
    d->mTreeView->setNoImapFound(noImapFound);
    if (!noImapFound) {
        d->mBlockSignal = false;
    }
    Q_EMIT serverSieveFound(!noImapFound);
}

void ManageSieveWidget::slotUpdateButtons()
{
    Q_EMIT updateButtons(d->mTreeView->currentItem());
}

void ManageSieveWidget::slotGotList(KManageSieve::SieveJob *job, bool success, const QStringList &listScript, const QString &activeScript)
{
Laurent Montel's avatar
Debug--    
Laurent Montel committed
533
534
    //qCDebug(LIBKSIEVE_LOG) << "void ManageSieveWidget::slotGotList(KManageSieve::SieveJob *job, bool success, const QStringList &listScript, const QString &activeScript) success: " << success
    //                       << " listScript" << listScript;
535
536
537
    if (d->mClearAll) {
        return;
    }
Laurent Montel's avatar
Debug--    
Laurent Montel committed
538
    //qCDebug(LIBKSIEVE_LOG) << " After mClear All";
539
    QTreeWidgetItem *parent = mJobs[job];
Laurent Montel's avatar
Debug--    
Laurent Montel committed
540
    //qCDebug(LIBKSIEVE_LOG) << " parent " << parent;
541
542
543
544
545
546
547
548
549
    if (!parent) {
        return;
    }
    (static_cast<SieveTreeWidgetItem *>(parent))->stopAnimation();

    mJobs.remove(job);
    if (!success) {
        d->mBlockSignal = false;
        parent->setData(0, SIEVE_SERVER_ERROR, true);
550
        auto *item = new QTreeWidgetItem(parent);
551
552
553
554
555
556
557
        item->setText(0, i18n("Failed to fetch the list of scripts"));
        item->setFlags(item->flags() & ~Qt::ItemIsEnabled);
        d->mTreeView->expandItem(parent);
        return;
    }

    d->mBlockSignal = true; // don't trigger slotItemChanged
Laurent Montel's avatar
Laurent Montel committed
558
    for (const QString &script : listScript) {
559
560
561
562
        //Hide protected name.
        if (Util::isKep14ProtectedName(script)) {
            continue;
        }
563
        auto *item = new QTreeWidgetItem(parent);
564
565
566
567
568
569
570
571
572
573
574
        item->setFlags(item->flags() & (Qt::ItemIsUserCheckable | Qt::ItemIsEnabled | Qt::ItemIsSelectable));

        item->setText(0, script);
        const bool isActive = (script == activeScript);
        item->setCheckState(0, isActive ? Qt::Checked : Qt::Unchecked);
        if (isActive) {
            d->mSelectedItems[parent] = item;
        }
    }
    d->mBlockSignal = false;

575
    bool hasKep14EditorMode = Util::hasKep14Support(job->sieveCapabilities(), listScript, activeScript);
576
577
578
    if (hasKep14EditorMode) {
        QUrl u = mUrls[parent];
        u = u.adjusted(QUrl::RemoveFilename);
Laurent Montel's avatar
Laurent Montel committed
579
        u.setPath(u.path() + QLatin1Char('/') + QStringLiteral("USER"));
580
        auto *parseJob = new ParseUserScriptJob(u, this);
Laurent Montel's avatar
Laurent Montel committed
581
        parseJob->setAutoDelete(true);
582
583
584
585
        parseJob->setProperty("parentItem", QVariant::fromValue<QTreeWidgetItem *>(parent));
        connect(parseJob, &ParseUserScriptJob::finished, this, &ManageSieveWidget::setActiveScripts);
        parseJob->start();
        (static_cast<SieveTreeWidgetItem *>(parent))->startAnimation();
586
587
    } else if (Util::hasKep14CapabilitySupport(job->sieveCapabilities())) { //We don't have user script but server support kep14
        hasKep14EditorMode = true;
588
589
590
591
592
    }

    parent->setData(0, SIEVE_SERVER_CAPABILITIES, job->sieveCapabilities());
    parent->setData(0, SIEVE_SERVER_ERROR, false);
    parent->setData(0, SIEVE_SERVER_MODE, hasKep14EditorMode ? Kep14EditorMode : NormalEditorMode);
Laurent Montel's avatar
Laurent Montel committed
593
    parent->setData(0, SIEVE_SERVER_IMAP_SETTINGS, QVariant::fromValue(job->property("sieveimapaccountsettings").value<KSieveUi::SieveImapAccountSettings>()));
594
    parent->setData(0, SIEVE_SERVER_LIST_SCRIPT, listScript);
595
596
597
598
599
    d->mTreeView->expandItem(parent);
}

void ManageSieveWidget::setActiveScripts(ParseUserScriptJob *job)
{
600
    auto *parent = job->property("parentItem").value<QTreeWidgetItem *>();
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
    if (!parent) {
        return;
    }
    (static_cast<SieveTreeWidgetItem *>(parent))->stopAnimation();

    if (!job->error().isEmpty()) {
        qCWarning(LIBKSIEVE_LOG) << job->error();
        return;
    }

    d->mBlockSignal = true; // don't trigger slotItemChanged
    const QStringList activeScriptList = job->activeScriptList();
    QStringList scriptOrder = activeScriptList;
    QMap<QString, QTreeWidgetItem *> scriptMap;

    const int children = parent->childCount();
    for (int i = 0; i < children; ++i) {
        QTreeWidgetItem *item = parent->takeChild(0);
        scriptMap.insert(item->text(0), item);
        const bool isActive = activeScriptList.contains(item->text(0));
        item->setCheckState(0, isActive ? Qt::Checked : Qt::Unchecked);
        if (!isActive) {
            scriptOrder <<  item->text(0);
        }
    }

Laurent Montel's avatar
Laurent Montel committed
627
    for (const QString &scriptName : qAsConst(scriptOrder)) {
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
        parent->addChild(scriptMap[scriptName]);
    }

    d->mBlockSignal = false;
}

void ManageSieveWidget::slotDoubleClicked(QTreeWidgetItem *item)
{
    if (!isFileNameItem(item)) {
        return;
    }
    slotEditScript();
}

void ManageSieveWidget::enableDisableActions(bool &newScriptAction, bool &editScriptAction, bool &deleteScriptAction, bool &desactivateScriptAction)
{
    QTreeWidgetItem *item = d->mTreeView->currentItem();

    bool enabled = true;
    if (!item) {
        enabled = false;
649
    } else if (!item->parent() && !mUrls.contains(item)) {
650
651
652
653
654
655
656
657
658
659
        enabled = false;
    }

    if (!enabled) {
        newScriptAction = false;
        editScriptAction = false;
        deleteScriptAction = false;
        desactivateScriptAction = false;
    } else {
        if (serverHasError(item) || !mJobs.keys(item).isEmpty()) {
Laurent Montel's avatar
Laurent Montel committed
660
            newScriptAction = false;
661
        } else {
662
            newScriptAction = mUrls.contains(item);
663
664
665
666
667
668
669
        }
        enabled = isFileNameItem(item);
        editScriptAction = enabled;
        deleteScriptAction = enabled;
        desactivateScriptAction = enabled && itemIsActived(item);
    }
}