accountwidget.cpp 21.7 KB
Newer Older
Igor Trindade Oliveira's avatar
Igor Trindade Oliveira committed
1
/*
2
3
4
5
 *   SPDX-FileCopyrightText: 2000 Espen Sand <espen@kde.org>
 *   SPDX-FileCopyrightText: 2009 Thomas McGuire <mcguire@kde.org>
 *   SPDX-FileCopyrightText: 2009-2010 Klaralvdalens Datakonsult AB, a KDAB Group company <info@kdab.net>
 *   SPDX-FileCopyrightText: 2010 Casey Link <unnamedrambler@gmail.com>
Igor Trindade Oliveira's avatar
Igor Trindade Oliveira committed
6
 *
7
 *   SPDX-License-Identifier: GPL-2.0-or-later
Igor Trindade Oliveira's avatar
Igor Trindade Oliveira committed
8
9
 *
 */
10
11

// Local includes
12
#include "accountwidget.h"
Tobias Koenig's avatar
Tobias Koenig committed
13
14
#include "settings.h"
#include "settingsadaptor.h"
Igor Trindade Oliveira's avatar
Igor Trindade Oliveira committed
15

16
#include <Akonadi/Collection>
17
#include <Akonadi/CollectionFetchJob>
18
#include <Akonadi/ResourceSettings>
19
20
#include <Akonadi/SpecialMailCollections>
#include <Akonadi/SpecialMailCollectionsRequestJob>
21
#include <Libkdepim/LineEditCatchReturnKey>
Laurent Montel's avatar
Laurent Montel committed
22
#include <MailTransport/ServerTest>
23

Laurent Montel's avatar
Laurent Montel committed
24
#include "pop3resource_debug.h"
25
#include <KAuthorized>
26
#include <KEMailSettings>
Igor Trindade Oliveira's avatar
Igor Trindade Oliveira committed
27
#include <KMessageBox>
28
#include <KUser>
Allan Sandfeld Jensen's avatar
Allan Sandfeld Jensen committed
29
30

#include <QButtonGroup>
Laurent Montel's avatar
Laurent Montel committed
31
32
#include <QPushButton>
#include <QVBoxLayout>
Igor Trindade Oliveira's avatar
Igor Trindade Oliveira committed
33

34
35
using namespace MailTransport;
using namespace Akonadi;
36
using namespace QKeychain;
Laurent Montel's avatar
Laurent Montel committed
37
38
namespace
{
Igor Trindade Oliveira's avatar
Igor Trindade Oliveira committed
39
40
41
class BusyCursorHelper : public QObject
{
public:
Laurent Montel's avatar
Laurent Montel committed
42
43
44
    inline BusyCursorHelper(QObject *parent)
        : QObject(parent)
    {
45
#ifndef QT_NO_CURSOR
Laurent Montel's avatar
Laurent Montel committed
46
        qApp->setOverrideCursor(Qt::BusyCursor);
47
#endif
Laurent Montel's avatar
Laurent Montel committed
48
    }
Igor Trindade Oliveira's avatar
Igor Trindade Oliveira committed
49

50
    inline ~BusyCursorHelper() override
Laurent Montel's avatar
Laurent Montel committed
51
    {
52
#ifndef QT_NO_CURSOR
Laurent Montel's avatar
Laurent Montel committed
53
        qApp->restoreOverrideCursor();
54
#endif
Laurent Montel's avatar
Laurent Montel committed
55
    }
Igor Trindade Oliveira's avatar
Igor Trindade Oliveira committed
56
57
58
};
}

59
AccountWidget::AccountWidget(Settings &settings, const QString &identifier, QWidget *parent)
60
    : QWidget(parent)
Laurent Montel's avatar
Laurent Montel committed
61
    , mValidator(this)
62
    , mIdentifier(identifier)
63
    , mSettings(settings)
Igor Trindade Oliveira's avatar
Igor Trindade Oliveira committed
64
{
65
    mValidator.setRegularExpression(QRegularExpression(QStringLiteral("[A-Za-z0-9_:.-]*")));
Laurent Montel's avatar
Laurent Montel committed
66
    setupWidgets();
Igor Trindade Oliveira's avatar
Igor Trindade Oliveira committed
67
68
}

69
AccountWidget::~AccountWidget()
Igor Trindade Oliveira's avatar
Igor Trindade Oliveira committed
70
{
Laurent Montel's avatar
Laurent Montel committed
71
    delete mServerTest;
Laurent Montel's avatar
Laurent Montel committed
72
    mServerTest = nullptr;
Igor Trindade Oliveira's avatar
Igor Trindade Oliveira committed
73
74
}

