my notes for future reference .. or similar.
[quassel.git] / gui / serverlist.cpp
1 /***************************************************************************
2  *   Copyright (C) 2005 by The Quassel 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) any later version.                                   *
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 "serverlist.h"
22 #include "global.h"
23
24 /* NOTE: This dialog holds not only the server list, but also the identities.
25  *       This makes perfect sense given the fact that connections are initiated from
26  *       this dialog, and that the dialog exists during the lifetime of the program.
27  */
28
29 ServerListDlg::ServerListDlg(QWidget *parent) : QDialog(parent) {
30   ui.setupUi(this);
31
32   QSettings settings;
33   settings.beginGroup("GUI");
34   ui.showOnStartup->setChecked(settings.value("ShowServerListOnStartup", true).toBool());
35   // create some default entries
36   VarMap s1, s2, s3, s4;
37
38   s1["group"] = "Private Servers";
39   networks["mindNet"] = s1;
40   s2["group"] = "Private Servers";
41   networks["fooBar"] = s2;
42   s3["group"] = "";
43   networks["Single"] = s3;
44   s4["group"] = "Public Servers";
45   networks["public"] = s4;
46
47   // load networks from QSettings here instead
48   // [...]
49
50   // Construct tree widget (and its items) from networks
51   QStringList headers;
52   headers << "Network" << "Autoconnect";
53   ui.networkTree->setHeaderLabels(headers);
54   QHash<QString, QTreeWidgetItem *> groups;
55   foreach(QString net, networks.keys()) {
56     VarMap s = networks[net].toMap();
57     QString gr = s["group"].toString();
58     QTreeWidgetItem *item = 0;
59     if(gr == "") {
60       item = new QTreeWidgetItem(ui.networkTree);
61     } else {
62       if(groups.contains(gr)) {
63         item = new QTreeWidgetItem(groups[gr]);
64       } else {
65         QTreeWidgetItem *newgr = new QTreeWidgetItem(ui.networkTree);
66         newgr->setText(0, gr);
67         newgr->setFlags(newgr->flags() & ~Qt::ItemIsSelectable);
68         ui.networkTree->expandItem(newgr);
69         groups[gr] = newgr;
70         item = new QTreeWidgetItem(newgr);
71       }
72     }
73     item->setText(0, net);
74     //item->setFlags(item->flags() | Qt::ItemIsUserCheckable);
75     item->setCheckState(1, Qt::Unchecked);
76   }
77   connect(ui.networkTree, SIGNAL(itemSelectionChanged()), this, SLOT(updateButtons()));
78
79   loadIdentities();
80   settings.endGroup();
81 }
82
83 ServerListDlg::~ServerListDlg() {
84
85 }
86
87 void ServerListDlg::updateButtons() {
88   QList<QTreeWidgetItem *> selected = ui.networkTree->selectedItems();
89   ui.editButton->setEnabled(selected.size() == 1);
90   ui.deleteButton->setEnabled(selected.size() >= 1);
91   ui.connectButton->setEnabled(selected.size() >= 1);
92
93 }
94
95 bool ServerListDlg::showOnStartup() {
96   return ui.showOnStartup->isChecked();
97 }
98
99 void ServerListDlg::on_addButton_clicked() {
100   NetworkEditDlg dlg(this, VarMap(), identities);
101   if(dlg.exec() == QDialog::Accepted) {
102
103   }
104 }
105
106 void ServerListDlg::loadNetworks() {
107
108 }
109
110 void ServerListDlg::storeNetworks() {
111
112 }
113
114 void ServerListDlg::loadIdentities() {
115   identities = global->getData("Identities", VarMap()).toMap();
116   while(!identities.contains("Default")) {
117     editIdentities();
118   }
119 }
120
121 void ServerListDlg::storeIdentities() {
122   global->putData("Identities", identities);
123 }
124
125 void ServerListDlg::editIdentities() {
126   IdentitiesDlg dlg(this, identities);
127   if(dlg.exec() == QDialog::Accepted) {
128     identities = dlg.getIdentities();
129     QMap<QString, QString> mapping = dlg.getNameMapping();
130     // add mapping here  <-- well, I don't fucking know anymore what I meant by this back in 2005...
131
132     //
133     storeIdentities();
134     storeNetworks();  // ? how to treat mapping and NOT save changes not yet applied to the server list?
135   }
136 }
137
138 void ServerListDlg::on_showOnStartup_stateChanged(int) {
139   QSettings s;
140   s.setValue("GUI/ShowServerListOnStartup", ui.showOnStartup->isChecked());
141 }
142
143 /***************************************************************************/
144
145 NetworkEditDlg::NetworkEditDlg(QWidget *parent, VarMap _network, VarMap _identities) : QDialog(parent) {
146   ui.setupUi(this);
147   network = _network;
148   identities = _identities;
149
150   ui.identityList->addItem(tr("Default Identity"));
151
152   foreach(QString id, identities.keys()) {
153     if(id != "Default") ui.identityList->addItem(id);
154   }
155
156 }
157
158 VarMap NetworkEditDlg::createDefaultNetwork() {
159   VarMap net;
160
161   net["group"] = "";
162
163   return net;
164 }
165
166 /***************************************************************************/
167
168 IdentitiesDlg::IdentitiesDlg(QWidget *parent, VarMap _identities) : QDialog(parent) {
169   ui.setupUi(this);
170   connect(global, SIGNAL(dataUpdatedRemotely(QString)), this, SLOT(globalDataUpdated(QString)));
171
172   connect(ui.enableAutoAway, SIGNAL(stateChanged(int)), this, SLOT(autoAwayChecked()));
173
174   identities = _identities;
175   foreach(QString name, identities.keys()) {
176     nameMapping[name] = name;
177   }
178   if(identities.size() == 0) {
179     VarMap id = createDefaultIdentity();
180     id["IdName"] = "Default";
181     identities["Default"] = id;
182   }
183   ui.identityList->addItem(tr("Default Identity"));
184
185   foreach(QString id, identities.keys()) {
186     if(id != "Default") ui.identityList->addItem(id);
187   }
188   updateWidgets();
189   lastIdentity = getCurIdentity();
190   connect(ui.identityList, SIGNAL(activated(QString)), this, SLOT(identityChanged(QString)));
191   connect(ui.editIdentitiesButton, SIGNAL(clicked()), this, SLOT(editIdentities()));
192   connect(ui.nickList, SIGNAL(itemSelectionChanged()), this, SLOT(nickSelectionChanged()));
193   connect(ui.addNickButton, SIGNAL(clicked()), this, SLOT(addNick()));
194   connect(ui.editNickButton, SIGNAL(clicked()), this, SLOT(editNick()));
195   connect(ui.delNickButton, SIGNAL(clicked()), this, SLOT(delNick()));
196   connect(ui.upNickButton, SIGNAL(clicked()), this, SLOT(upNick()));
197   connect(ui.downNickButton, SIGNAL(clicked()), this, SLOT(downNick()));
198 }
199
200 void IdentitiesDlg::globalDataUpdated(QString key) {
201   if(key == "Identities") {
202     if(QMessageBox::warning(this, tr("Data changed remotely!"), tr("<b>Some other GUI client changed the identities data!</b><br>"
203                                                                 "Apply updated settings, losing all changes done locally?"),
204                                                                 QMessageBox::Apply|QMessageBox::Discard) == QMessageBox::Apply) {
205       identities = global->getData(key).toMap();
206       updateWidgets();
207     }
208   }
209 }
210
211 VarMap IdentitiesDlg::createDefaultIdentity() {
212   VarMap id;
213   id["RealName"] = "foo";
214   id["Ident"] = "";
215   id["NickList"] = QStringList();
216   id["enableAwayNick"] = false;
217   id["AwayNick"] = "";
218   id["enableAwayReason"] = false;
219   id["AwayReason"] = "";
220   id["enableReturnMessage"] = false;
221   id["ReturnMessage"] = "";
222   id["enableAutoAway"] = false;
223   id["AutoAwayTime"] = 10;
224   id["enableAutoAwayReason"] = false;
225   id["AutoAwayReason"] = "";
226   id["enableAutoAwayReturn"] = false;
227   id["AutoAwayReturn"] = "";
228   id["PartReason"] = "Quasseling elsewhere.";
229   id["QuitReason"] = "Every Quassel comes to its end.";
230   id["KickReason"] = "No more quasseling for you!";
231
232   return id;
233 }
234
235 QString IdentitiesDlg::getCurIdentity() {
236   if(ui.identityList->currentIndex() == 0) return "Default";
237   return ui.identityList->currentText();
238 }
239
240 void IdentitiesDlg::updateWidgets() {
241   VarMap id = identities[getCurIdentity()].toMap();
242   ui.realNameEdit->setText(id["RealName"].toString());
243   ui.identEdit->setText(id["Ident"].toString());
244   ui.nickList->clear();
245   ui.nickList->addItems(id["NickList"].toStringList());
246   if(ui.nickList->count()>0) ui.nickList->setCurrentRow(0);
247   ui.enableAwayNick->setChecked(id["enableAwayNick"].toBool());
248   ui.awayNickEdit->setText(id["AwayNick"].toString());
249   ui.awayNickEdit->setEnabled(ui.enableAwayNick->isChecked());
250   ui.enableAwayReason->setChecked(id["enableAwayReason"].toBool());
251   ui.awayReasonEdit->setText(id["AwayReason"].toString());
252   ui.awayReasonEdit->setEnabled(ui.enableAwayReason->isChecked());
253   ui.enableReturnMessage->setChecked(id["enableReturnMessage"].toBool());
254   ui.returnMessageEdit->setText(id["ReturnMessage"].toString());
255   ui.returnMessageEdit->setEnabled(ui.enableReturnMessage->isChecked());
256   ui.enableAutoAway->setChecked(id["enableAutoAway"].toBool());
257   ui.autoAwayTime->setValue(id["AutoAwayTime"].toInt());
258   ui.enableAutoAwayReason->setChecked(id["enableAutoAwayReason"].toBool());
259   ui.autoAwayReasonEdit->setText(id["AutoAwayReason"].toString());
260   ui.enableAutoAwayReturn->setChecked(id["enableAutoAwayReturn"].toBool());
261   ui.autoAwayReturnEdit->setText(id["AutoAwayReturn"].toString());
262   ui.partReasonEdit->setText(id["PartReason"].toString());
263   ui.kickReasonEdit->setText(id["KickReason"].toString());
264   ui.quitReasonEdit->setText(id["QuitReason"].toString());
265   // set enabled states correctly
266   autoAwayChecked();
267   nickSelectionChanged();
268 }
269
270 void IdentitiesDlg::updateIdentity(QString idName) {
271   VarMap id;
272   id["RealName"] = ui.realNameEdit->text();
273   id["Ident"] = ui.identEdit->text();
274   QStringList nicks;
275   for(int i = 0; i < ui.nickList->count(); i++) nicks << ui.nickList->item(i)->text();
276   id["NickList"] = nicks;
277   id["enableAwayNick"] = ui.enableAwayNick->isChecked();
278   id["AwayNick"] = ui.awayNickEdit->text();
279   id["enableAwayReason"] = ui.enableAwayReason->isChecked();
280   id["AwayReason"] = ui.awayReasonEdit->text();
281   id["enableReturnMessage"] = ui.enableReturnMessage->isChecked();
282   id["ReturnMessage"] = ui.returnMessageEdit->text();
283   id["enableAutoAway"] = ui.enableAutoAway->isChecked();
284   id["AutoAwayTime"] = ui.autoAwayTime->value();
285   id["enableAutoAwayReason"] = ui.enableAutoAwayReason->isChecked();
286   id["AutoAwayReason"] = ui.autoAwayReasonEdit->text();
287   id["enableAutoAwayReturn"] = ui.enableAutoAwayReturn->isChecked();
288   id["AutoAwayReturn"] = ui.autoAwayReturnEdit->text();
289   id["PartReason"] = ui.partReasonEdit->text();
290   id["KickReason"] = ui.kickReasonEdit->text();
291   id["QuitReason"] = ui.quitReasonEdit->text();
292
293   id["IdName"] = idName;
294   identities[idName] = id;
295 }
296
297 void IdentitiesDlg::identityChanged(QString) {
298   updateIdentity(lastIdentity);
299   lastIdentity = getCurIdentity();
300   updateWidgets();
301 }
302
303 void IdentitiesDlg::autoAwayChecked() {
304   if(ui.enableAutoAway->isChecked()) {
305     ui.autoAwayLabel_1->setEnabled(1);
306     ui.autoAwayLabel_2->setEnabled(1);
307     ui.autoAwayTime->setEnabled(1);
308     ui.enableAutoAwayReason->setEnabled(1);
309     ui.enableAutoAwayReturn->setEnabled(1);
310     ui.autoAwayReasonEdit->setEnabled(ui.enableAutoAwayReason->isChecked());
311     ui.autoAwayReturnEdit->setEnabled(ui.enableAutoAwayReturn->isChecked());
312   } else {
313     ui.autoAwayLabel_1->setEnabled(0);
314     ui.autoAwayLabel_2->setEnabled(0);
315     ui.autoAwayTime->setEnabled(0);
316     ui.enableAutoAwayReason->setEnabled(0);
317     ui.enableAutoAwayReturn->setEnabled(0);
318     ui.autoAwayReasonEdit->setEnabled(0);
319     ui.autoAwayReturnEdit->setEnabled(0);
320   }
321 }
322
323 void IdentitiesDlg::nickSelectionChanged() {
324   int curidx = ui.nickList->currentRow();
325   ui.editNickButton->setEnabled(curidx >= 0);
326   ui.delNickButton->setEnabled(curidx >= 0);
327   ui.upNickButton->setEnabled(curidx > 0);
328   ui.downNickButton->setEnabled(curidx >= 0 && curidx < ui.nickList->count() - 1);
329 }
330
331 void IdentitiesDlg::addNick() {
332   NickEditDlg dlg(this);
333   if(dlg.exec() == QDialog::Accepted) {
334     QListWidgetItem *item = new QListWidgetItem(ui.nickList);
335     item->setText(dlg.getNick());
336     item->setFlags(item->flags() | Qt::ItemIsEditable);
337     ui.nickList->setCurrentItem(item);
338     nickSelectionChanged();
339   }
340 }
341
342 void IdentitiesDlg::editNick() {
343   NickEditDlg dlg(this, ui.nickList->currentItem()->text());
344   if(dlg.exec() == QDialog::Accepted) {
345     ui.nickList->currentItem()->setText(dlg.getNick());
346   }
347 }
348
349 void IdentitiesDlg::delNick() {
350   int row = ui.nickList->currentRow();
351   delete ui.nickList->takeItem(row);
352   if(row <= ui.nickList->count() - 1) ui.nickList->setCurrentRow(row);
353   else if(row > 0) ui.nickList->setCurrentRow(ui.nickList->count()-1);
354   nickSelectionChanged();
355 }
356
357 void IdentitiesDlg::upNick() {
358   int row = ui.nickList->currentRow();
359   QListWidgetItem *item = ui.nickList->takeItem(row);
360   ui.nickList->insertItem(row-1, item);
361   ui.nickList->setCurrentRow(row-1);
362   nickSelectionChanged();
363 }
364
365 void IdentitiesDlg::downNick() {
366   int row = ui.nickList->currentRow();
367   QListWidgetItem *item = ui.nickList->takeItem(row);
368   ui.nickList->insertItem(row+1, item);
369   ui.nickList->setCurrentRow(row+1);
370   nickSelectionChanged();
371 }
372
373 void IdentitiesDlg::accept() {
374   updateIdentity(getCurIdentity());
375   QString result = checkValidity();
376   if(result.length() == 0) QDialog::accept();
377   else {
378     QMessageBox::warning(this, tr("Invalid Identity!"),
379                          tr("One or more of your identities do not contain all necessary information:\n\n%1\n"
380                              "Please fill in any missing information.").arg(result));
381   }
382 }
383
384 QString IdentitiesDlg::checkValidity() {
385   QString reason;
386   foreach(QString name, identities.keys()) {
387     QString r;
388     VarMap id = identities[name].toMap();
389     if(name == "Default") name = tr("Default Identity");
390     if(id["RealName"].toString().length() == 0) {
391       r += tr(" You have not set a real name.");
392     }
393     if(id["Ident"].toString().length() == 0) {
394       r += tr(" You have to specify an Ident.");
395     }
396     if(id["NickList"].toStringList().size() == 0) {
397       r += tr(" You haven't entered any nicknames.");
398     }
399     if(r.length()>0) {
400       reason += tr("[%1]%2\n").arg(name).arg(r);
401     }
402   }
403   return reason;
404 }
405
406 void IdentitiesDlg::editIdentities() {
407   updateIdentity(getCurIdentity());
408   IdentitiesEditDlg dlg(this, identities, nameMapping, createDefaultIdentity());
409   if(dlg.exec() == QDialog::Accepted) {
410     identities = dlg.getIdentities();
411     nameMapping = dlg.getMapping();
412     ui.identityList->clear();
413     ui.identityList->addItem(tr("Default Identity"));
414     foreach(QString id, identities.keys()) {
415       if(id != "Default") ui.identityList->addItem(id);
416     }
417     lastIdentity = getCurIdentity();
418     updateWidgets();
419   }
420 }
421
422 /******************************************************************************/
423
424 IdentitiesEditDlg::IdentitiesEditDlg(QWidget *parent, VarMap _identities, QMap<QString, QString> _mapping, VarMap templ)
425   : QDialog(parent) {
426   ui.setupUi(this);
427   identities = _identities;
428   mapping = _mapping;
429   identTemplate = templ;
430
431   foreach(QString name, identities.keys()) {
432     if(name == "Default") continue;
433     ui.identList->addItem(name);
434   }
435   ui.identList->sortItems();
436   ui.identList->insertItem(0, tr("Default Identity"));
437   ui.identList->setCurrentRow(0);
438   selectionChanged();
439   connect(ui.identList, SIGNAL(itemSelectionChanged()), this, SLOT(selectionChanged()));
440   connect(ui.addButton, SIGNAL(clicked()), this, SLOT(addIdentity()));
441   connect(ui.duplicateButton, SIGNAL(clicked()), this, SLOT(duplicateIdentity()));
442   connect(ui.renameButton, SIGNAL(clicked()), this, SLOT(renameIdentity()));
443   connect(ui.deleteButton, SIGNAL(clicked()), this, SLOT(deleteIdentity()));
444 }
445
446 void IdentitiesEditDlg::selectionChanged() {
447   int idx = ui.identList->currentRow();
448   ui.duplicateButton->setEnabled(idx >= 0);
449   ui.renameButton->setEnabled(idx > 0);
450   ui.deleteButton->setEnabled(idx > 0);
451
452 }
453
454 void IdentitiesEditDlg::addIdentity() {
455   RenameIdentityDlg dlg(this, identities.keys());
456   if(dlg.exec() == QDialog::Accepted) {
457     VarMap id = identTemplate;
458     identities[dlg.getName()] = id;
459     QListWidgetItem *item = new QListWidgetItem(dlg.getName(), ui.identList);
460     sortList();
461     ui.identList->setCurrentItem(item);
462     selectionChanged();
463   }
464 }
465
466 void IdentitiesEditDlg::duplicateIdentity() {
467   RenameIdentityDlg dlg(this, identities.keys());
468   if(dlg.exec() == QDialog::Accepted) {
469     QString curname = ui.identList->currentRow() == 0 ? "Default" : ui.identList->currentItem()->text();
470     QVariant id = identities[curname];
471     identities[dlg.getName()] = id;
472     QListWidgetItem *item = new QListWidgetItem(dlg.getName(), ui.identList);
473     sortList();
474     ui.identList->setCurrentItem(item);
475     selectionChanged();
476   }
477 }
478
479 void IdentitiesEditDlg::renameIdentity() {
480   QList<QString> names;
481   QString curname = ui.identList->currentItem()->text();
482   foreach(QString n, identities.keys()) {
483     if(n != curname) names.append(n);
484   }
485   RenameIdentityDlg dlg(this, names, curname);
486   if(dlg.exec() == QDialog::Accepted) {
487     QString newname = dlg.getName();
488     foreach(QString key, mapping.keys()) {
489       if(mapping[key] == curname) {
490         mapping[key] = newname;
491         break;
492       }
493     }
494     QVariant id = identities.take(curname);
495     identities[newname] = id;
496     QListWidgetItem *item = ui.identList->currentItem();
497     item->setText(newname);
498     sortList();
499     ui.identList->setCurrentItem(item);
500     selectionChanged();
501   }
502 }
503
504 void IdentitiesEditDlg::deleteIdentity() {
505   QString curname = ui.identList->currentItem()->text();
506   if(QMessageBox::question(this, tr("Delete Identity?"),
507      tr("Do you really want to delete identity \"%1\"?\nNetworks using this identity "
508         "will be reset to use the default identity.").arg(curname),
509     tr("&Delete"), tr("&Cancel"), QString(), 1, 1) == 0) {
510       delete ui.identList->takeItem(ui.identList->currentRow());
511       foreach(QString key, mapping.keys()) {
512         if(mapping[key] == curname) {
513           mapping.remove(key); break;
514         }
515       }
516       identities.remove(curname);
517       selectionChanged();
518   }
519 }
520
521 void IdentitiesEditDlg::sortList() {
522   QListWidgetItem *def = ui.identList->takeItem(0);
523   ui.identList->sortItems();
524   ui.identList->insertItem(0, def);
525 }
526
527 /******************************************************************************/
528
529 NickEditDlg::NickEditDlg(QWidget *parent, QString nick) : QDialog(parent) {
530   ui.setupUi(this);
531   ui.lineEdit->setText(nick);
532   connect(ui.lineEdit, SIGNAL(textChanged(QString)), this, SLOT(textChanged(QString)));
533   textChanged(nick);
534 }
535
536 void NickEditDlg::textChanged(QString text) {
537   ui.okButton->setDisabled(text.isEmpty() || text == "");
538 }
539
540 QString NickEditDlg::getNick() {
541   return ui.lineEdit->text();
542 }
543
544 /*******************************************************************************/
545
546 RenameIdentityDlg::RenameIdentityDlg(QWidget *parent, QList<QString> _reserved, QString name) : QDialog(parent) {
547   ui.setupUi(this);
548   reserved = _reserved;
549   //ui.NickEditDlg->setWindowTitle(tr("Edit Identity Name"));  // why does this not work?
550   ui.label->setText(tr("Identity:"));
551   ui.lineEdit->setText(name);
552   connect(ui.lineEdit, SIGNAL(textChanged(QString)), this, SLOT(textChanged(QString)));
553   textChanged(name);
554 }
555
556 void RenameIdentityDlg::textChanged(QString text) {
557   if(text.length() == 0) { ui.okButton->setEnabled(0); return; }
558   ui.okButton->setDisabled(reserved.contains(text));
559 }
560
561 QString RenameIdentityDlg::getName() {
562   return ui.lineEdit->text();
563 }
564