proxy config is now saved properly
[quassel.git] / src / qtui / coreconnectdlg.cpp
1 /***************************************************************************
2  *   Copyright (C) 2005-08 by the Quassel IRC Team                         *
3  *   devel@quassel-irc.org                                                 *
4  *                                                                         *
5  *   This program is free software; you can redistribute it and/or modify  *
6  *   it under the terms of the GNU General Public License as published by  *
7  *   the Free Software Foundation; either version 2 of the License, or     *
8  *   (at your option) version 3.                                           *
9  *                                                                         *
10  *   This program is distributed in the hope that it will be useful,       *
11  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
12  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
13  *   GNU General Public License for more details.                          *
14  *                                                                         *
15  *   You should have received a copy of the GNU General Public License     *
16  *   along with this program; if not, write to the                         *
17  *   Free Software Foundation, Inc.,                                       *
18  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
19  ***************************************************************************/
20
21 #include <QDebug>
22 #include <QMessageBox>
23 #include <QNetworkProxy>
24
25 #include "coreconnectdlg.h"
26
27 #include "clientsettings.h"
28 #include "clientsyncer.h"
29 #include "coreconfigwizard.h"
30
31 CoreConnectDlg::CoreConnectDlg(QWidget *parent, bool autoconnect) : QDialog(parent) {
32   ui.setupUi(this);
33
34   clientSyncer = new ClientSyncer(this);
35   wizard = 0;
36
37   setAttribute(Qt::WA_DeleteOnClose);
38
39   doingAutoConnect = false;
40
41   ui.stackedWidget->setCurrentWidget(ui.accountPage);
42
43   CoreAccountSettings s;
44   AccountId lastacc = s.lastAccount();
45   autoConnectAccount = s.autoConnectAccount();
46   QListWidgetItem *currentItem = 0;
47   foreach(AccountId id, s.knownAccounts()) {
48     if(!id.isValid()) continue;
49     QVariantMap data = s.retrieveAccountData(id);
50     accounts[id] = data;
51     QListWidgetItem *item = new QListWidgetItem(data["AccountName"].toString(), ui.accountList);
52     item->setData(Qt::UserRole, QVariant::fromValue<AccountId>(id));
53     if(id == lastacc) currentItem = item;
54   }
55   if(currentItem) ui.accountList->setCurrentItem(currentItem);
56   else ui.accountList->setCurrentRow(0);
57
58   setAccountWidgetStates();
59
60   ui.accountButtonBox->button(QDialogButtonBox::Ok)->setFocus();
61   //ui.accountButtonBox->button(QDialogButtonBox::Ok)->setAutoDefault(true);
62
63   connect(clientSyncer, SIGNAL(socketStateChanged(QAbstractSocket::SocketState)),this, SLOT(initPhaseSocketState(QAbstractSocket::SocketState)));
64   connect(clientSyncer, SIGNAL(connectionError(const QString &)), this, SLOT(initPhaseError(const QString &)));
65   connect(clientSyncer, SIGNAL(connectionMsg(const QString &)), this, SLOT(initPhaseMsg(const QString &)));
66   connect(clientSyncer, SIGNAL(encrypted(bool)), this, SLOT(encrypted(bool)));
67   connect(clientSyncer, SIGNAL(startLogin()), this, SLOT(startLogin()));
68   connect(clientSyncer, SIGNAL(loginFailed(const QString &)), this, SLOT(loginFailed(const QString &)));
69   connect(clientSyncer, SIGNAL(loginSuccess()), this, SLOT(startSync()));
70   connect(clientSyncer, SIGNAL(startCoreSetup(const QVariantList &)), this, SLOT(startCoreConfig(const QVariantList &)));
71   connect(clientSyncer, SIGNAL(sessionProgress(quint32, quint32)), this, SLOT(coreSessionProgress(quint32, quint32)));
72   connect(clientSyncer, SIGNAL(networksProgress(quint32, quint32)), this, SLOT(coreNetworksProgress(quint32, quint32)));
73   connect(clientSyncer, SIGNAL(channelsProgress(quint32, quint32)), this, SLOT(coreChannelsProgress(quint32, quint32)));
74   connect(clientSyncer, SIGNAL(ircUsersProgress(quint32, quint32)), this, SLOT(coreIrcUsersProgress(quint32, quint32)));
75   connect(clientSyncer, SIGNAL(syncFinished()), this, SLOT(syncFinished()));
76
77   connect(ui.user, SIGNAL(textChanged(const QString &)), this, SLOT(setLoginWidgetStates()));
78   connect(ui.password, SIGNAL(textChanged(const QString &)), this, SLOT(setLoginWidgetStates()));
79
80   connect(ui.loginButtonBox, SIGNAL(rejected()), this, SLOT(restartPhaseNull()));
81   connect(ui.syncButtonBox->button(QDialogButtonBox::Abort), SIGNAL(clicked()), this, SLOT(restartPhaseNull()));
82
83   if(autoconnect && ui.accountList->count() && autoConnectAccount.isValid()
84      && autoConnectAccount == ui.accountList->currentItem()->data(Qt::UserRole).value<AccountId>()) {
85     doingAutoConnect = true;
86     on_accountButtonBox_accepted();
87   }
88 }
89
90 CoreConnectDlg::~CoreConnectDlg() {
91   if(ui.accountList->selectedItems().count()) {
92     CoreAccountSettings s;
93     s.setLastAccount(ui.accountList->selectedItems()[0]->data(Qt::UserRole).value<AccountId>());
94   }
95 }
96
97
98 /****************************************************
99  * Account Management
100  ***************************************************/
101
102 void CoreConnectDlg::on_accountList_itemSelectionChanged() {
103   setAccountWidgetStates();
104 }
105
106 void CoreConnectDlg::setAccountWidgetStates() {
107   QList<QListWidgetItem *> selectedItems = ui.accountList->selectedItems();
108   ui.editAccount->setEnabled(selectedItems.count());
109   ui.deleteAccount->setEnabled(selectedItems.count());
110   ui.autoConnect->setEnabled(selectedItems.count());
111   if(selectedItems.count()) {
112     ui.autoConnect->setChecked(selectedItems[0]->data(Qt::UserRole).value<AccountId>() == autoConnectAccount);
113   }
114   ui.accountButtonBox->button(QDialogButtonBox::Ok)->setEnabled(ui.accountList->count());
115 }
116
117 void CoreConnectDlg::on_autoConnect_clicked(bool state) {
118   if(!state) {
119     autoConnectAccount = 0;
120   } else {
121     if(ui.accountList->selectedItems().count()) {
122       autoConnectAccount = ui.accountList->selectedItems()[0]->data(Qt::UserRole).value<AccountId>();
123     } else {
124       qWarning() << "Checked auto connect without an enabled item!";  // should never happen!
125       autoConnectAccount = 0;
126     }
127   }
128   setAccountWidgetStates();
129 }
130
131 void CoreConnectDlg::on_addAccount_clicked() {
132   QStringList existing;
133   for(int i = 0; i < ui.accountList->count(); i++) existing << ui.accountList->item(i)->text();
134   CoreAccountEditDlg dlg(0, QVariantMap(), existing, this);
135   if(dlg.exec() == QDialog::Accepted) {
136     // find free ID
137     AccountId id = accounts.count() + 1;
138     for(AccountId i = 1; i <= accounts.count(); i++) {
139       if(!accounts.keys().contains(i)) {
140         id = i;
141         break;
142       }
143     }
144     QVariantMap data = dlg.accountData();
145     data["AccountId"] = QVariant::fromValue<AccountId>(id);
146     accounts[id] = data;
147     QListWidgetItem *item = new QListWidgetItem(data["AccountName"].toString(), ui.accountList);
148     item->setData(Qt::UserRole, QVariant::fromValue<AccountId>(id));
149     ui.accountList->setCurrentItem(item);
150   }
151 }
152
153 void CoreConnectDlg::on_editAccount_clicked() {
154   QStringList existing;
155   for(int i = 0; i < ui.accountList->count(); i++) existing << ui.accountList->item(i)->text();
156   AccountId id = ui.accountList->currentItem()->data(Qt::UserRole).value<AccountId>();
157   QVariantMap acct = accounts[id];
158   CoreAccountEditDlg dlg(id, acct, existing, this);
159   if(dlg.exec() == QDialog::Accepted) {
160     QVariantMap data = dlg.accountData();
161     ui.accountList->currentItem()->setText(data["AccountName"].toString());
162     accounts[id] = data;
163   }
164 }
165
166 void CoreConnectDlg::on_deleteAccount_clicked() {
167   AccountId id = ui.accountList->currentItem()->data(Qt::UserRole).value<AccountId>();
168   int ret = QMessageBox::question(this, tr("Remove Account Settings"),
169                                   tr("Do you really want to remove your local settings for this Quassel Core account?<br>"
170                                   "Note: This will <em>not</em> remove or change any data on the Core itself!"),
171                                   QMessageBox::Yes|QMessageBox::No, QMessageBox::No);
172   if(ret == QMessageBox::Yes) {
173     int idx = ui.accountList->currentRow();
174     delete ui.accountList->takeItem(idx);
175     ui.accountList->setCurrentRow(qMin(idx, ui.accountList->count()-1));
176     accounts[id]["Delete"] = true;  // we only flag this here, actual deletion happens on accept!
177     setAccountWidgetStates();
178   }
179 }
180
181 void CoreConnectDlg::on_accountList_itemDoubleClicked(QListWidgetItem *item) {
182   Q_UNUSED(item);
183   on_accountButtonBox_accepted();
184 }
185
186 void CoreConnectDlg::on_accountButtonBox_accepted() {
187   // save accounts
188   CoreAccountSettings s;
189   foreach(QVariantMap acct, accounts.values()) {
190     AccountId id = acct["AccountId"].value<AccountId>();
191     if(acct.contains("Delete")) {
192       s.removeAccount(id);
193     } else {
194       s.storeAccountData(id, acct);
195     }
196   }
197   s.setAutoConnectAccount(autoConnectAccount);
198
199   ui.stackedWidget->setCurrentWidget(ui.loginPage);
200   account = ui.accountList->currentItem()->data(Qt::UserRole).value<AccountId>();
201   accountData = accounts[account];
202   s.setLastAccount(account);
203   connectToCore();
204 }
205
206 /*****************************************************
207  * Connecting to the Core
208  ****************************************************/
209
210 /*** Phase One: initializing the core connection ***/
211
212 void CoreConnectDlg::connectToCore() {
213   ui.secureConnection->hide();
214   ui.connectIcon->setPixmap(QPixmap::fromImage(QImage(":/22x22/actions/network-disconnect")));
215   ui.connectLabel->setText(tr("Connect to %1").arg(accountData["Host"].toString()));
216   ui.coreInfoLabel->setText("");
217   ui.loginStack->setCurrentWidget(ui.loginEmptyPage);
218   ui.loginButtonBox->setStandardButtons(QDialogButtonBox::Cancel|QDialogButtonBox::Ok);
219   ui.loginButtonBox->button(QDialogButtonBox::Ok)->setDefault(true);
220   ui.loginButtonBox->button(QDialogButtonBox::Ok)->setDisabled(true);
221   disconnect(ui.loginButtonBox, 0, this, 0);
222   connect(ui.loginButtonBox, SIGNAL(rejected()), this, SLOT(restartPhaseNull()));
223
224   clientSyncer->connectToCore(accountData);
225 }
226
227 void CoreConnectDlg::initPhaseError(const QString &error) {
228   doingAutoConnect = false;
229   ui.secureConnection->hide();
230   ui.connectIcon->setPixmap(QPixmap::fromImage(QImage(":/22x22/status/dialog-error")));
231   //ui.connectLabel->setBrush(QBrush("red"));
232   ui.connectLabel->setText(tr("<div style=color:red;>Connection to %1 failed!</div>").arg(accountData["Host"].toString()));
233   ui.coreInfoLabel->setText(error);
234   ui.loginButtonBox->setStandardButtons(QDialogButtonBox::Retry|QDialogButtonBox::Cancel);
235   ui.loginButtonBox->button(QDialogButtonBox::Retry)->setFocus();
236   disconnect(ui.loginButtonBox, 0, this, 0);
237   connect(ui.loginButtonBox, SIGNAL(accepted()), this, SLOT(restartPhaseNull()));
238   connect(ui.loginButtonBox, SIGNAL(rejected()), this, SLOT(reject()));
239 }
240
241 void CoreConnectDlg::initPhaseMsg(const QString &msg) {
242   ui.coreInfoLabel->setText(msg);
243 }
244
245 void CoreConnectDlg::encrypted(bool useSsl) {
246   if(useSsl)
247     ui.secureConnection->show();
248   else
249     ui.secureConnection->hide();
250 }
251
252 void CoreConnectDlg::initPhaseSocketState(QAbstractSocket::SocketState state) {
253   QString s;
254   QString host = accountData["Host"].toString();
255   switch(state) {
256     case QAbstractSocket::UnconnectedState: s = tr("Not connected to %1.").arg(host); break;
257     case QAbstractSocket::HostLookupState: s = tr("Looking up %1...").arg(host); break;
258     case QAbstractSocket::ConnectingState: s = tr("Connecting to %1...").arg(host); break;
259     case QAbstractSocket::ConnectedState: s = tr("Connected to %1").arg(host); break;
260     default: s = tr("Unknown connection state to %1"); break;
261   }
262   ui.connectLabel->setText(s);
263 }
264
265 void CoreConnectDlg::restartPhaseNull() {
266   doingAutoConnect = false;
267   ui.stackedWidget->setCurrentWidget(ui.accountPage);
268   clientSyncer->disconnectFromCore();
269 }
270
271 /*********************************************************
272  * Phase Two: Login
273  *********************************************************/
274
275 void CoreConnectDlg::startLogin() {
276   ui.connectIcon->setPixmap(QPixmap::fromImage(QImage(":/22x22/actions/network-connect")));
277   ui.loginStack->setCurrentWidget(ui.loginCredentialsPage);
278   //ui.loginStack->setMinimumSize(ui.loginStack->sizeHint()); ui.loginStack->updateGeometry();
279   ui.loginButtonBox->setStandardButtons(QDialogButtonBox::Ok|QDialogButtonBox::Cancel);
280   ui.loginButtonBox->button(QDialogButtonBox::Ok)->setDefault(true);
281   ui.loginButtonBox->button(QDialogButtonBox::Ok)->setFocus();
282   if(!accountData["User"].toString().isEmpty()) {
283     ui.user->setText(accountData["User"].toString());
284     if(accountData["RememberPasswd"].toBool()) {
285       ui.password->setText(accountData["Password"].toString());
286       ui.rememberPasswd->setChecked(true);
287       ui.loginButtonBox->button(QDialogButtonBox::Ok)->setFocus();
288     } else {
289       ui.rememberPasswd->setChecked(false);
290       ui.password->setFocus();
291     }
292   } else ui.user->setFocus();
293   disconnect(ui.loginButtonBox, 0, this, 0);
294   connect(ui.loginButtonBox, SIGNAL(accepted()), this, SLOT(doLogin()));
295   connect(ui.loginButtonBox, SIGNAL(rejected()), this, SLOT(restartPhaseNull()));
296   if(doingAutoConnect) doLogin();
297 }
298
299 void CoreConnectDlg::doLogin() {
300   QVariantMap loginData;
301   loginData["User"] = ui.user->text();
302   loginData["Password"] = ui.password->text();
303   loginData["RememberPasswd"] = ui.rememberPasswd->isChecked();
304   doLogin(loginData);
305 }
306
307 void CoreConnectDlg::doLogin(const QVariantMap &loginData) {
308   disconnect(ui.loginButtonBox, 0, this, 0);
309   connect(ui.loginButtonBox, SIGNAL(accepted()), this, SLOT(doLogin()));
310   connect(ui.loginButtonBox, SIGNAL(rejected()), this, SLOT(restartPhaseNull()));
311   ui.loginStack->setCurrentWidget(ui.loginCredentialsPage);
312   ui.loginGroup->setTitle(tr("Logging in..."));
313   ui.user->setDisabled(true);
314   ui.password->setDisabled(true);
315   ui.rememberPasswd->setDisabled(true);
316   ui.loginButtonBox->button(QDialogButtonBox::Ok)->setDisabled(true);
317   accountData["User"] = loginData["User"];
318   accountData["RememberPasswd"] = loginData["RememberPasswd"];
319   if(loginData["RememberPasswd"].toBool()) accountData["Password"] = loginData["Password"];
320   else accountData.remove("Password");
321   ui.user->setText(loginData["User"].toString());
322   ui.password->setText(loginData["Password"].toString());
323   ui.rememberPasswd->setChecked(loginData["RememberPasswd"].toBool());
324   CoreAccountSettings s;
325   s.storeAccountData(account, accountData);
326   clientSyncer->loginToCore(loginData["User"].toString(), loginData["Password"].toString());
327 }
328
329 void CoreConnectDlg::setLoginWidgetStates() {
330   ui.loginButtonBox->button(QDialogButtonBox::Ok)->setDisabled(ui.user->text().isEmpty() || ui.password->text().isEmpty());
331 }
332
333 void CoreConnectDlg::loginFailed(const QString &error) {
334   if(wizard) {
335     wizard->reject();
336   }
337   ui.loginStack->setCurrentWidget(ui.loginCredentialsPage);
338   ui.loginGroup->setTitle(tr("Login"));
339   ui.user->setEnabled(true);
340   ui.password->setEnabled(true);
341   ui.rememberPasswd->setEnabled(true);
342   ui.coreInfoLabel->setText(error);
343   ui.loginButtonBox->button(QDialogButtonBox::Ok)->setEnabled(true);
344   ui.password->setFocus();
345   doingAutoConnect = false;
346 }
347
348 void CoreConnectDlg::startCoreConfig(const QVariantList &backends) {
349   storageBackends = backends;
350   ui.loginStack->setCurrentWidget(ui.coreConfigPage);
351
352   //on_launchCoreConfigWizard_clicked();
353
354 }
355
356 void CoreConnectDlg::on_launchCoreConfigWizard_clicked() {
357   Q_ASSERT(!wizard);
358   wizard = new CoreConfigWizard(storageBackends, this);
359   connect(wizard, SIGNAL(setupCore(const QVariant &)), clientSyncer, SLOT(doCoreSetup(const QVariant &)));
360   connect(wizard, SIGNAL(loginToCore(const QVariantMap &)), this, SLOT(doLogin(const QVariantMap &)));
361   connect(clientSyncer, SIGNAL(coreSetupSuccess()), wizard, SLOT(coreSetupSuccess()));
362   connect(clientSyncer, SIGNAL(coreSetupFailed(const QString &)), wizard, SLOT(coreSetupFailed(const QString &)));
363   connect(wizard, SIGNAL(accepted()), this, SLOT(configWizardAccepted()));
364   connect(wizard, SIGNAL(rejected()), this, SLOT(configWizardRejected()));
365   connect(clientSyncer, SIGNAL(loginSuccess()), wizard, SLOT(loginSuccess()));
366   connect(clientSyncer, SIGNAL(syncFinished()), wizard, SLOT(syncFinished()));
367   wizard->show();
368 }
369
370 void CoreConnectDlg::configWizardAccepted() {
371
372   wizard->deleteLater();
373   wizard = 0;
374 }
375
376 void CoreConnectDlg::configWizardRejected() {
377
378   wizard->deleteLater();
379   wizard = 0;
380   //exit(1); // FIXME
381 }
382
383
384 /************************************************************
385  * Phase Three: Syncing
386  ************************************************************/
387
388 void CoreConnectDlg::startSync() {
389   ui.sessionProgress->setRange(0, 1);
390   ui.sessionProgress->setValue(0);
391   ui.networksProgress->setRange(0, 1);
392   ui.networksProgress->setValue(0);
393   ui.channelsProgress->setRange(0, 1);
394   ui.channelsProgress->setValue(0);
395   ui.ircUsersProgress->setRange(0, 1);
396   ui.ircUsersProgress->setValue(0);
397
398   ui.stackedWidget->setCurrentWidget(ui.syncPage);
399   // clean up old page
400   ui.loginGroup->setTitle(tr("Login"));
401   ui.user->setEnabled(true);
402   ui.password->setEnabled(true);
403   ui.rememberPasswd->setEnabled(true);
404   ui.loginButtonBox->button(QDialogButtonBox::Ok)->setEnabled(true);
405 }
406
407 void CoreConnectDlg::coreSessionProgress(quint32 val, quint32 max) {
408   ui.sessionProgress->setRange(0, max);
409   ui.sessionProgress->setValue(val);
410
411 }
412
413 void CoreConnectDlg::coreNetworksProgress(quint32 val, quint32 max) {
414   if(max == 0) {
415     ui.networksProgress->setFormat("0/0");
416     ui.networksProgress->setRange(0, 1);
417     ui.networksProgress->setValue(1);
418   } else {
419     ui.networksProgress->setFormat("%v/%m");
420     ui.networksProgress->setRange(0, max);
421     ui.networksProgress->setValue(val);
422   }
423 }
424
425 void CoreConnectDlg::coreChannelsProgress(quint32 val, quint32 max) {
426   if(max == 0) {
427     ui.channelsProgress->setFormat("0/0");
428     ui.channelsProgress->setRange(0, 1);
429     ui.channelsProgress->setValue(1);
430   } else {
431     ui.channelsProgress->setFormat("%v/%m");
432     ui.channelsProgress->setRange(0, max);
433     ui.channelsProgress->setValue(val);
434   }
435 }
436
437 void CoreConnectDlg::coreIrcUsersProgress(quint32 val, quint32 max) {
438   if(max == 0) {
439     ui.ircUsersProgress->setFormat("0/0");
440     ui.ircUsersProgress->setRange(0, 1);
441     ui.ircUsersProgress->setValue(1);
442   } else {
443     if(val % 100) return;
444     ui.ircUsersProgress->setFormat("%v/%m");
445     ui.ircUsersProgress->setRange(0, max);
446     ui.ircUsersProgress->setValue(val);
447   }
448 }
449
450 void CoreConnectDlg::syncFinished() {
451   if(!wizard) accept();
452   else {
453     hide();
454     disconnect(wizard, 0, this, 0);
455     connect(wizard, SIGNAL(finished(int)), this, SLOT(accept()));
456   }
457 }
458
459 /*****************************************************************************************
460  * CoreAccountEditDlg
461  *****************************************************************************************/
462 CoreAccountEditDlg::CoreAccountEditDlg(AccountId id, const QVariantMap &acct, const QStringList &_existing, QWidget *parent)
463   : QDialog(parent)
464 {
465   ui.setupUi(this);
466   existing = _existing;
467   if(id.isValid()) {
468     existing.removeAll(acct["AccountName"].toString());
469     ui.host->setText(acct["Host"].toString());
470     ui.port->setValue(acct["Port"].toUInt());
471     ui.useInternal->setChecked(acct["UseInternal"].toBool());
472     ui.accountName->setText(acct["AccountName"].toString());
473 #ifndef QT_NO_OPENSSL
474     ui.useSsl->setChecked(acct["useSsl"].toBool());
475 #else
476     ui.useSsl->setChecked(false);
477     ui.useSsl->setEnabled(false);
478 #endif
479     ui.useProxy->setChecked(acct["useProxy"].toBool());
480     ui.proxyHost->setText(acct["proxyHost"].toString());
481     ui.proxyPort->setValue(acct["proxyPort"].toUInt());
482     ui.proxyType->setCurrentIndex(acct["proxyType"].toInt() == QNetworkProxy::Socks5Proxy ? 0 : 1);
483     ui.proxyUser->setText(acct["proxyUser"].toString());
484     ui.proxyPassword->setText(acct["proxyPassword"].toString());
485   } else {
486     setWindowTitle(tr("Add Core Account"));
487 #ifdef QT_NO_OPENSSL
488     ui.useSsl->setChecked(false);
489     ui.useSsl->setEnabled(false);
490 #endif
491   }
492 }
493
494 QVariantMap CoreAccountEditDlg::accountData() {
495   account["AccountName"] = ui.accountName->text().trimmed();
496   account["Host"] = ui.host->text().trimmed();
497   account["Port"] = ui.port->value();
498   account["UseInternal"] = ui.useInternal->isChecked();
499   account["useSsl"] = ui.useSsl->isChecked();
500   account["useProxy"] = ui.useProxy->isChecked();
501   account["proxyHost"] = ui.proxyHost->text().trimmed();
502   account["proxyPort"] = ui.proxyPort->value();
503   account["proxyType"] = ui.proxyType->currentIndex() == 0 ? QNetworkProxy::Socks5Proxy : QNetworkProxy::HttpProxy;
504   account["proxyUser"] = ui.proxyUser->text().trimmed();
505   account["proxyPassword"] = ui.proxyPassword->text().trimmed();
506   return account;
507 }
508
509 void CoreAccountEditDlg::setWidgetStates() {
510   bool ok = !ui.accountName->text().trimmed().isEmpty() && !existing.contains(ui.accountName->text()) && (ui.useInternal->isChecked() || !ui.host->text().isEmpty());
511   ui.buttonBox->button(QDialogButtonBox::Ok)->setEnabled(ok);
512 }
513
514 void CoreAccountEditDlg::on_host_textChanged(const QString &text) {
515   Q_UNUSED(text);
516   setWidgetStates();
517 }
518
519 void CoreAccountEditDlg::on_accountName_textChanged(const QString &text) {
520   Q_UNUSED(text);
521   setWidgetStates();
522 }
523
524 void CoreAccountEditDlg::on_useRemote_toggled(bool state) {
525   Q_UNUSED(state);
526   setWidgetStates();
527 }