75
void AccountWidget::setupWidgets()
Igor Trindade Oliveira's avatar
Igor Trindade Oliveira committed
76
{
Laurent Montel's avatar
Laurent Montel committed
77
    auto mainLayout = new QVBoxLayout(this);
Laurent Montel's avatar
Laurent Montel committed
78

Laurent Montel's avatar
Laurent Montel committed
79
    auto page = new QWidget(this);
Laurent Montel's avatar
Laurent Montel committed
80
81
82
83
    mainLayout->addWidget(page);

    setupUi(page);

84
85
    passwordEdit->setRevealPasswordAvailable(KAuthorized::authorize(QStringLiteral("lineedit_reveal_password")));

Laurent Montel's avatar
Laurent Montel committed
86
87
88
89
90
91
92
    // only letters, digits, '-', '.', ':' (IPv6) and '_' (for Windows
    // compatibility) are allowed
    hostEdit->setValidator(&mValidator);
    intervalSpin->setSuffix(ki18np(" minute", " minutes"));

    intervalSpin->setRange(ResourceSettings::self()->minimumCheckInterval(), 10000);
    intervalSpin->setSingleStep(1);
Laurent Montel's avatar
Laurent Montel committed
93
94
95
96
97
    new KPIM::LineEditCatchReturnKey(nameEdit, this);
    new KPIM::LineEditCatchReturnKey(hostEdit, this);
    new KPIM::LineEditCatchReturnKey(loginEdit, this);
    new KPIM::LineEditCatchReturnKey(precommand, this);

98
99
    connect(leaveOnServerCheck, &QCheckBox::clicked, this, &AccountWidget::slotLeaveOnServerClicked);
    connect(leaveOnServerDaysCheck, &QCheckBox::toggled, this, &AccountWidget::slotEnableLeaveOnServerDays);
100
    connect(leaveOnServerDaysSpin, &QSpinBox::valueChanged, this, &AccountWidget::slotLeaveOnServerDaysChanged);
101
    connect(leaveOnServerCountCheck, &QCheckBox::toggled, this, &AccountWidget::slotEnableLeaveOnServerCount);
102
    connect(leaveOnServerCountSpin, &QSpinBox::valueChanged, this, &AccountWidget::slotLeaveOnServerCountChanged);
103
    connect(leaveOnServerSizeCheck, &QCheckBox::toggled, this, &AccountWidget::slotEnableLeaveOnServerSize);
Laurent Montel's avatar
Laurent Montel committed
104

105
    connect(checkCapabilities, &QPushButton::clicked, this, &AccountWidget::slotCheckPopCapabilities);
Laurent Montel's avatar
Laurent Montel committed
106
    encryptionButtonGroup = new QButtonGroup(page);
Laurent Montel's avatar
Laurent Montel committed
107
108
109
    encryptionButtonGroup->addButton(encryptionNone, Transport::EnumEncryption::None);
    encryptionButtonGroup->addButton(encryptionSSL, Transport::EnumEncryption::SSL);
    encryptionButtonGroup->addButton(encryptionTLS, Transport::EnumEncryption::TLS);
Laurent Montel's avatar
Laurent Montel committed
110

Laurent Montel's avatar
Laurent Montel committed
111
    connect(encryptionButtonGroup, &QButtonGroup::buttonClicked, this, &AccountWidget::slotPopEncryptionChanged);
112
    connect(intervalCheck, &QCheckBox::toggled, this, &AccountWidget::slotEnablePopInterval);
Laurent Montel's avatar
Laurent Montel committed
113
114
115

    populateDefaultAuthenticationOptions();

Laurent Montel's avatar
Laurent Montel committed
116
    folderRequester->setMimeTypeFilter(QStringList() << QStringLiteral("message/rfc822"));
Laurent Montel's avatar
Laurent Montel committed
117
118
119
    folderRequester->setAccessRightsFilter(Akonadi::Collection::CanCreateItem);
    folderRequester->changeCollectionDialogOptions(Akonadi::CollectionDialog::AllowToCreateNewChildCollection);

120
    connect(usePipeliningCheck, &QCheckBox::clicked, this, &AccountWidget::slotPipeliningClicked);
Igor Trindade Oliveira's avatar
Igor Trindade Oliveira committed
121
122
}

