1 | /*************************************************************************** |
2 | * Copyright (C) 2005-2014 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 <QHeaderView> |
22 | #include <QMessageBox> |
23 | #include <QTextCodec> |
24 | |
25 | #include "networkssettingspage.h" |
26 | |
27 | #include "client.h" |
28 | #include "iconloader.h" |
29 | #include "identity.h" |
30 | #include "network.h" |
31 | #include "presetnetworks.h" |
32 | #include "settingspagedlg.h" |
33 | #include "util.h" |
34 | |
35 | #include "settingspages/identitiessettingspage.h" |
36 | |
37 | NetworksSettingsPage::NetworksSettingsPage(QWidget *parent) |
38 | : SettingsPage(tr("IRC" ), tr("Networks" ), parent) |
39 | #ifdef HAVE_SSL |
40 | , _cid(0) |
41 | #endif |
42 | { |
43 | ui.setupUi(this); |
44 | |
45 | // hide SASL options for older cores |
46 | if (!(Client::coreFeatures() & Quassel::SaslAuthentication)) |
47 | ui.sasl->hide(); |
48 | if (!(Client::coreFeatures() & Quassel::SaslExternal)) |
49 | ui.saslExtInfo->hide(); |
50 | #ifndef HAVE_SSL |
51 | ui.saslExtInfo->hide(); |
52 | #endif |
53 | |
54 | // set up icons |
55 | ui.renameNetwork->setIcon(SmallIcon("edit-rename" )); |
56 | ui.addNetwork->setIcon(SmallIcon("list-add" )); |
57 | ui.deleteNetwork->setIcon(SmallIcon("edit-delete" )); |
58 | ui.addServer->setIcon(SmallIcon("list-add" )); |
59 | ui.deleteServer->setIcon(SmallIcon("edit-delete" )); |
60 | ui.editServer->setIcon(SmallIcon("configure" )); |
61 | ui.upServer->setIcon(SmallIcon("go-up" )); |
62 | ui.downServer->setIcon(SmallIcon("go-down" )); |
63 | ui.editIdentities->setIcon(SmallIcon("configure" )); |
64 | |
65 | _ignoreWidgetChanges = false; |
66 | |
67 | connectedIcon = SmallIcon("network-connect" ); |
68 | connectingIcon = SmallIcon("network-wired" ); // FIXME network-connecting |
69 | disconnectedIcon = SmallIcon("network-disconnect" ); |
70 | |
71 | foreach(int mib, QTextCodec::availableMibs()) { |
72 | QByteArray codec = QTextCodec::codecForMib(mib)->name(); |
73 | ui.sendEncoding->addItem(codec); |
74 | ui.recvEncoding->addItem(codec); |
75 | ui.serverEncoding->addItem(codec); |
76 | } |
77 | ui.sendEncoding->model()->sort(0); |
78 | ui.recvEncoding->model()->sort(0); |
79 | ui.serverEncoding->model()->sort(0); |
80 | currentId = 0; |
81 | setEnabled(Client::isConnected()); // need a core connection! |
82 | setWidgetStates(); |
83 | connect(Client::instance(), SIGNAL(coreConnectionStateChanged(bool)), this, SLOT(coreConnectionStateChanged(bool))); |
84 | connect(Client::instance(), SIGNAL(networkCreated(NetworkId)), this, SLOT(clientNetworkAdded(NetworkId))); |
85 | connect(Client::instance(), SIGNAL(networkRemoved(NetworkId)), this, SLOT(clientNetworkRemoved(NetworkId))); |
86 | connect(Client::instance(), SIGNAL(identityCreated(IdentityId)), this, SLOT(clientIdentityAdded(IdentityId))); |
87 | connect(Client::instance(), SIGNAL(identityRemoved(IdentityId)), this, SLOT(clientIdentityRemoved(IdentityId))); |
88 | |
89 | connect(ui.identityList, SIGNAL(currentIndexChanged(int)), this, SLOT(widgetHasChanged())); |
90 | //connect(ui.randomServer, SIGNAL(clicked(bool)), this, SLOT(widgetHasChanged())); |
91 | connect(ui.performEdit, SIGNAL(textChanged()), this, SLOT(widgetHasChanged())); |
92 | connect(ui.autoIdentify, SIGNAL(clicked(bool)), this, SLOT(widgetHasChanged())); |
93 | connect(ui.autoIdentifyService, SIGNAL(textEdited(const QString &)), this, SLOT(widgetHasChanged())); |
94 | connect(ui.autoIdentifyPassword, SIGNAL(textEdited(const QString &)), this, SLOT(widgetHasChanged())); |
95 | connect(ui.sasl, SIGNAL(clicked(bool)), this, SLOT(widgetHasChanged())); |
96 | connect(ui.saslAccount, SIGNAL(textEdited(QString)), this, SLOT(widgetHasChanged())); |
97 | connect(ui.saslPassword, SIGNAL(textEdited(QString)), this, SLOT(widgetHasChanged())); |
98 | connect(ui.useCustomEncodings, SIGNAL(clicked(bool)), this, SLOT(widgetHasChanged())); |
99 | connect(ui.sendEncoding, SIGNAL(currentIndexChanged(int)), this, SLOT(widgetHasChanged())); |
100 | connect(ui.recvEncoding, SIGNAL(currentIndexChanged(int)), this, SLOT(widgetHasChanged())); |
101 | connect(ui.serverEncoding, SIGNAL(currentIndexChanged(int)), this, SLOT(widgetHasChanged())); |
102 | connect(ui.autoReconnect, SIGNAL(clicked(bool)), this, SLOT(widgetHasChanged())); |
103 | connect(ui.reconnectInterval, SIGNAL(valueChanged(int)), this, SLOT(widgetHasChanged())); |
104 | connect(ui.reconnectRetries, SIGNAL(valueChanged(int)), this, SLOT(widgetHasChanged())); |
105 | connect(ui.unlimitedRetries, SIGNAL(clicked(bool)), this, SLOT(widgetHasChanged())); |
106 | connect(ui.rejoinOnReconnect, SIGNAL(clicked(bool)), this, SLOT(widgetHasChanged())); |
107 | //connect(ui., SIGNAL(), this, SLOT(widgetHasChanged())); |
108 | //connect(ui., SIGNAL(), this, SLOT(widgetHasChanged())); |
109 | |
110 | foreach(IdentityId id, Client::identityIds()) { |
111 | clientIdentityAdded(id); |
112 | } |
113 | } |
114 | |
115 | |
116 | void NetworksSettingsPage::save() |
117 | { |
118 | setEnabled(false); |
119 | if (currentId != 0) saveToNetworkInfo(networkInfos[currentId]); |
120 | |
121 | QList<NetworkInfo> toCreate, toUpdate; |
122 | QList<NetworkId> toRemove; |
123 | QHash<NetworkId, NetworkInfo>::iterator i = networkInfos.begin(); |
124 | while (i != networkInfos.end()) { |
125 | NetworkId id = (*i).networkId; |
126 | if (id < 0) { |
127 | toCreate.append(*i); |
128 | //if(id == currentId) currentId = 0; |
129 | //QList<QListWidgetItem *> items = ui.networkList->findItems((*i).networkName, Qt::MatchExactly); |
130 | //if(items.count()) { |
131 | // Q_ASSERT(items[0]->data(Qt::UserRole).value<NetworkId>() == id); |
132 | // delete items[0]; |
133 | //} |
134 | //i = networkInfos.erase(i); |
135 | ++i; |
136 | } |
137 | else { |
138 | if ((*i) != Client::network((*i).networkId)->networkInfo()) { |
139 | toUpdate.append(*i); |
140 | } |
141 | ++i; |
142 | } |
143 | } |
144 | foreach(NetworkId id, Client::networkIds()) { |
145 | if (!networkInfos.contains(id)) toRemove.append(id); |
146 | } |
147 | SaveNetworksDlg dlg(toCreate, toUpdate, toRemove, this); |
148 | int ret = dlg.exec(); |
149 | if (ret == QDialog::Rejected) { |
150 | // canceled -> reload everything to be safe |
151 | load(); |
152 | } |
153 | setChangedState(false); |
154 | setEnabled(true); |
155 | } |
156 | |
157 | |
158 | void NetworksSettingsPage::load() |
159 | { |
160 | reset(); |
161 | foreach(NetworkId netid, Client::networkIds()) { |
162 | clientNetworkAdded(netid); |
163 | } |
164 | ui.networkList->setCurrentRow(0); |
165 | setChangedState(false); |
166 | } |
167 | |
168 | |
169 | void NetworksSettingsPage::reset() |
170 | { |
171 | currentId = 0; |
172 | ui.networkList->clear(); |
173 | networkInfos.clear(); |
174 | } |
175 | |
176 | |
177 | bool NetworksSettingsPage::aboutToSave() |
178 | { |
179 | if (currentId != 0) saveToNetworkInfo(networkInfos[currentId]); |
180 | QList<int> errors; |
181 | foreach(NetworkInfo info, networkInfos.values()) { |
182 | if (!info.serverList.count()) errors.append(1); |
183 | } |
184 | if (!errors.count()) return true; |
185 | QString error(tr("<b>The following problems need to be corrected before your changes can be applied:</b><ul>" )); |
186 | if (errors.contains(1)) error += tr("<li>All networks need at least one server defined</li>" ); |
187 | error += tr("</ul>" ); |
188 | QMessageBox::warning(this, tr("Invalid Network Settings" ), error); |
189 | return false; |
190 | } |
191 | |
192 | |
193 | void NetworksSettingsPage::widgetHasChanged() |
194 | { |
195 | if (_ignoreWidgetChanges) return; |
196 | bool changed = testHasChanged(); |
197 | if (changed != hasChanged()) setChangedState(changed); |
198 | } |
199 | |
200 | |
201 | bool NetworksSettingsPage::testHasChanged() |
202 | { |
203 | if (currentId != 0) { |
204 | saveToNetworkInfo(networkInfos[currentId]); |
205 | } |
206 | if (Client::networkIds().count() != networkInfos.count()) return true; |
207 | foreach(NetworkId id, networkInfos.keys()) { |
208 | if (id < 0) return true; |
209 | if (Client::network(id)->networkInfo() != networkInfos[id]) return true; |
210 | } |
211 | return false; |
212 | } |
213 | |
214 | |
215 | void NetworksSettingsPage::setWidgetStates() |
216 | { |
217 | // network list |
218 | if (ui.networkList->selectedItems().count()) { |
219 | ui.detailsBox->setEnabled(true); |
220 | ui.renameNetwork->setEnabled(true); |
221 | ui.deleteNetwork->setEnabled(true); |
222 | |
223 | /* button disabled for now |
224 | NetworkId id = ui.networkList->selectedItems()[0]->data(Qt::UserRole).value<NetworkId>(); |
225 | const Network *net = id > 0 ? Client::network(id) : 0; |
226 | ui.connectNow->setEnabled(net); |
227 | // && (Client::network(id)->connectionState() == Network::Initialized |
228 | // || Client::network(id)->connectionState() == Network::Disconnected)); |
229 | if(net) { |
230 | if(net->connectionState() == Network::Disconnected) { |
231 | ui.connectNow->setIcon(connectedIcon); |
232 | ui.connectNow->setText(tr("Connect")); |
233 | } else { |
234 | ui.connectNow->setIcon(disconnectedIcon); |
235 | ui.connectNow->setText(tr("Disconnect")); |
236 | } |
237 | } else { |
238 | ui.connectNow->setIcon(QIcon()); |
239 | ui.connectNow->setText(tr("Apply first!")); |
240 | } */ |
241 | } |
242 | else { |
243 | ui.renameNetwork->setEnabled(false); |
244 | ui.deleteNetwork->setEnabled(false); |
245 | //ui.connectNow->setEnabled(false); |
246 | ui.detailsBox->setEnabled(false); |
247 | } |
248 | // network details |
249 | if (ui.serverList->selectedItems().count()) { |
250 | ui.editServer->setEnabled(true); |
251 | ui.deleteServer->setEnabled(true); |
252 | ui.upServer->setEnabled(ui.serverList->currentRow() > 0); |
253 | ui.downServer->setEnabled(ui.serverList->currentRow() < ui.serverList->count() - 1); |
254 | } |
255 | else { |
256 | ui.editServer->setEnabled(false); |
257 | ui.deleteServer->setEnabled(false); |
258 | ui.upServer->setEnabled(false); |
259 | ui.downServer->setEnabled(false); |
260 | } |
261 | } |
262 | |
263 | |
264 | void NetworksSettingsPage::setItemState(NetworkId id, QListWidgetItem *item) |
265 | { |
266 | if (!item && !(item = networkItem(id))) return; |
267 | const Network *net = Client::network(id); |
268 | if (!net || net->isInitialized()) item->setFlags(item->flags() | Qt::ItemIsEnabled); |
269 | else item->setFlags(item->flags() & ~Qt::ItemIsEnabled); |
270 | if (net && net->connectionState() == Network::Initialized) { |
271 | item->setIcon(connectedIcon); |
272 | } |
273 | else if (net && net->connectionState() != Network::Disconnected) { |
274 | item->setIcon(connectingIcon); |
275 | } |
276 | else { |
277 | item->setIcon(disconnectedIcon); |
278 | } |
279 | if (net) { |
280 | bool select = false; |
281 | // check if we already have another net of this name in the list, and replace it |
282 | QList<QListWidgetItem *> items = ui.networkList->findItems(net->networkName(), Qt::MatchExactly); |
283 | if (items.count()) { |
284 | foreach(QListWidgetItem *i, items) { |
285 | NetworkId oldid = i->data(Qt::UserRole).value<NetworkId>(); |
286 | if (oldid > 0) continue; // only locally created nets should be replaced |
287 | if (oldid == currentId) { |
288 | select = true; |
289 | currentId = 0; |
290 | ui.networkList->clearSelection(); |
291 | } |
292 | int row = ui.networkList->row(i); |
293 | if (row >= 0) { |
294 | QListWidgetItem *olditem = ui.networkList->takeItem(row); |
295 | Q_ASSERT(olditem); |
296 | delete olditem; |
297 | } |
298 | networkInfos.remove(oldid); |
299 | break; |
300 | } |
301 | } |
302 | item->setText(net->networkName()); |
303 | if (select) item->setSelected(true); |
304 | } |
305 | } |
306 | |
307 | |
308 | void NetworksSettingsPage::coreConnectionStateChanged(bool state) |
309 | { |
310 | this->setEnabled(state); |
311 | if (state) { |
312 | load(); |
313 | } |
314 | else { |
315 | // reset |
316 | //currentId = 0; |
317 | } |
318 | } |
319 | |
320 | |
321 | void NetworksSettingsPage::clientIdentityAdded(IdentityId id) |
322 | { |
323 | const Identity *identity = Client::identity(id); |
324 | connect(identity, SIGNAL(updatedRemotely()), this, SLOT(clientIdentityUpdated())); |
325 | |
326 | QString name = identity->identityName(); |
327 | for (int j = 0; j < ui.identityList->count(); j++) { |
328 | if ((j > 0 || ui.identityList->itemData(0).toInt() != 1) && name.localeAwareCompare(ui.identityList->itemText(j)) < 0) { |
329 | ui.identityList->insertItem(j, name, id.toInt()); |
330 | widgetHasChanged(); |
331 | return; |
332 | } |
333 | } |
334 | // append |
335 | ui.identityList->insertItem(ui.identityList->count(), name, id.toInt()); |
336 | widgetHasChanged(); |
337 | } |
338 | |
339 | |
340 | void NetworksSettingsPage::clientIdentityUpdated() |
341 | { |
342 | const Identity *identity = qobject_cast<const Identity *>(sender()); |
343 | if (!identity) { |
344 | qWarning() << "NetworksSettingsPage: Invalid identity to update!" ; |
345 | return; |
346 | } |
347 | int row = ui.identityList->findData(identity->id().toInt()); |
348 | if (row < 0) { |
349 | qWarning() << "NetworksSettingsPage: Invalid identity to update!" ; |
350 | return; |
351 | } |
352 | if (ui.identityList->itemText(row) != identity->identityName()) { |
353 | ui.identityList->setItemText(row, identity->identityName()); |
354 | } |
355 | } |
356 | |
357 | |
358 | void NetworksSettingsPage::clientIdentityRemoved(IdentityId id) |
359 | { |
360 | IdentityId defaultId = defaultIdentity(); |
361 | if (currentId != 0) saveToNetworkInfo(networkInfos[currentId]); |
362 | foreach(NetworkInfo info, networkInfos.values()) { |
363 | if (info.identity == id) { |
364 | if (info.networkId == currentId) |
365 | ui.identityList->setCurrentIndex(0); |
366 | info.identity = defaultId; |
367 | networkInfos[info.networkId] = info; |
368 | if (info.networkId > 0) Client::updateNetwork(info); |
369 | } |
370 | } |
371 | ui.identityList->removeItem(ui.identityList->findData(id.toInt())); |
372 | widgetHasChanged(); |
373 | } |
374 | |
375 | |
376 | QListWidgetItem *NetworksSettingsPage::networkItem(NetworkId id) const |
377 | { |
378 | for (int i = 0; i < ui.networkList->count(); i++) { |
379 | QListWidgetItem *item = ui.networkList->item(i); |
380 | if (item->data(Qt::UserRole).value<NetworkId>() == id) return item; |
381 | } |
382 | return 0; |
383 | } |
384 | |
385 | |
386 | void NetworksSettingsPage::clientNetworkAdded(NetworkId id) |
387 | { |
388 | insertNetwork(id); |
389 | //connect(Client::network(id), SIGNAL(updatedRemotely()), this, SLOT(clientNetworkUpdated())); |
390 | connect(Client::network(id), SIGNAL(configChanged()), this, SLOT(clientNetworkUpdated())); |
391 | |
392 | connect(Client::network(id), SIGNAL(connectionStateSet(Network::ConnectionState)), this, SLOT(networkConnectionStateChanged(Network::ConnectionState))); |
393 | connect(Client::network(id), SIGNAL(connectionError(const QString &)), this, SLOT(networkConnectionError(const QString &))); |
394 | } |
395 | |
396 | |
397 | void NetworksSettingsPage::clientNetworkUpdated() |
398 | { |
399 | const Network *net = qobject_cast<const Network *>(sender()); |
400 | if (!net) { |
401 | qWarning() << "Update request for unknown network received!" ; |
402 | return; |
403 | } |
404 | networkInfos[net->networkId()] = net->networkInfo(); |
405 | setItemState(net->networkId()); |
406 | if (net->networkId() == currentId) displayNetwork(net->networkId()); |
407 | setWidgetStates(); |
408 | widgetHasChanged(); |
409 | } |
410 | |
411 | |
412 | void NetworksSettingsPage::clientNetworkRemoved(NetworkId id) |
413 | { |
414 | if (!networkInfos.contains(id)) return; |
415 | if (id == currentId) displayNetwork(0); |
416 | NetworkInfo info = networkInfos.take(id); |
417 | QList<QListWidgetItem *> items = ui.networkList->findItems(info.networkName, Qt::MatchExactly); |
418 | foreach(QListWidgetItem *item, items) { |
419 | if (item->data(Qt::UserRole).value<NetworkId>() == id) |
420 | delete ui.networkList->takeItem(ui.networkList->row(item)); |
421 | } |
422 | setWidgetStates(); |
423 | widgetHasChanged(); |
424 | } |
425 | |
426 | |
427 | void NetworksSettingsPage::networkConnectionStateChanged(Network::ConnectionState state) |
428 | { |
429 | Q_UNUSED(state); |
430 | const Network *net = qobject_cast<const Network *>(sender()); |
431 | if (!net) return; |
432 | /* |
433 | if(net->networkId() == currentId) { |
434 | ui.connectNow->setEnabled(state == Network::Initialized || state == Network::Disconnected); |
435 | } |
436 | */ |
437 | setItemState(net->networkId()); |
438 | setWidgetStates(); |
439 | } |
440 | |
441 | |
442 | void NetworksSettingsPage::networkConnectionError(const QString &) |
443 | { |
444 | } |
445 | |
446 | |
447 | QListWidgetItem *NetworksSettingsPage::insertNetwork(NetworkId id) |
448 | { |
449 | NetworkInfo info = Client::network(id)->networkInfo(); |
450 | networkInfos[id] = info; |
451 | return insertNetwork(info); |
452 | } |
453 | |
454 | |
455 | QListWidgetItem *NetworksSettingsPage::insertNetwork(const NetworkInfo &info) |
456 | { |
457 | QListWidgetItem *item = 0; |
458 | QList<QListWidgetItem *> items = ui.networkList->findItems(info.networkName, Qt::MatchExactly); |
459 | if (!items.count()) item = new QListWidgetItem(disconnectedIcon, info.networkName, ui.networkList); |
460 | else { |
461 | // we overwrite an existing net if it a) has the same name and b) has a negative ID meaning we created it locally before |
462 | // -> then we can be sure that this is the core-side replacement for the net we created |
463 | foreach(QListWidgetItem *i, items) { |
464 | NetworkId id = i->data(Qt::UserRole).value<NetworkId>(); |
465 | if (id < 0) { item = i; break; } |
466 | } |
467 | if (!item) item = new QListWidgetItem(disconnectedIcon, info.networkName, ui.networkList); |
468 | } |
469 | item->setData(Qt::UserRole, QVariant::fromValue<NetworkId>(info.networkId)); |
470 | setItemState(info.networkId, item); |
471 | widgetHasChanged(); |
472 | return item; |
473 | } |
474 | |
475 | |
476 | void NetworksSettingsPage::displayNetwork(NetworkId id) |
477 | { |
478 | _ignoreWidgetChanges = true; |
479 | if (id != 0) { |
480 | NetworkInfo info = networkInfos[id]; |
481 | |
482 | #ifdef HAVE_SSL |
483 | // this is only needed when the core supports SASL EXTERNAL |
484 | if (Client::coreFeatures() & Quassel::SaslExternal) { |
485 | if (_cid) { |
486 | disconnect(_cid, SIGNAL(sslSettingsUpdated()), this, SLOT(sslUpdated())); |
487 | delete _cid; |
488 | } |
489 | _cid = new CertIdentity(*Client::identity(info.identity), this); |
490 | _cid->enableEditSsl(true); |
491 | connect(_cid, SIGNAL(sslSettingsUpdated()), this, SLOT(sslUpdated())); |
492 | } |
493 | #endif |
494 | |
495 | ui.identityList->setCurrentIndex(ui.identityList->findData(info.identity.toInt())); |
496 | ui.serverList->clear(); |
497 | foreach(Network::Server server, info.serverList) { |
498 | QListWidgetItem *item = new QListWidgetItem(QString("%1:%2" ).arg(server.host).arg(server.port)); |
499 | if (server.useSsl) |
500 | item->setIcon(SmallIcon("document-encrypt" )); |
501 | ui.serverList->addItem(item); |
502 | } |
503 | //setItemState(id); |
504 | //ui.randomServer->setChecked(info.useRandomServer); |
505 | ui.performEdit->setPlainText(info.perform.join("\n" )); |
506 | ui.autoIdentify->setChecked(info.useAutoIdentify); |
507 | ui.autoIdentifyService->setText(info.autoIdentifyService); |
508 | ui.autoIdentifyPassword->setText(info.autoIdentifyPassword); |
509 | ui.sasl->setChecked(info.useSasl); |
510 | ui.saslAccount->setText(info.saslAccount); |
511 | ui.saslPassword->setText(info.saslPassword); |
512 | if (info.codecForEncoding.isEmpty()) { |
513 | ui.sendEncoding->setCurrentIndex(ui.sendEncoding->findText(Network::defaultCodecForEncoding())); |
514 | ui.recvEncoding->setCurrentIndex(ui.recvEncoding->findText(Network::defaultCodecForDecoding())); |
515 | ui.serverEncoding->setCurrentIndex(ui.serverEncoding->findText(Network::defaultCodecForServer())); |
516 | ui.useCustomEncodings->setChecked(false); |
517 | } |
518 | else { |
519 | ui.sendEncoding->setCurrentIndex(ui.sendEncoding->findText(info.codecForEncoding)); |
520 | ui.recvEncoding->setCurrentIndex(ui.recvEncoding->findText(info.codecForDecoding)); |
521 | ui.serverEncoding->setCurrentIndex(ui.serverEncoding->findText(info.codecForServer)); |
522 | ui.useCustomEncodings->setChecked(true); |
523 | } |
524 | ui.autoReconnect->setChecked(info.useAutoReconnect); |
525 | ui.reconnectInterval->setValue(info.autoReconnectInterval); |
526 | ui.reconnectRetries->setValue(info.autoReconnectRetries); |
527 | ui.unlimitedRetries->setChecked(info.unlimitedReconnectRetries); |
528 | ui.rejoinOnReconnect->setChecked(info.rejoinChannels); |
529 | } |
530 | else { |
531 | // just clear widgets |
532 | #ifdef HAVE_SSL |
533 | if (_cid) { |
534 | disconnect(_cid, SIGNAL(sslSettingsUpdated()), this, SLOT(sslUpdated())); |
535 | delete _cid; |
536 | } |
537 | #endif |
538 | ui.identityList->setCurrentIndex(-1); |
539 | ui.serverList->clear(); |
540 | ui.performEdit->clear(); |
541 | ui.autoIdentifyService->clear(); |
542 | ui.autoIdentifyPassword->clear(); |
543 | ui.saslAccount->clear(); |
544 | ui.saslPassword->clear(); |
545 | setWidgetStates(); |
546 | } |
547 | _ignoreWidgetChanges = false; |
548 | currentId = id; |
549 | } |
550 | |
551 | |
552 | void NetworksSettingsPage::saveToNetworkInfo(NetworkInfo &info) |
553 | { |
554 | info.identity = ui.identityList->itemData(ui.identityList->currentIndex()).toInt(); |
555 | //info.useRandomServer = ui.randomServer->isChecked(); |
556 | info.perform = ui.performEdit->toPlainText().split("\n" ); |
557 | info.useAutoIdentify = ui.autoIdentify->isChecked(); |
558 | info.autoIdentifyService = ui.autoIdentifyService->text(); |
559 | info.autoIdentifyPassword = ui.autoIdentifyPassword->text(); |
560 | info.useSasl = ui.sasl->isChecked(); |
561 | info.saslAccount = ui.saslAccount->text(); |
562 | info.saslPassword = ui.saslPassword->text(); |
563 | if (!ui.useCustomEncodings->isChecked()) { |
564 | info.codecForEncoding.clear(); |
565 | info.codecForDecoding.clear(); |
566 | info.codecForServer.clear(); |
567 | } |
568 | else { |
569 | info.codecForEncoding = ui.sendEncoding->currentText().toLatin1(); |
570 | info.codecForDecoding = ui.recvEncoding->currentText().toLatin1(); |
571 | info.codecForServer = ui.serverEncoding->currentText().toLatin1(); |
572 | } |
573 | info.useAutoReconnect = ui.autoReconnect->isChecked(); |
574 | info.autoReconnectInterval = ui.reconnectInterval->value(); |
575 | info.autoReconnectRetries = ui.reconnectRetries->value(); |
576 | info.unlimitedReconnectRetries = ui.unlimitedRetries->isChecked(); |
577 | info.rejoinChannels = ui.rejoinOnReconnect->isChecked(); |
578 | } |
579 | |
580 | |
581 | #ifdef HAVE_SSL |
582 | void NetworksSettingsPage::sslUpdated() |
583 | { |
584 | if (_cid && !_cid->sslKey().isNull()) { |
585 | ui.saslAccount->setDisabled(true); |
586 | ui.saslAccountLabel->setDisabled(true); |
587 | ui.saslPassword->setDisabled(true); |
588 | ui.saslPasswordLabel->setDisabled(true); |
589 | ui.saslExtInfo->setHidden(false); |
590 | } else { |
591 | ui.saslAccount->setDisabled(false); |
592 | ui.saslAccountLabel->setDisabled(false); |
593 | ui.saslPassword->setDisabled(false); |
594 | ui.saslPasswordLabel->setDisabled(false); |
595 | ui.saslExtInfo->setHidden(true); |
596 | } |
597 | } |
598 | #endif |
599 | |
600 | |
601 | /*** Network list ***/ |
602 | |
603 | void NetworksSettingsPage::on_networkList_itemSelectionChanged() |
604 | { |
605 | if (currentId != 0) { |
606 | saveToNetworkInfo(networkInfos[currentId]); |
607 | } |
608 | if (ui.networkList->selectedItems().count()) { |
609 | NetworkId id = ui.networkList->selectedItems()[0]->data(Qt::UserRole).value<NetworkId>(); |
610 | currentId = id; |
611 | displayNetwork(id); |
612 | ui.serverList->setCurrentRow(0); |
613 | } |
614 | else { |
615 | currentId = 0; |
616 | } |
617 | setWidgetStates(); |
618 | } |
619 | |
620 | |
621 | void NetworksSettingsPage::on_addNetwork_clicked() |
622 | { |
623 | QStringList existing; |
624 | for (int i = 0; i < ui.networkList->count(); i++) existing << ui.networkList->item(i)->text(); |
625 | NetworkAddDlg dlg(existing, this); |
626 | if (dlg.exec() == QDialog::Accepted) { |
627 | NetworkInfo info = dlg.networkInfo(); |
628 | if (info.networkName.isEmpty()) |
629 | return; // sanity check |
630 | |
631 | NetworkId id; |
632 | for (id = 1; id <= networkInfos.count(); id++) { |
633 | widgetHasChanged(); |
634 | if (!networkInfos.keys().contains(-id.toInt())) break; |
635 | } |
636 | id = -id.toInt(); |
637 | info.networkId = id; |
638 | info.identity = defaultIdentity(); |
639 | networkInfos[id] = info; |
640 | QListWidgetItem *item = insertNetwork(info); |
641 | ui.networkList->setCurrentItem(item); |
642 | setWidgetStates(); |
643 | } |
644 | } |
645 | |
646 | |
647 | void NetworksSettingsPage::on_deleteNetwork_clicked() |
648 | { |
649 | if (ui.networkList->selectedItems().count()) { |
650 | NetworkId netid = ui.networkList->selectedItems()[0]->data(Qt::UserRole).value<NetworkId>(); |
651 | int ret = QMessageBox::question(this, tr("Delete Network?" ), |
652 | tr("Do you really want to delete the network \"%1\" and all related settings, including the backlog?" ).arg(networkInfos[netid].networkName), |
653 | QMessageBox::Yes|QMessageBox::No, QMessageBox::No); |
654 | if (ret == QMessageBox::Yes) { |
655 | currentId = 0; |
656 | networkInfos.remove(netid); |
657 | delete ui.networkList->takeItem(ui.networkList->row(ui.networkList->selectedItems()[0])); |
658 | ui.networkList->setCurrentRow(qMin(ui.networkList->currentRow()+1, ui.networkList->count()-1)); |
659 | setWidgetStates(); |
660 | widgetHasChanged(); |
661 | } |
662 | } |
663 | } |
664 | |
665 | |
666 | void NetworksSettingsPage::on_renameNetwork_clicked() |
667 | { |
668 | if (!ui.networkList->selectedItems().count()) return; |
669 | QString old = ui.networkList->selectedItems()[0]->text(); |
670 | QStringList existing; |
671 | for (int i = 0; i < ui.networkList->count(); i++) existing << ui.networkList->item(i)->text(); |
672 | NetworkEditDlg dlg(old, existing, this); |
673 | if (dlg.exec() == QDialog::Accepted) { |
674 | ui.networkList->selectedItems()[0]->setText(dlg.networkName()); |
675 | NetworkId netid = ui.networkList->selectedItems()[0]->data(Qt::UserRole).value<NetworkId>(); |
676 | networkInfos[netid].networkName = dlg.networkName(); |
677 | widgetHasChanged(); |
678 | } |
679 | } |
680 | |
681 | |
682 | /* |
683 | void NetworksSettingsPage::on_connectNow_clicked() { |
684 | if(!ui.networkList->selectedItems().count()) return; |
685 | NetworkId id = ui.networkList->selectedItems()[0]->data(Qt::UserRole).value<NetworkId>(); |
686 | const Network *net = Client::network(id); |
687 | if(!net) return; |
688 | if(net->connectionState() == Network::Disconnected) net->requestConnect(); |
689 | else net->requestDisconnect(); |
690 | } |
691 | */ |
692 | |
693 | /*** Server list ***/ |
694 | |
695 | void NetworksSettingsPage::on_serverList_itemSelectionChanged() |
696 | { |
697 | setWidgetStates(); |
698 | } |
699 | |
700 | |
701 | void NetworksSettingsPage::on_addServer_clicked() |
702 | { |
703 | if (currentId == 0) return; |
704 | ServerEditDlg dlg(Network::Server(), this); |
705 | if (dlg.exec() == QDialog::Accepted) { |
706 | networkInfos[currentId].serverList.append(dlg.serverData()); |
707 | displayNetwork(currentId); |
708 | ui.serverList->setCurrentRow(ui.serverList->count()-1); |
709 | widgetHasChanged(); |
710 | } |
711 | } |
712 | |
713 | |
714 | void NetworksSettingsPage::on_editServer_clicked() |
715 | { |
716 | if (currentId == 0) return; |
717 | int cur = ui.serverList->currentRow(); |
718 | ServerEditDlg dlg(networkInfos[currentId].serverList[cur], this); |
719 | if (dlg.exec() == QDialog::Accepted) { |
720 | networkInfos[currentId].serverList[cur] = dlg.serverData(); |
721 | displayNetwork(currentId); |
722 | ui.serverList->setCurrentRow(cur); |
723 | widgetHasChanged(); |
724 | } |
725 | } |
726 | |
727 | |
728 | void NetworksSettingsPage::on_deleteServer_clicked() |
729 | { |
730 | if (currentId == 0) return; |
731 | int cur = ui.serverList->currentRow(); |
732 | networkInfos[currentId].serverList.removeAt(cur); |
733 | displayNetwork(currentId); |
734 | ui.serverList->setCurrentRow(qMin(cur, ui.serverList->count()-1)); |
735 | widgetHasChanged(); |
736 | } |
737 | |
738 | |
739 | void NetworksSettingsPage::on_upServer_clicked() |
740 | { |
741 | int cur = ui.serverList->currentRow(); |
742 | Network::Server server = networkInfos[currentId].serverList.takeAt(cur); |
743 | networkInfos[currentId].serverList.insert(cur-1, server); |
744 | displayNetwork(currentId); |
745 | ui.serverList->setCurrentRow(cur-1); |
746 | widgetHasChanged(); |
747 | } |
748 | |
749 | |
750 | void NetworksSettingsPage::on_downServer_clicked() |
751 | { |
752 | int cur = ui.serverList->currentRow(); |
753 | Network::Server server = networkInfos[currentId].serverList.takeAt(cur); |
754 | networkInfos[currentId].serverList.insert(cur+1, server); |
755 | displayNetwork(currentId); |
756 | ui.serverList->setCurrentRow(cur+1); |
757 | widgetHasChanged(); |
758 | } |
759 | |
760 | |
761 | void NetworksSettingsPage::on_editIdentities_clicked() |
762 | { |
763 | SettingsPageDlg dlg(new IdentitiesSettingsPage(this), this); |
764 | dlg.exec(); |
765 | } |
766 | |
767 | |
768 | IdentityId NetworksSettingsPage::defaultIdentity() const |
769 | { |
770 | IdentityId defaultId = 0; |
771 | QList<IdentityId> ids = Client::identityIds(); |
772 | foreach(IdentityId id, ids) { |
773 | if (defaultId == 0 || id < defaultId) |
774 | defaultId = id; |
775 | } |
776 | return defaultId; |
777 | } |
778 | |
779 | |
780 | /************************************************************************** |
781 | * NetworkAddDlg |
782 | *************************************************************************/ |
783 | |
784 | NetworkAddDlg::NetworkAddDlg(const QStringList &exist, QWidget *parent) : QDialog(parent), existing(exist) |
785 | { |
786 | ui.setupUi(this); |
787 | ui.useSSL->setIcon(SmallIcon("document-encrypt" )); |
788 | |
789 | // read preset networks |
790 | QStringList networks = PresetNetworks::names(); |
791 | foreach(QString s, existing) |
792 | networks.removeAll(s); |
793 | if (networks.count()) |
794 | ui.presetList->addItems(networks); |
795 | else { |
796 | ui.useManual->setChecked(true); |
797 | ui.usePreset->setEnabled(false); |
798 | } |
799 | connect(ui.networkName, SIGNAL(textChanged(const QString &)), SLOT(setButtonStates())); |
800 | connect(ui.serverAddress, SIGNAL(textChanged(const QString &)), SLOT(setButtonStates())); |
801 | setButtonStates(); |
802 | } |
803 | |
804 | |
805 | NetworkInfo NetworkAddDlg::networkInfo() const |
806 | { |
807 | if (ui.useManual->isChecked()) { |
808 | NetworkInfo info; |
809 | info.networkName = ui.networkName->text().trimmed(); |
810 | info.serverList << Network::Server(ui.serverAddress->text().trimmed(), ui.port->value(), ui.serverPassword->text(), ui.useSSL->isChecked()); |
811 | return info; |
812 | } |
813 | else |
814 | return PresetNetworks::networkInfo(ui.presetList->currentText()); |
815 | } |
816 | |
817 | |
818 | void NetworkAddDlg::setButtonStates() |
819 | { |
820 | bool ok = false; |
821 | if (ui.usePreset->isChecked() && ui.presetList->count()) |
822 | ok = true; |
823 | else if (ui.useManual->isChecked()) { |
824 | ok = !ui.networkName->text().trimmed().isEmpty() && !existing.contains(ui.networkName->text().trimmed()) |
825 | && !ui.serverAddress->text().isEmpty(); |
826 | } |
827 | ui.buttonBox->button(QDialogButtonBox::Ok)->setEnabled(ok); |
828 | } |
829 | |
830 | |
831 | /************************************************************************** |
832 | * NetworkEditDlg |
833 | *************************************************************************/ |
834 | |
835 | NetworkEditDlg::NetworkEditDlg(const QString &old, const QStringList &exist, QWidget *parent) : QDialog(parent), existing(exist) |
836 | { |
837 | ui.setupUi(this); |
838 | |
839 | if (old.isEmpty()) { |
840 | // new network |
841 | setWindowTitle(tr("Add Network" )); |
842 | on_networkEdit_textChanged("" ); // disable ok button |
843 | } |
844 | else ui.networkEdit->setText(old); |
845 | } |
846 | |
847 | |
848 | QString NetworkEditDlg::networkName() const |
849 | { |
850 | return ui.networkEdit->text().trimmed(); |
851 | } |
852 | |
853 | |
854 | void NetworkEditDlg::on_networkEdit_textChanged(const QString &text) |
855 | { |
856 | ui.buttonBox->button(QDialogButtonBox::Ok)->setDisabled(text.isEmpty() || existing.contains(text.trimmed())); |
857 | } |
858 | |
859 | |
860 | /************************************************************************** |
861 | * ServerEditDlg |
862 | *************************************************************************/ |
863 | ServerEditDlg::ServerEditDlg(const Network::Server &server, QWidget *parent) : QDialog(parent) |
864 | { |
865 | ui.setupUi(this); |
866 | ui.useSSL->setIcon(SmallIcon("document-encrypt" )); |
867 | ui.host->setText(server.host); |
868 | ui.port->setValue(server.port); |
869 | ui.password->setText(server.password); |
870 | ui.useSSL->setChecked(server.useSsl); |
871 | ui.useProxy->setChecked(server.useProxy); |
872 | ui.proxyType->setCurrentIndex(server.proxyType == QNetworkProxy::Socks5Proxy ? 0 : 1); |
873 | ui.proxyHost->setText(server.proxyHost); |
874 | ui.proxyPort->setValue(server.proxyPort); |
875 | ui.proxyUsername->setText(server.proxyUser); |
876 | ui.proxyPassword->setText(server.proxyPass); |
877 | on_host_textChanged(); |
878 | } |
879 | |
880 | |
881 | Network::Server ServerEditDlg::serverData() const |
882 | { |
883 | Network::Server server(ui.host->text().trimmed(), ui.port->value(), ui.password->text(), ui.useSSL->isChecked()); |
884 | server.useProxy = ui.useProxy->isChecked(); |
885 | server.proxyType = ui.proxyType->currentIndex() == 0 ? QNetworkProxy::Socks5Proxy : QNetworkProxy::HttpProxy; |
886 | server.proxyHost = ui.proxyHost->text(); |
887 | server.proxyPort = ui.proxyPort->value(); |
888 | server.proxyUser = ui.proxyUsername->text(); |
889 | server.proxyPass = ui.proxyPassword->text(); |
890 | return server; |
891 | } |
892 | |
893 | |
894 | void ServerEditDlg::on_host_textChanged() |
895 | { |
896 | ui.buttonBox->button(QDialogButtonBox::Ok)->setDisabled(ui.host->text().trimmed().isEmpty()); |
897 | } |
898 | |
899 | |
900 | /************************************************************************** |
901 | * SaveNetworksDlg |
902 | *************************************************************************/ |
903 | |
904 | SaveNetworksDlg::SaveNetworksDlg(const QList<NetworkInfo> &toCreate, const QList<NetworkInfo> &toUpdate, const QList<NetworkId> &toRemove, QWidget *parent) : QDialog(parent) |
905 | { |
906 | ui.setupUi(this); |
907 | |
908 | numevents = toCreate.count() + toUpdate.count() + toRemove.count(); |
909 | rcvevents = 0; |
910 | if (numevents) { |
911 | ui.progressBar->setMaximum(numevents); |
912 | ui.progressBar->setValue(0); |
913 | |
914 | connect(Client::instance(), SIGNAL(networkCreated(NetworkId)), this, SLOT(clientEvent())); |
915 | connect(Client::instance(), SIGNAL(networkRemoved(NetworkId)), this, SLOT(clientEvent())); |
916 | |
917 | foreach(NetworkId id, toRemove) { |
918 | Client::removeNetwork(id); |
919 | } |
920 | foreach(NetworkInfo info, toCreate) { |
921 | Client::createNetwork(info); |
922 | } |
923 | foreach(NetworkInfo info, toUpdate) { |
924 | const Network *net = Client::network(info.networkId); |
925 | if (!net) { |
926 | qWarning() << "Invalid client network!" ; |
927 | numevents--; |
928 | continue; |
929 | } |
930 | // FIXME this only checks for one changed item rather than all! |
931 | connect(net, SIGNAL(updatedRemotely()), this, SLOT(clientEvent())); |
932 | Client::updateNetwork(info); |
933 | } |
934 | } |
935 | else { |
936 | qWarning() << "Sync dialog called without stuff to change!" ; |
937 | accept(); |
938 | } |
939 | } |
940 | |
941 | |
942 | void SaveNetworksDlg::clientEvent() |
943 | { |
944 | ui.progressBar->setValue(++rcvevents); |
945 | if (rcvevents >= numevents) accept(); |
946 | } |
947 | |