3a6f1cd6ad7c5e5af206e0f9a612de6b6249fdfd
[quassel.git] / src / qtui / settingspages / coreaccountsettingspage.cpp
1 /***************************************************************************
2  *   Copyright (C) 2005-2018 by the Quassel Project                        *
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  *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.         *
19  ***************************************************************************/
20
21 #include "coreaccountsettingspage.h"
22
23 #include "client.h"
24 #include "clientsettings.h"
25 #include "coreaccountmodel.h"
26 #include "icon.h"
27
28 CoreAccountSettingsPage::CoreAccountSettingsPage(QWidget *parent)
29     : SettingsPage(tr("Remote Cores"), QString(), parent),
30     _lastAccountId(0),
31     _lastAutoConnectId(0)
32 {
33     ui.setupUi(this);
34     initAutoWidgets();
35     ui.addAccountButton->setIcon(icon::get("list-add"));
36     ui.editAccountButton->setIcon(icon::get("document-edit"));
37     ui.deleteAccountButton->setIcon(icon::get("edit-delete"));
38
39     _model = new CoreAccountModel(Client::coreAccountModel(), this);
40     _filteredModel = new FilteredCoreAccountModel(_model, this);
41
42     ui.accountView->setModel(filteredModel());
43     ui.autoConnectAccount->setModel(filteredModel());
44
45     connect(filteredModel(), SIGNAL(rowsAboutToBeRemoved(QModelIndex, int, int)), SLOT(rowsAboutToBeRemoved(QModelIndex, int, int)));
46     connect(filteredModel(), SIGNAL(rowsInserted(QModelIndex, int, int)), SLOT(rowsInserted(QModelIndex, int, int)));
47
48     connect(ui.accountView->selectionModel(), SIGNAL(selectionChanged(QItemSelection, QItemSelection)), SLOT(setWidgetStates()));
49     connect(ui.autoConnectAccount, SIGNAL(currentIndexChanged(int)), SLOT(widgetHasChanged()));
50     setWidgetStates();
51 }
52
53
54 void CoreAccountSettingsPage::setStandAlone(bool standalone)
55 {
56     _standalone = standalone;
57 }
58
59
60 void CoreAccountSettingsPage::load()
61 {
62     model()->update(Client::coreAccountModel());
63     SettingsPage::load();
64
65     CoreAccountSettings s;
66
67     if (Quassel::runMode() != Quassel::Monolithic) {
68         // make sure we don't have selected the internal account as autoconnect account
69
70         if (s.autoConnectOnStartup() && s.autoConnectToFixedAccount()) {
71             CoreAccount acc = model()->account(s.autoConnectAccount());
72             if (acc.isInternal())
73                 ui.autoConnectOnStartup->setChecked(false);
74         }
75     }
76     ui.accountView->setCurrentIndex(filteredModel()->index(0, 0));
77     ui.accountView->selectionModel()->select(filteredModel()->index(0, 0), QItemSelectionModel::Select);
78
79     QModelIndex idx = filteredModel()->mapFromSource(model()->accountIndex(s.autoConnectAccount()));
80     ui.autoConnectAccount->setCurrentIndex(idx.isValid() ? idx.row() : 0);
81     ui.autoConnectAccount->setProperty("storedValue", ui.autoConnectAccount->currentIndex());
82     setWidgetStates();
83     // Mark as no changes made, we just loaded settings
84     setChangedState(false);
85 }
86
87
88 void CoreAccountSettingsPage::save()
89 {
90     SettingsPage::save();
91     Client::coreAccountModel()->update(model());
92     Client::coreAccountModel()->save();
93     CoreAccountSettings s;
94     AccountId id = filteredModel()->index(ui.autoConnectAccount->currentIndex(), 0).data(CoreAccountModel::AccountIdRole).value<AccountId>();
95     s.setAutoConnectAccount(id);
96     ui.autoConnectAccount->setProperty("storedValue", ui.autoConnectAccount->currentIndex());
97 }
98
99
100 // TODO: Qt 4.6 - replace by proper rowsMoved() semantics
101 // NOTE: This is the filtered model
102 void CoreAccountSettingsPage::rowsAboutToBeRemoved(const QModelIndex &index, int start, int end)
103 {
104     _lastAutoConnectId = _lastAccountId = 0;
105     if (index.isValid() || start != end)
106         return;
107
108     // the current index is removed, so remember it in case it's reinserted immediately afterwards
109     AccountId id = filteredModel()->index(start, 0).data(CoreAccountModel::AccountIdRole).value<AccountId>();
110     if (start == ui.accountView->currentIndex().row())
111         _lastAccountId = id;
112     if (start == ui.autoConnectAccount->currentIndex())
113         _lastAutoConnectId = id;
114 }
115
116
117 void CoreAccountSettingsPage::rowsInserted(const QModelIndex &index, int start, int end)
118 {
119     if (index.isValid() || start != end)
120         return;
121
122     // check if the inserted index was just removed and select it in that case
123     AccountId id = filteredModel()->index(start, 0).data(CoreAccountModel::AccountIdRole).value<AccountId>();
124     if (id == _lastAccountId)
125         ui.accountView->setCurrentIndex(filteredModel()->index(start, 0));
126     if (id == _lastAutoConnectId)
127         ui.autoConnectAccount->setCurrentIndex(start);
128     _lastAccountId = _lastAutoConnectId = 0;
129 }
130
131
132 AccountId CoreAccountSettingsPage::selectedAccount() const
133 {
134     QModelIndex index = ui.accountView->currentIndex();
135     if (!index.isValid())
136         return 0;
137     return index.data(CoreAccountModel::AccountIdRole).value<AccountId>();
138 }
139
140
141 void CoreAccountSettingsPage::setSelectedAccount(AccountId accId)
142 {
143     QModelIndex index = filteredModel()->mapFromSource(model()->accountIndex(accId));
144     if (index.isValid())
145         ui.accountView->setCurrentIndex(index);
146 }
147
148
149 void CoreAccountSettingsPage::on_addAccountButton_clicked()
150 {
151     CoreAccountEditDlg dlg(CoreAccount(), this);
152     if (dlg.exec() == QDialog::Accepted) {
153         AccountId id = model()->createOrUpdateAccount(dlg.account());
154         ui.accountView->setCurrentIndex(filteredModel()->mapFromSource(model()->accountIndex(id)));
155         widgetHasChanged();
156     }
157 }
158
159
160 void CoreAccountSettingsPage::on_editAccountButton_clicked()
161 {
162     QModelIndex idx = ui.accountView->selectionModel()->currentIndex();
163     if (!idx.isValid())
164         return;
165
166     editAccount(idx);
167 }
168
169
170 void CoreAccountSettingsPage::editAccount(const QModelIndex &index)
171 {
172     if (!index.isValid())
173         return;
174
175     CoreAccountEditDlg dlg(model()->account(filteredModel()->mapToSource(index)), this);
176     if (dlg.exec() == QDialog::Accepted) {
177         AccountId id = model()->createOrUpdateAccount(dlg.account());
178         ui.accountView->setCurrentIndex(filteredModel()->mapFromSource(model()->accountIndex(id)));
179         widgetHasChanged();
180     }
181 }
182
183
184 void CoreAccountSettingsPage::on_deleteAccountButton_clicked()
185 {
186     if (!ui.accountView->selectionModel()->selectedIndexes().count())
187         return;
188
189     AccountId id = ui.accountView->selectionModel()->selectedIndexes().at(0).data(CoreAccountModel::AccountIdRole).value<AccountId>();
190     if (id.isValid()) {
191         model()->removeAccount(id);
192         widgetHasChanged();
193     }
194 }
195
196
197 void CoreAccountSettingsPage::on_accountView_doubleClicked(const QModelIndex &index)
198 {
199     if (!index.isValid())
200         return;
201
202     if (isStandAlone())
203         emit connectToCore(index.data(CoreAccountModel::AccountIdRole).value<AccountId>());
204     else
205         editAccount(index);
206 }
207
208
209 void CoreAccountSettingsPage::setWidgetStates()
210 {
211     AccountId accId = selectedAccount();
212     bool editable = accId.isValid() && accId != model()->internalAccount();
213
214     ui.editAccountButton->setEnabled(editable);
215     ui.deleteAccountButton->setEnabled(editable);
216 }
217
218
219 void CoreAccountSettingsPage::widgetHasChanged()
220 {
221     setChangedState(testHasChanged());
222     setWidgetStates();
223 }
224
225
226 bool CoreAccountSettingsPage::testHasChanged()
227 {
228     if (ui.autoConnectAccount->currentIndex() !=
229             ui.autoConnectAccount->property("storedValue").toInt()) {
230         return true;
231     }
232     if (*model() != *Client::coreAccountModel()) {
233         return true;
234     }
235
236     return false;
237 }
238
239
240 /*****************************************************************************************
241  * CoreAccountEditDlg
242  *****************************************************************************************/
243 CoreAccountEditDlg::CoreAccountEditDlg(const CoreAccount &acct, QWidget *parent)
244     : QDialog(parent)
245 {
246     ui.setupUi(this);
247
248     _account = acct;
249
250     ui.hostName->setText(acct.hostName());
251     ui.port->setValue(acct.port());
252     ui.accountName->setText(acct.accountName());
253     ui.user->setText(acct.user());
254     ui.password->setText(acct.password());
255     ui.rememberPassword->setChecked(acct.storePassword());
256
257     ui.buttonGroupProxyType->setId(ui.radioButtonNoProxy, 0);
258     ui.buttonGroupProxyType->setId(ui.radioButtonSystemProxy, 1);
259     ui.buttonGroupProxyType->setId(ui.radioButtonManualProxy, 2);
260
261     bool manualProxy = false;
262     switch (acct.proxyType()) {
263     case QNetworkProxy::NoProxy:
264         ui.buttonGroupProxyType->button(0)->setChecked(true);
265         break;
266     case QNetworkProxy::DefaultProxy:
267         ui.buttonGroupProxyType->button(1)->setChecked(true);
268         break;
269     case QNetworkProxy::Socks5Proxy:
270         ui.buttonGroupProxyType->button(2)->setChecked(true);
271         ui.proxyType->setCurrentIndex(0);
272         manualProxy = true;
273         break;
274     case QNetworkProxy::HttpProxy:
275         ui.buttonGroupProxyType->button(2)->setChecked(true);
276         ui.proxyType->setCurrentIndex(1);
277         manualProxy = true;
278         break;
279     default:
280         break;
281     }
282
283     if (manualProxy) {
284         ui.proxyHostName->setText(acct.proxyHostName());
285         ui.proxyPort->setValue(acct.proxyPort());
286         ui.proxyType->setEnabled(true);
287         ui.proxyUser->setText(acct.proxyUser());
288         ui.proxyPassword->setText(acct.proxyPassword());
289     }
290
291     if (acct.accountId().isValid())
292         setWindowTitle(tr("Edit Core Account"));
293     else
294         setWindowTitle(tr("Add Core Account"));
295 }
296
297
298 CoreAccount CoreAccountEditDlg::account()
299 {
300     _account.setAccountName(ui.accountName->text().trimmed());
301     _account.setHostName(ui.hostName->text().trimmed());
302     _account.setPort(ui.port->value());
303     _account.setUser(ui.user->text().trimmed());
304     _account.setPassword(ui.password->text());
305     _account.setStorePassword(ui.rememberPassword->isChecked());
306
307     QNetworkProxy::ProxyType proxyType = QNetworkProxy::NoProxy;
308     int checkedId = ui.buttonGroupProxyType->checkedId();
309
310     switch (checkedId) {
311     case NoProxy: // QNetworkProxy::NoProxy
312         QNetworkProxyFactory::setUseSystemConfiguration(false);
313         _account.setProxyType(proxyType);
314         break;
315     case SystemProxy: // QNetworkProxy::DefaultProxy:
316         QNetworkProxyFactory::setUseSystemConfiguration(true);
317         _account.setProxyType(QNetworkProxy::DefaultProxy);
318         break;
319     case ManualProxy: // QNetworkProxy::Socks5Proxy || QNetworkProxy::HttpProxy
320         proxyType = ui.proxyType->currentIndex() == 0 ?
321                     QNetworkProxy::Socks5Proxy : QNetworkProxy::HttpProxy;
322         QNetworkProxyFactory::setUseSystemConfiguration(false);
323         _account.setProxyHostName(ui.proxyHostName->text().trimmed());
324         _account.setProxyPort(ui.proxyPort->value());
325         _account.setProxyType(proxyType);
326         _account.setProxyUser(ui.proxyUser->text().trimmed());
327         _account.setProxyPassword(ui.proxyPassword->text());
328         break;
329     default:
330         break;
331     }
332     return _account;
333 }
334
335
336 void CoreAccountEditDlg::setWidgetStates()
337 {
338     bool ok = !ui.accountName->text().trimmed().isEmpty()
339               && !ui.user->text().trimmed().isEmpty()
340               && !ui.hostName->text().isEmpty();
341     ui.buttonBox->button(QDialogButtonBox::Ok)->setEnabled(ok);
342 }
343
344
345 void CoreAccountEditDlg::on_hostName_textChanged(const QString &text)
346 {
347     Q_UNUSED(text);
348     setWidgetStates();
349 }
350
351
352 void CoreAccountEditDlg::on_accountName_textChanged(const QString &text)
353 {
354     Q_UNUSED(text);
355     setWidgetStates();
356 }
357
358
359 void CoreAccountEditDlg::on_user_textChanged(const QString &text)
360 {
361     Q_UNUSED(text)
362     setWidgetStates();
363 }
364
365 void CoreAccountEditDlg::on_radioButtonManualProxy_toggled(bool checked)
366 {
367     ui.proxyType->setEnabled(checked);
368     ui.proxyHostName->setEnabled(checked);
369     ui.proxyPort->setEnabled(checked);
370     ui.proxyUser->setEnabled(checked);
371     ui.proxyPassword->setEnabled(checked);
372 }
373
374
375 /*****************************************************************************************
376  * FilteredCoreAccountModel
377  *****************************************************************************************/
378
379 FilteredCoreAccountModel::FilteredCoreAccountModel(CoreAccountModel *model, QObject *parent) : QSortFilterProxyModel(parent)
380 {
381     _internalAccount = model->internalAccount();
382     setSourceModel(model);
383 }
384
385
386 bool FilteredCoreAccountModel::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const
387 {
388     if (Quassel::runMode() == Quassel::Monolithic)
389         return true;
390
391     if (!_internalAccount.isValid())
392         return true;
393
394     return _internalAccount != sourceModel()->index(source_row, 0, source_parent).data(CoreAccountModel::AccountIdRole).value<AccountId>();
395 }