123
void AccountWidget::loadSettings()
Igor Trindade Oliveira's avatar
Igor Trindade Oliveira committed
124
{
125
    if (mSettings.name().isEmpty()) {
126
127
        nameEdit->setText(i18n("POP3 Account"));
    } else {
128
        nameEdit->setText(mSettings.name());
Laurent Montel's avatar
Laurent Montel committed
129
    }
Volker Krause's avatar
Volker Krause committed
130

Laurent Montel's avatar
Laurent Montel committed
131
    nameEdit->setFocus();
Laurent Montel's avatar
Laurent Montel committed
132
    loginEdit->setText(!mSettings.login().isEmpty() ? mSettings.login() : KUser().loginName());
Laurent Montel's avatar
Laurent Montel committed
133

Laurent Montel's avatar
Laurent Montel committed
134
    hostEdit->setText(!mSettings.host().isEmpty() ? mSettings.host() : KEMailSettings().getSetting(KEMailSettings::InServer));
135
136
137
138
139
140
141
    hostEdit->setText(mSettings.host());
    portEdit->setValue(mSettings.port());
    precommand->setText(mSettings.precommand());
    usePipeliningCheck->setChecked(mSettings.pipelining());
    leaveOnServerCheck->setChecked(mSettings.leaveOnServer());
    leaveOnServerDaysCheck->setEnabled(mSettings.leaveOnServer());
    leaveOnServerDaysCheck->setChecked(mSettings.leaveOnServerDays() >= 1);
Laurent Montel's avatar
Laurent Montel committed
142
    leaveOnServerDaysSpin->setValue(mSettings.leaveOnServerDays() >= 1 ? mSettings.leaveOnServerDays() : 7);
143
144
    leaveOnServerCountCheck->setEnabled(mSettings.leaveOnServer());
    leaveOnServerCountCheck->setChecked(mSettings.leaveOnServerCount() >= 1);
Laurent Montel's avatar
Laurent Montel committed
145
    leaveOnServerCountSpin->setValue(mSettings.leaveOnServerCount() >= 1 ? mSettings.leaveOnServerCount() : 100);
146
147
    leaveOnServerSizeCheck->setEnabled(mSettings.leaveOnServer());
    leaveOnServerSizeCheck->setChecked(mSettings.leaveOnServerSize() >= 1);
Laurent Montel's avatar
Laurent Montel committed
148
    leaveOnServerSizeSpin->setValue(mSettings.leaveOnServerSize() >= 1 ? mSettings.leaveOnServerSize() : 10);
149
150
151
152
153
    intervalCheck->setChecked(mSettings.intervalCheckEnabled());
    intervalSpin->setValue(mSettings.intervalCheckInterval());
    intervalSpin->setEnabled(mSettings.intervalCheckEnabled());

    const int authenticationMethod = mSettings.authenticationMethod();
Laurent Montel's avatar
Laurent Montel committed
154
    authCombo->setCurrentIndex(authCombo->findData(authenticationMethod));
155
156
157
158
    encryptionNone->setChecked(!mSettings.useSSL() && !mSettings.useTLS());
    encryptionSSL->setChecked(mSettings.useSSL());
    encryptionTLS->setChecked(mSettings.useTLS());
    proxyCheck->setChecked(mSettings.useProxy());
Laurent Montel's avatar
Laurent Montel committed
159

Laurent Montel's avatar
Laurent Montel committed
160
161
162
    slotEnableLeaveOnServerDays(leaveOnServerDaysCheck->isEnabled() ? mSettings.leaveOnServerDays() >= 1 : false);
    slotEnableLeaveOnServerCount(leaveOnServerCountCheck->isEnabled() ? mSettings.leaveOnServerCount() >= 1 : false);
    slotEnableLeaveOnServerSize(leaveOnServerSizeCheck->isEnabled() ? mSettings.leaveOnServerSize() >= 1 : false);
Laurent Montel's avatar
Laurent Montel committed
163
164
165

    // We need to fetch the collection, as the CollectionRequester needs the name
    // of it to work correctly
166
    Collection targetCollection(mSettings.targetCollection());
Laurent Montel's avatar
Laurent Montel committed
167
    if (targetCollection.isValid()) {
Laurent Montel's avatar
Laurent Montel committed
168
        auto fetchJob = new CollectionFetchJob(targetCollection, CollectionFetchJob::Base, this);
169
        connect(fetchJob, &CollectionFetchJob::collectionsReceived, this, &AccountWidget::targetCollectionReceived);
Laurent Montel's avatar
Laurent Montel committed
170
171
172
173
    } else {
        // FIXME: This is a bit duplicated from POP3Resource...

        // No target collection set in the config? Try requesting a default inbox
Laurent Montel's avatar
Laurent Montel committed
174
        auto requestJob = new SpecialMailCollectionsRequestJob(this);
Laurent Montel's avatar
Laurent Montel committed
175
176
        requestJob->requestDefaultCollection(SpecialMailCollections::Inbox);
        requestJob->start();
177
        connect(requestJob, &SpecialMailCollectionsRequestJob::result, this, &AccountWidget::localFolderRequestJobFinished);
178
    }
Laurent Montel's avatar
Laurent Montel committed
179
180
181

    passwordEdit->setEnabled(false);
    passwordLabel->setEnabled(false);
182
183
184
185
    auto readJob = new ReadPasswordJob(QStringLiteral("pop3"), this);
    connect(readJob, &QKeychain::Job::finished, this, &AccountWidget::walletOpenedForLoading);
    readJob->setKey(mIdentifier);
    readJob->start();
Volker Krause's avatar
Volker Krause committed
186
187
}

