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