40f0f5e537e1c474862f82e402dd7def41b51be6
[quassel.git] / src / qtui / settingspages / coreaccountsettingspage.cpp
1 /***************************************************************************
2  *   Copyright (C) 2009 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  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
19  ***************************************************************************/
20
21 #include "coreaccountsettingspage.h"
22
23 #include "client.h"
24 #include "clientsettings.h"
25 #include "coreaccountmodel.h"
26 #include "iconloader.h"
27
28 CoreAccountSettingsPage::CoreAccountSettingsPage(QWidget *parent)
29 : SettingsPage(tr("Misc"), tr("Core Accounts"), parent),
30 _lastAccountId(0),
31 _lastAutoConnectId(0),
32 _standalone(false)
33 {
34   ui.setupUi(this);
35   initAutoWidgets();
36   ui.addAccountButton->setIcon(SmallIcon("list-add"));
37   ui.editAccountButton->setIcon(SmallIcon("document-edit"));
38   ui.deleteAccountButton->setIcon(SmallIcon("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(), SIGNAL(rowsAboutToBeRemoved(QModelIndex, int, int)), SLOT(rowsAboutToBeRemoved(QModelIndex, int, int)));
47   connect(filteredModel(), SIGNAL(rowsInserted(QModelIndex, int, int)), SLOT(rowsInserted(QModelIndex, int, int)));
48
49   connect(ui.accountView->selectionModel(), SIGNAL(selectionChanged(QItemSelection, QItemSelection)), SLOT(setWidgetStates()));
50   setWidgetStates();
51 }
52
53 void CoreAccountSettingsPage::setStandAlone(bool standalone) {
54   _standalone = standalone;
55 }
56
57 void CoreAccountSettingsPage::load() {
58   model()->update(Client::coreAccountModel());
59   SettingsPage::load();
60
61   CoreAccountSettings s;
62
63   if(Quassel::runMode() != Quassel::Monolithic) {
64     // make sure we don't have selected the internal account as autoconnect account
65
66     if(s.autoConnectOnStartup() && s.autoConnectToFixedAccount()) {
67       CoreAccount acc = model()->account(s.autoConnectAccount());
68       if(acc.isInternal())
69         ui.autoConnectOnStartup->setChecked(false);
70     }
71   }
72   ui.accountView->setCurrentIndex(filteredModel()->index(0, 0));
73   ui.accountView->selectionModel()->select(filteredModel()->index(0, 0), QItemSelectionModel::Select);
74
75   QModelIndex idx = filteredModel()->mapFromSource(model()->accountIndex(s.autoConnectAccount()));
76   ui.autoConnectAccount->setCurrentIndex(idx.isValid() ? idx.row() : 0);
77   setWidgetStates();
78 }
79
80 void CoreAccountSettingsPage::save() {
81   SettingsPage::save();
82   Client::coreAccountModel()->update(model());
83   Client::coreAccountModel()->save();
84   CoreAccountSettings s;
85 }
86
87 QVariant CoreAccountSettingsPage::loadAutoWidgetValue(const QString &widgetName) {
88   if(widgetName == "autoConnectAccount") {
89     CoreAccountSettings s;
90     AccountId id = s.autoConnectAccount();
91     if(!id.isValid())
92       return QVariant();
93     return id.toInt();
94   }
95   return SettingsPage::loadAutoWidgetValue(widgetName);
96 }
97
98 void CoreAccountSettingsPage::saveAutoWidgetValue(const QString &widgetName, const QVariant &v) {
99   CoreAccountSettings s;
100   if(widgetName == "autoConnectAccount") {
101     AccountId id = filteredModel()->index(ui.autoConnectAccount->currentIndex(), 0).data(CoreAccountModel::AccountIdRole).value<AccountId>();
102     s.setAutoConnectAccount(id);
103     return;
104   }
105   SettingsPage::saveAutoWidgetValue(widgetName, v);
106 }
107
108 // TODO: Qt 4.6 - replace by proper rowsMoved() semantics
109 // NOTE: This is the filtered model
110 void CoreAccountSettingsPage::rowsAboutToBeRemoved(const QModelIndex &index, int start, int end) {
111   _lastAutoConnectId = _lastAccountId = 0;
112   if(index.isValid() || start != end)
113     return;
114
115   // the current index is removed, so remember it in case it's reinserted immediately afterwards
116   AccountId id = filteredModel()->index(start, 0).data(CoreAccountModel::AccountIdRole).value<AccountId>();
117   if(start == ui.accountView->currentIndex().row())
118     _lastAccountId = id;
119   if(start == ui.autoConnectAccount->currentIndex())
120     _lastAutoConnectId = id;
121 }
122
123 void CoreAccountSettingsPage::rowsInserted(const QModelIndex &index, int start, int end) {
124   if(index.isValid() || start != end)
125     return;
126
127   // check if the inserted index was just removed and select it in that case
128   AccountId id = filteredModel()->index(start, 0).data(CoreAccountModel::AccountIdRole).value<AccountId>();
129   if(id == _lastAccountId)
130     ui.accountView->setCurrentIndex(filteredModel()->index(start, 0));
131   if(id == _lastAutoConnectId)
132     ui.autoConnectAccount->setCurrentIndex(start);
133   _lastAccountId = _lastAutoConnectId = 0;
134 }
135
136 AccountId CoreAccountSettingsPage::selectedAccount() const {
137   QModelIndex index = ui.accountView->currentIndex();
138   if(!index.isValid())
139     return 0;
140   return index.data(CoreAccountModel::AccountIdRole).value<AccountId>();
141 }
142
143 void CoreAccountSettingsPage::setSelectedAccount(AccountId accId) {
144   QModelIndex index = filteredModel()->mapFromSource(model()->accountIndex(accId));
145   if(index.isValid())
146     ui.accountView->setCurrentIndex(index);
147 }
148
149 void CoreAccountSettingsPage::on_addAccountButton_clicked() {
150   CoreAccountEditDlg dlg(CoreAccount(), this);
151   if(dlg.exec() == QDialog::Accepted) {
152     AccountId id =model()->createOrUpdateAccount(dlg.account());
153     ui.accountView->setCurrentIndex(filteredModel()->mapFromSource(model()->accountIndex(id)));
154     widgetHasChanged();
155   }
156 }
157
158 void CoreAccountSettingsPage::on_editAccountButton_clicked() {
159   QModelIndex idx = ui.accountView->selectionModel()->currentIndex();
160   if(!idx.isValid())
161     return;
162
163   editAccount(idx);
164 }
165
166 void CoreAccountSettingsPage::editAccount(const QModelIndex &index) {
167   if(!index.isValid())
168     return;
169
170   CoreAccountEditDlg dlg(model()->account(filteredModel()->mapToSource(index)), this);
171   if(dlg.exec() == QDialog::Accepted) {
172     AccountId id = model()->createOrUpdateAccount(dlg.account());
173     ui.accountView->setCurrentIndex(filteredModel()->mapFromSource(model()->accountIndex(id)));
174     widgetHasChanged();
175   }
176 }
177
178 void CoreAccountSettingsPage::on_deleteAccountButton_clicked() {
179   if(!ui.accountView->selectionModel()->selectedIndexes().count())
180     return;
181
182   AccountId id = ui.accountView->selectionModel()->selectedIndexes().at(0).data(CoreAccountModel::AccountIdRole).value<AccountId>();
183   if(id.isValid()) {
184     model()->removeAccount(id);
185     widgetHasChanged();
186   }
187 }
188
189 void CoreAccountSettingsPage::on_accountView_doubleClicked(const QModelIndex &index) {
190   if(!index.isValid())
191     return;
192
193   if(isStandAlone())
194     emit connectToCore(index.data(CoreAccountModel::AccountIdRole).value<AccountId>());
195   else
196     editAccount(index);
197 }
198
199 void CoreAccountSettingsPage::setWidgetStates() {
200   AccountId accId = selectedAccount();
201   bool editable = accId.isValid() && accId != model()->internalAccount();
202
203   ui.editAccountButton->setEnabled(editable);
204   ui.deleteAccountButton->setEnabled(editable);
205 }
206
207 void CoreAccountSettingsPage::widgetHasChanged() {
208   setChangedState(testHasChanged());
209   setWidgetStates();
210 }
211
212 bool CoreAccountSettingsPage::testHasChanged() {
213   if(!(*model() == *Client::coreAccountModel()))
214     return true;
215
216   return false;
217 }
218
219 /*****************************************************************************************
220  * CoreAccountEditDlg
221  *****************************************************************************************/
222 CoreAccountEditDlg::CoreAccountEditDlg(const CoreAccount &acct, QWidget *parent)
223   : QDialog(parent)
224 {
225   ui.setupUi(this);
226
227   _account = acct;
228
229   ui.hostName->setText(acct.hostName());
230   ui.port->setValue(acct.port());
231   ui.accountName->setText(acct.accountName());
232   ui.user->setText(acct.user());
233   ui.password->setText(acct.password());
234   ui.rememberPassword->setChecked(acct.storePassword());
235   ui.useProxy->setChecked(acct.useProxy());
236   ui.proxyHostName->setText(acct.proxyHostName());
237   ui.proxyPort->setValue(acct.proxyPort());
238   ui.proxyType->setCurrentIndex(acct.proxyType() == QNetworkProxy::Socks5Proxy ? 0 : 1);
239   ui.proxyUser->setText(acct.proxyUser());
240   ui.proxyPassword->setText(acct.proxyPassword());
241
242   if(acct.accountId().isValid())
243     setWindowTitle(tr("Edit Core Account"));
244   else
245     setWindowTitle(tr("Add Core Account"));
246 }
247
248 CoreAccount CoreAccountEditDlg::account() {
249   _account.setAccountName(ui.accountName->text().trimmed());
250   _account.setHostName(ui.hostName->text().trimmed());
251   _account.setPort(ui.port->value());
252   _account.setUser(ui.user->text().trimmed());
253   _account.setPassword(ui.password->text());
254   _account.setStorePassword(ui.rememberPassword->isChecked());
255   _account.setUseProxy(ui.useProxy->isChecked());
256   _account.setProxyHostName(ui.proxyHostName->text().trimmed());
257   _account.setProxyPort(ui.proxyPort->value());
258   _account.setProxyType(ui.proxyType->currentIndex() == 0 ? QNetworkProxy::Socks5Proxy : QNetworkProxy::HttpProxy);
259   _account.setProxyUser(ui.proxyUser->text().trimmed());
260   _account.setProxyPassword(ui.proxyPassword->text());
261   return _account;
262 }
263
264 void CoreAccountEditDlg::setWidgetStates() {
265   bool ok = !ui.accountName->text().trimmed().isEmpty()
266             && !ui.user->text().trimmed().isEmpty()
267             && !ui.hostName->text().isEmpty();
268   ui.buttonBox->button(QDialogButtonBox::Ok)->setEnabled(ok);
269 }
270
271 void CoreAccountEditDlg::on_hostName_textChanged(const QString &text) {
272   Q_UNUSED(text);
273   setWidgetStates();
274 }
275
276 void CoreAccountEditDlg::on_accountName_textChanged(const QString &text) {
277   Q_UNUSED(text);
278   setWidgetStates();
279 }
280
281 void CoreAccountEditDlg::on_user_textChanged(const QString &text) {
282   Q_UNUSED(text)
283   setWidgetStates();
284 }
285
286 /*****************************************************************************************
287  * FilteredCoreAccountModel
288  *****************************************************************************************/
289
290 FilteredCoreAccountModel::FilteredCoreAccountModel(CoreAccountModel *model, QObject *parent) : QSortFilterProxyModel(parent) {
291   _internalAccount = model->internalAccount();
292   setSourceModel(model);
293 }
294
295 bool FilteredCoreAccountModel::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const {
296   if(Quassel::runMode() == Quassel::Monolithic)
297     return true;
298
299   if(!_internalAccount.isValid())
300     return true;
301
302   return _internalAccount != sourceModel()->index(source_row, 0, source_parent).data(CoreAccountModel::AccountIdRole).value<AccountId>();
303 }