188
void AccountWidget::walletOpenedForLoading(QKeychain::Job *baseJob)
Volker Krause's avatar
Volker Krause committed
189
{
Laurent Montel's avatar
Laurent Montel committed
190
    auto job = qobject_cast<ReadPasswordJob *>(baseJob);
191
    Q_ASSERT(job);
Laurent Montel's avatar
Laurent Montel committed
192
193
194
195
    if (job->error()) {
        qCWarning(POP3RESOURCE_LOG) << "Failed to open wallet for loading the password." << job->errorString();
        passwordEdit->lineEdit()->setPlaceholderText(i18n("Unable to open wallet"));
    } else {
196
197
198
        passwordEdit->setPassword(job->textData());
        passwordEdit->setEnabled(true);
        passwordLabel->setEnabled(true);
Volker Krause's avatar
Volker Krause committed
199
    }
Laurent Montel's avatar
Laurent Montel committed
200
201
}

Laurent Montel's avatar
Laurent Montel committed
202
void AccountWidget::walletOpenedForSaving()
Laurent Montel's avatar
Laurent Montel committed
203
{
Laurent Montel's avatar
Laurent Montel committed
204
205
206
207
    if (passwordEdit->password().isEmpty()) {
        auto deleteJob = new DeletePasswordJob(QStringLiteral("pop3"));
        deleteJob->setKey(mIdentifier);
        deleteJob->start();
Laurent Montel's avatar
Laurent Montel committed
208
    } else {
209
        auto writeJob = new WritePasswordJob(QStringLiteral("pop3"));
Laurent Montel's avatar
Laurent Montel committed
210
211
212
213
214
215
216
217
        connect(writeJob, &QKeychain::Job::finished, this, [](QKeychain::Job *baseJob) {
            if (baseJob->error()) {
                qCWarning(POP3RESOURCE_LOG) << "Error writing password using QKeychain:" << baseJob->errorString();
            }
        });
        writeJob->setKey(mIdentifier);
        writeJob->setTextData(passwordEdit->password());
        writeJob->start();
Volker Krause's avatar
Volker Krause committed
218
    }
Igor Trindade Oliveira's avatar
Igor Trindade Oliveira committed
219
220
}

221
void AccountWidget::slotLeaveOnServerClicked()
Igor Trindade Oliveira's avatar
Igor Trindade Oliveira committed
222
{
Laurent Montel's avatar
Laurent Montel committed
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
    const bool state = leaveOnServerCheck->isChecked();
    leaveOnServerDaysCheck->setEnabled(state);
    leaveOnServerCountCheck->setEnabled(state);
    leaveOnServerSizeCheck->setEnabled(state);
    if (state) {
        if (leaveOnServerDaysCheck->isChecked()) {
            slotEnableLeaveOnServerDays(state);
        }
        if (leaveOnServerCountCheck->isChecked()) {
            slotEnableLeaveOnServerCount(state);
        }
        if (leaveOnServerSizeCheck->isChecked()) {
            slotEnableLeaveOnServerSize(state);
        }
    } else {
        slotEnableLeaveOnServerDays(state);
        slotEnableLeaveOnServerCount(state);
        slotEnableLeaveOnServerSize(state);
Igor Trindade Oliveira's avatar
Igor Trindade Oliveira committed
241
    }
Laurent Montel's avatar
Laurent Montel committed
242
    if (mServerTest && !mServerTest->capabilities().contains(ServerTest::UIDL) && leaveOnServerCheck->isChecked()) {
Laurent Montel's avatar
Laurent Montel committed
243
244
245
246
247
248
249
250
251
        KMessageBox::information(topLevelWidget(),
                                 i18n("The server does not seem to support unique "
                                      "message numbers, but this is a "
                                      "requirement for leaving messages on the "
                                      "server.\n"
                                      "Since some servers do not correctly "
                                      "announce their capabilities you still "
                                      "have the possibility to turn leaving "
                                      "fetched messages on the server on."));
Igor Trindade Oliveira's avatar
Igor Trindade Oliveira committed
252
253
254
    }
}

255
void AccountWidget::slotPipeliningClicked()
Igor Trindade Oliveira's avatar
Igor Trindade Oliveira committed
256
{
Laurent Montel's avatar
Laurent Montel committed
257
    if (usePipeliningCheck->isChecked()) {
Laurent Montel's avatar
Laurent Montel committed
258
259
260
        KMessageBox::information(topLevelWidget(),
                                 i18n("Please note that this feature can cause some POP3 servers "
                                      "that do not support pipelining to send corrupted mail;\n"
261
262
                                      "this is configurable, though, because some servers support pipelining\n"
                                      "but do not announce their capabilities. To check whether your POP3 server\n"
263
264
                                      "announces pipelining support use the \"Auto Detect\""
                                      " button at the bottom of the dialog;\n"
265
266
                                      "if your server does not announce it, but you want more speed, then\n"
                                      "you should do some testing first by sending yourself a batch\n"
Laurent Montel's avatar
Laurent Montel committed
267
268
                                      "of mail and downloading it."),
                                 QString(),
Laurent Montel's avatar
Laurent Montel committed
269
                                 QStringLiteral("pipelining"));
Laurent Montel's avatar
Laurent Montel committed
270
    }
Igor Trindade Oliveira's avatar
Igor Trindade Oliveira committed
271
272
}

Laurent Montel's avatar
Laurent Montel committed
273
void AccountWidget::slotPopEncryptionChanged(QAbstractButton *button)
Igor Trindade Oliveira's avatar
Igor Trindade Oliveira committed
274
{
Laurent Montel's avatar
Laurent Montel committed
275
276
277
278
279
280
281
    if (button) {
        const int id = encryptionButtonGroup->id(button);
        qCDebug(POP3RESOURCE_LOG) << "setting port";
        // adjust port
        if (id == Transport::EnumEncryption::SSL || portEdit->value() == 995) {
            portEdit->setValue((id == Transport::EnumEncryption::SSL) ? 995 : 110);
        }
Igor Trindade Oliveira's avatar
Igor Trindade Oliveira committed
282

Laurent Montel's avatar
Laurent Montel committed
283
284
285
        qCDebug(POP3RESOURCE_LOG) << "port set ";
        enablePopFeatures(); // removes invalid auth options from the combobox
    }
Igor Trindade Oliveira's avatar
Igor Trindade Oliveira committed
286
287
}

288
void AccountWidget::slotCheckPopCapabilities()
Igor Trindade Oliveira's avatar
Igor Trindade Oliveira committed
289
{
Laurent Montel's avatar
Laurent Montel committed
290
    if (hostEdit->text().isEmpty()) {
291
        KMessageBox::error(this,
Laurent Montel's avatar
Laurent Montel committed
292
293
                           i18n("Please specify a server and port on "
                                "the General tab first."));
Laurent Montel's avatar
Laurent Montel committed
294
295
296
297
        return;
    }
    delete mServerTest;
    mServerTest = new ServerTest(this);
Laurent Montel's avatar
Laurent Montel committed
298
    auto busyCursorHelper = new BusyCursorHelper(mServerTest);
Laurent Montel's avatar
Laurent Montel committed
299
    mServerTest->setProgressBar(checkCapabilitiesProgress);
300
    Q_EMIT okEnabled(false);
Laurent Montel's avatar
Laurent Montel committed
301
302
303
304
305
306
307
308
309
    checkCapabilitiesStack->setCurrentIndex(1);
    Transport::EnumEncryption::type encryptionType;
    if (encryptionSSL->isChecked()) {
        encryptionType = Transport::EnumEncryption::SSL;
    } else {
        encryptionType = Transport::EnumEncryption::None;
    }
    mServerTest->setPort(encryptionType, portEdit->value());
    mServerTest->setServer(hostEdit->text());
Laurent Montel's avatar
Laurent Montel committed
310
    mServerTest->setProtocol(QStringLiteral("pop"));
311
    connect(mServerTest, &MailTransport::ServerTest::finished, this, &AccountWidget::slotPopCapabilities);
Laurent Montel's avatar
Laurent Montel committed
312
313
314
315
    connect(mServerTest, &MailTransport::ServerTest::finished, busyCursorHelper, &BusyCursorHelper::deleteLater);

    mServerTest->start();
    mServerTestFailed = false;
Igor Trindade Oliveira's avatar
Igor Trindade Oliveira committed
316
317
}

318
void AccountWidget::slotPopCapabilities(const QVector<int> &encryptionTypes)
Igor Trindade Oliveira's avatar
Igor Trindade Oliveira committed
319
{
Laurent Montel's avatar
Laurent Montel committed
320
    checkCapabilitiesStack->setCurrentIndex(0);
321
    Q_EMIT okEnabled(true);
Igor Trindade Oliveira's avatar
Igor Trindade Oliveira committed
322

Laurent Montel's avatar
Laurent Montel committed
323
324
    // if both fail, popup a dialog
    if (!mServerTest->isNormalPossible() && !mServerTest->isSecurePossible()) {
325
        KMessageBox::error(this, i18n("Unable to connect to the server, please verify the server address."));
Laurent Montel's avatar
Laurent Montel committed
326
    }
327

328
    // If the servertest did not find any usable authentication modes, assume the
Laurent Montel's avatar
Laurent Montel committed
329
330
331
332
333
    // connection failed and don't disable any of the radioboxes.
    if (encryptionTypes.isEmpty()) {
        mServerTestFailed = true;
        return;
    }
Igor Trindade Oliveira's avatar
Igor Trindade Oliveira committed
334

Laurent Montel's avatar
Laurent Montel committed
335
336
337
    encryptionNone->setEnabled(encryptionTypes.contains(Transport::EnumEncryption::None));
    encryptionSSL->setEnabled(encryptionTypes.contains(Transport::EnumEncryption::SSL));
    encryptionTLS->setEnabled(encryptionTypes.contains(Transport::EnumEncryption::TLS));
338

Laurent Montel's avatar
Laurent Montel committed
339
    usePipeliningCheck->setChecked(mServerTest->capabilities().contains(ServerTest::Pipelining));
340

Laurent Montel's avatar
Laurent Montel committed
341
    checkHighest(encryptionButtonGroup);
Igor Trindade Oliveira's avatar
Igor Trindade Oliveira committed
342
343
}

344
void AccountWidget::enablePopFeatures()
Igor Trindade Oliveira's avatar
Igor Trindade Oliveira committed
345
{
Laurent Montel's avatar
Laurent Montel committed
346
347
348
349
    if (!mServerTest || mServerTestFailed) {
        return;
    }

350
    QVector<int> supportedAuths;
Laurent Montel's avatar
Laurent Montel committed
351
352
353
354
355
356
357
358
359
360
361
    if (encryptionButtonGroup->checkedId() == Transport::EnumEncryption::None) {
        supportedAuths = mServerTest->normalProtocols();
    }
    if (encryptionButtonGroup->checkedId() == Transport::EnumEncryption::SSL) {
        supportedAuths = mServerTest->secureProtocols();
    }
    if (encryptionButtonGroup->checkedId() == Transport::EnumEncryption::TLS) {
        supportedAuths = mServerTest->tlsProtocols();
    }

    authCombo->clear();
362
    for (int prot : std::as_const(supportedAuths)) {
Laurent Montel's avatar
Laurent Montel committed
363
        authCombo->addItem(Transport::authenticationTypeString(prot), prot);
Laurent Montel's avatar
Laurent Montel committed
364
365
    }

Laurent Montel's avatar
Laurent Montel committed
366
    if (mServerTest && !mServerTest->capabilities().contains(ServerTest::Pipelining) && usePipeliningCheck->isChecked()) {
Laurent Montel's avatar
Laurent Montel committed
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
        usePipeliningCheck->setChecked(false);
        KMessageBox::information(topLevelWidget(),
                                 i18n("The server does not seem to support "
                                      "pipelining; therefore, this option has "
                                      "been disabled.\n"
                                      "Since some servers do not correctly "
                                      "announce their capabilities you still "
                                      "have the possibility to turn pipelining "
                                      "on. But please note that this feature can "
                                      "cause some POP servers that do not "
                                      "support pipelining to send corrupt "
                                      "messages. So before using this feature "
                                      "with important mail you should first "
                                      "test it by sending yourself a larger "
                                      "number of test messages which you all "
                                      "download in one go from the POP "
                                      "server."));
    }

Laurent Montel's avatar
Laurent Montel committed
386
    if (mServerTest && !mServerTest->capabilities().contains(ServerTest::UIDL) && leaveOnServerCheck->isChecked()) {
Laurent Montel's avatar
Laurent Montel committed
387
388
389
390
391
392
393
394
395
396
397
398
        leaveOnServerCheck->setChecked(false);
        KMessageBox::information(topLevelWidget(),
                                 i18n("The server does not seem to support unique "
                                      "message numbers, but this is a "
                                      "requirement for leaving messages on the "
                                      "server; therefore, this option has been "
                                      "disabled.\n"
                                      "Since some servers do not correctly "
                                      "announce their capabilities you still "
                                      "have the possibility to turn leaving "
                                      "fetched messages on the server on."));
    }
Igor Trindade Oliveira's avatar
Igor Trindade Oliveira committed
399
400
}

Laurent Montel's avatar
Laurent Montel committed
401
static void addAuthenticationItem(QComboBox *combo, int authenticationType)
402
{
Laurent Montel's avatar
Laurent Montel committed
403
    combo->addItem(Transport::authenticationTypeString(authenticationType), QVariant(authenticationType));
404
}
405

406
void AccountWidget::populateDefaultAuthenticationOptions()
407
{
Laurent Montel's avatar
Laurent Montel committed
408
409
410
411
412
413
414
415
416
    authCombo->clear();
    addAuthenticationItem(authCombo, Transport::EnumAuthenticationType::CLEAR);
    addAuthenticationItem(authCombo, Transport::EnumAuthenticationType::LOGIN);
    addAuthenticationItem(authCombo, Transport::EnumAuthenticationType::PLAIN);
    addAuthenticationItem(authCombo, Transport::EnumAuthenticationType::CRAM_MD5);
    addAuthenticationItem(authCombo, Transport::EnumAuthenticationType::DIGEST_MD5);
    addAuthenticationItem(authCombo, Transport::EnumAuthenticationType::NTLM);
    addAuthenticationItem(authCombo, Transport::EnumAuthenticationType::GSSAPI);
    addAuthenticationItem(authCombo, Transport::EnumAuthenticationType::APOP);
417
418
}

419
void AccountWidget::slotLeaveOnServerDaysChanged(int value)
Igor Trindade Oliveira's avatar
Igor Trindade Oliveira committed
420
{
Laurent Montel's avatar
Laurent Montel committed
421
    leaveOnServerDaysSpin->setSuffix(i18np(" day", " days", value));
Igor Trindade Oliveira's avatar
Igor Trindade Oliveira committed
422
423
}

424
void AccountWidget::slotLeaveOnServerCountChanged(int value)
Igor Trindade Oliveira's avatar
Igor Trindade Oliveira committed
425
{
Laurent Montel's avatar
Laurent Montel committed
426
    leaveOnServerCountSpin->setSuffix(i18np(" message", " messages", value));
Igor Trindade Oliveira's avatar
Igor Trindade Oliveira committed
427
428
}

429
void AccountWidget::checkHighest(QButtonGroup *btnGroup)
Igor Trindade Oliveira's avatar
Igor Trindade Oliveira committed
430
{
Laurent Montel's avatar
Laurent Montel committed
431
432
433
434
435
436
437
438
    QListIterator<QAbstractButton *> it(btnGroup->buttons());
    it.toBack();
    while (it.hasPrevious()) {
        QAbstractButton *btn = it.previous();
        if (btn && btn->isEnabled()) {
            btn->animateClick();
            return;
        }
Igor Trindade Oliveira's avatar
Igor Trindade Oliveira committed
439
440
441
    }
}

442
void AccountWidget::slotAccepted()
Igor Trindade Oliveira's avatar
Igor Trindade Oliveira committed
443
{
Volker Krause's avatar
Volker Krause committed
444
    saveSettings();
445
    // Don't call accept() yet, saveSettings() triggers an asynchronous wallet operation,
Volker Krause's avatar
Volker Krause committed
446
    // which will call accept() when it is finished
Igor Trindade Oliveira's avatar
Igor Trindade Oliveira committed
447
448
}

449
void AccountWidget::saveSettings()
Igor Trindade Oliveira's avatar
Igor Trindade Oliveira committed
450
{
451
452
453
454
455
456
457
458
459
460
461
462
463
    mSettings.setName(nameEdit->text());
    mSettings.setIntervalCheckEnabled(intervalCheck->checkState() == Qt::Checked);
    mSettings.setIntervalCheckInterval(intervalSpin->value());
    mSettings.setHost(hostEdit->text().trimmed());
    mSettings.setPort(portEdit->value());
    mSettings.setLogin(loginEdit->text().trimmed());
    mSettings.setPrecommand(precommand->text());
    mSettings.setUseSSL(encryptionSSL->isChecked());
    mSettings.setUseTLS(encryptionTLS->isChecked());
    mSettings.setAuthenticationMethod(authCombo->itemData(authCombo->currentIndex()).toInt());
    mSettings.setUseProxy(proxyCheck->isChecked());
    mSettings.setPipelining(usePipeliningCheck->isChecked());
    mSettings.setLeaveOnServer(leaveOnServerCheck->isChecked());
Laurent Montel's avatar
Laurent Montel committed
464
465
466
    mSettings.setLeaveOnServerDays(leaveOnServerCheck->isChecked() ? (leaveOnServerDaysCheck->isChecked() ? leaveOnServerDaysSpin->value() : -1) : 0);
    mSettings.setLeaveOnServerCount(leaveOnServerCheck->isChecked() ? (leaveOnServerCountCheck->isChecked() ? leaveOnServerCountSpin->value() : -1) : 0);
    mSettings.setLeaveOnServerSize(leaveOnServerCheck->isChecked() ? (leaveOnServerSizeCheck->isChecked() ? leaveOnServerSizeSpin->value() : -1) : 0);
467
468
    mSettings.setTargetCollection(folderRequester->collection().id());
    mSettings.save();
Laurent Montel's avatar
Laurent Montel committed
469
470
471

    // Now, either save the password or delete it from the wallet. For both, we need
    // to open it.
Laurent Montel's avatar
Laurent Montel committed
472
    const bool userChangedPassword = mInitalPassword != passwordEdit->password();
Laurent Montel's avatar
Laurent Montel committed
473
474
475
    const bool userWantsToDeletePassword = passwordEdit->password().isEmpty() && userChangedPassword;
    // Move to async
    if ((!passwordEdit->password().isEmpty() && userChangedPassword) || userWantsToDeletePassword) {
Laurent Montel's avatar
Laurent Montel committed
476
        walletOpenedForSaving();
477
    }
Igor Trindade Oliveira's avatar
Igor Trindade Oliveira committed
478
479
}

480
void AccountWidget::slotEnableLeaveOnServerDays(bool state)
Igor Trindade Oliveira's avatar
Igor Trindade Oliveira committed
481
{
Laurent Montel's avatar
Laurent Montel committed
482
483
484
485
    if (state && !leaveOnServerDaysCheck->isEnabled()) {
        return;
    }
    leaveOnServerDaysSpin->setEnabled(state);
Igor Trindade Oliveira's avatar
Igor Trindade Oliveira committed
486
487
}

488
void AccountWidget::slotEnableLeaveOnServerCount(bool state)
Igor Trindade Oliveira's avatar
Igor Trindade Oliveira committed
489
{
Laurent Montel's avatar
Laurent Montel committed
490
491
492
493
    if (state && !leaveOnServerCountCheck->isEnabled()) {
        return;
    }
    leaveOnServerCountSpin->setEnabled(state);
Igor Trindade Oliveira's avatar
Igor Trindade Oliveira committed
494
495
}

496
void AccountWidget::slotEnableLeaveOnServerSize(bool state)
Igor Trindade Oliveira's avatar
Igor Trindade Oliveira committed
497
{
Laurent Montel's avatar
Laurent Montel committed
498
499
500
501
    if (state && !leaveOnServerSizeCheck->isEnabled()) {
        return;
    }
    leaveOnServerSizeSpin->setEnabled(state);
Igor Trindade Oliveira's avatar
Igor Trindade Oliveira committed
502
503
}

504
void AccountWidget::slotEnablePopInterval(bool state)
Igor Trindade Oliveira's avatar
Igor Trindade Oliveira committed
505
{
Laurent Montel's avatar
Laurent Montel committed
506
507
    intervalSpin->setEnabled(state);
    intervalLabel->setEnabled(state);
Igor Trindade Oliveira's avatar
Igor Trindade Oliveira committed
508
509
}

510
void AccountWidget::targetCollectionReceived(Akonadi::Collection::List collections)
Igor Trindade Oliveira's avatar
Igor Trindade Oliveira committed
511
{
Laurent Montel's avatar
Laurent Montel committed
512
    folderRequester->setCollection(collections.first());
Igor Trindade Oliveira's avatar
Igor Trindade Oliveira committed
513
514
}

515
void AccountWidget::localFolderRequestJobFinished(KJob *job)
516
{
Laurent Montel's avatar
Laurent Montel committed
517
518
519
520
521
    if (!job->error()) {
        Collection targetCollection = SpecialMailCollections::self()->defaultCollection(SpecialMailCollections::Inbox);
        Q_ASSERT(targetCollection.isValid());
        folderRequester->setCollection(targetCollection);
    }
522
}