uint -> NetworkId, uint -> BufferId almost everywhere. Conversion will be made explic...
[quassel.git] / src / qtui / identities.cpp
1 /***************************************************************************
2  *   Copyright (C) 2005/06 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 "identities.h"
22 #include "client.h"
23
24 IdentitiesDlg::IdentitiesDlg(QWidget *parent, QString selected) : QDialog(parent) {
25   ui.setupUi(this);
26   connect(Client::instance(), SIGNAL(sessionDataChanged(const QString &)), this, SLOT(globalDataUpdated(QString)));
27
28   connect(ui.enableAutoAway, SIGNAL(stateChanged(int)), this, SLOT(autoAwayChecked()));
29
30   identities = Client::retrieveSessionData("Identities").toMap();
31   foreach(QString name, identities.keys()) {
32     nameMapping[name] = name;
33   }
34   if(identities.size() == 0) {
35     QVariantMap id = createDefaultIdentity();
36     id["IdName"] = "Default";
37     identities["Default"] = id;
38     nameMapping["Default"] = "Default";
39   }
40   ui.identityList->addItem(tr("Default Identity"));
41
42   foreach(QString id, identities.keys()) {
43     if(id != "Default") ui.identityList->addItem(id);
44     if(id == selected) ui.identityList->setCurrentIndex(ui.identityList->count()-1);
45   }
46   updateWidgets();
47   lastIdentity = getCurIdentity();
48   connect(ui.identityList, SIGNAL(activated(QString)), this, SLOT(identityChanged(QString)));
49   connect(ui.editIdentitiesButton, SIGNAL(clicked()), this, SLOT(editIdentities()));
50   connect(ui.nickList, SIGNAL(itemSelectionChanged()), this, SLOT(nickSelectionChanged()));
51   connect(ui.addNickButton, SIGNAL(clicked()), this, SLOT(addNick()));
52   connect(ui.editNickButton, SIGNAL(clicked()), this, SLOT(editNick()));
53   connect(ui.delNickButton, SIGNAL(clicked()), this, SLOT(delNick()));
54   connect(ui.upNickButton, SIGNAL(clicked()), this, SLOT(upNick()));
55   connect(ui.downNickButton, SIGNAL(clicked()), this, SLOT(downNick()));
56 }
57
58 /* this needs more work! mapping? */
59 void IdentitiesDlg::globalDataUpdated(QString key) {
60   if(key == "Identities") {
61     if(QMessageBox::warning(this, tr("Data changed remotely!"), tr("<b>Some other GUI client changed the identities data!</b><br>"
62        "Apply updated settings, losing all changes done locally?"),
63        QMessageBox::Apply|QMessageBox::Discard) == QMessageBox::Apply) {
64       //identities = global->getData(key).toMap();
65       //updateWidgets();
66          reject();
67        }
68   }
69 }
70
71 QVariantMap IdentitiesDlg::createDefaultIdentity() {
72   QVariantMap id;
73   id["RealName"] = "foo";
74   id["Ident"] = "";
75   id["NickList"] = QStringList();
76   id["enableAwayNick"] = false;
77   id["AwayNick"] = "";
78   id["enableAwayReason"] = false;
79   id["AwayReason"] = "";
80   id["enableReturnMessage"] = false;
81   id["ReturnMessage"] = "";
82   id["enableAutoAway"] = false;
83   id["AutoAwayTime"] = 10;
84   id["enableAutoAwayReason"] = false;
85   id["AutoAwayReason"] = "";
86   id["enableAutoAwayReturn"] = false;
87   id["AutoAwayReturn"] = "";
88   id["PartReason"] = "Quasseling elsewhere.";
89   id["QuitReason"] = "Every Quassel comes to its end.";
90   id["KickReason"] = "No more quasseling for you!";
91
92   return id;
93 }
94
95 QString IdentitiesDlg::getCurIdentity() {
96   if(ui.identityList->currentIndex() == 0) return "Default";
97   return ui.identityList->currentText();
98 }
99
100 void IdentitiesDlg::updateWidgets() {
101   QVariantMap id = identities[getCurIdentity()].toMap();
102   ui.realNameEdit->setText(id["RealName"].toString());
103   ui.identEdit->setText(id["Ident"].toString());
104   ui.nickList->clear();
105   ui.nickList->addItems(id["NickList"].toStringList());
106   if(ui.nickList->count()>0) ui.nickList->setCurrentRow(0);
107   ui.enableAwayNick->setChecked(id["enableAwayNick"].toBool());
108   ui.awayNickEdit->setText(id["AwayNick"].toString());
109   ui.awayNickEdit->setEnabled(ui.enableAwayNick->isChecked());
110   ui.enableAwayReason->setChecked(id["enableAwayReason"].toBool());
111   ui.awayReasonEdit->setText(id["AwayReason"].toString());
112   ui.awayReasonEdit->setEnabled(ui.enableAwayReason->isChecked());
113   ui.enableReturnMessage->setChecked(id["enableReturnMessage"].toBool());
114   ui.returnMessageEdit->setText(id["ReturnMessage"].toString());
115   ui.returnMessageEdit->setEnabled(ui.enableReturnMessage->isChecked());
116   ui.enableAutoAway->setChecked(id["enableAutoAway"].toBool());
117   ui.autoAwayTime->setValue(id["AutoAwayTime"].toInt());
118   ui.enableAutoAwayReason->setChecked(id["enableAutoAwayReason"].toBool());
119   ui.autoAwayReasonEdit->setText(id["AutoAwayReason"].toString());
120   ui.enableAutoAwayReturn->setChecked(id["enableAutoAwayReturn"].toBool());
121   ui.autoAwayReturnEdit->setText(id["AutoAwayReturn"].toString());
122   ui.partReasonEdit->setText(id["PartReason"].toString());
123   ui.kickReasonEdit->setText(id["KickReason"].toString());
124   ui.quitReasonEdit->setText(id["QuitReason"].toString());
125   // set enabled states correctly
126   autoAwayChecked();
127   nickSelectionChanged();
128 }
129
130 void IdentitiesDlg::updateIdentity(QString idName) {
131   QVariantMap id;
132   id["RealName"] = ui.realNameEdit->text();
133   id["Ident"] = ui.identEdit->text();
134   QStringList nicks;
135   for(int i = 0; i < ui.nickList->count(); i++) nicks << ui.nickList->item(i)->text();
136   id["NickList"] = nicks;
137   id["enableAwayNick"] = ui.enableAwayNick->isChecked();
138   id["AwayNick"] = ui.awayNickEdit->text();
139   id["enableAwayReason"] = ui.enableAwayReason->isChecked();
140   id["AwayReason"] = ui.awayReasonEdit->text();
141   id["enableReturnMessage"] = ui.enableReturnMessage->isChecked();
142   id["ReturnMessage"] = ui.returnMessageEdit->text();
143   id["enableAutoAway"] = ui.enableAutoAway->isChecked();
144   id["AutoAwayTime"] = ui.autoAwayTime->value();
145   id["enableAutoAwayReason"] = ui.enableAutoAwayReason->isChecked();
146   id["AutoAwayReason"] = ui.autoAwayReasonEdit->text();
147   id["enableAutoAwayReturn"] = ui.enableAutoAwayReturn->isChecked();
148   id["AutoAwayReturn"] = ui.autoAwayReturnEdit->text();
149   id["PartReason"] = ui.partReasonEdit->text();
150   id["KickReason"] = ui.kickReasonEdit->text();
151   id["QuitReason"] = ui.quitReasonEdit->text();
152
153   id["IdName"] = idName;
154   identities[idName] = id;
155 }
156
157 void IdentitiesDlg::identityChanged(QString) {
158   updateIdentity(lastIdentity);
159   lastIdentity = getCurIdentity();
160   updateWidgets();
161 }
162
163 void IdentitiesDlg::autoAwayChecked() {
164   if(ui.enableAutoAway->isChecked()) {
165     ui.autoAwayLabel_1->setEnabled(1);
166     ui.autoAwayLabel_2->setEnabled(1);
167     ui.autoAwayTime->setEnabled(1);
168     ui.enableAutoAwayReason->setEnabled(1);
169     ui.enableAutoAwayReturn->setEnabled(1);
170     ui.autoAwayReasonEdit->setEnabled(ui.enableAutoAwayReason->isChecked());
171     ui.autoAwayReturnEdit->setEnabled(ui.enableAutoAwayReturn->isChecked());
172   } else {
173     ui.autoAwayLabel_1->setEnabled(0);
174     ui.autoAwayLabel_2->setEnabled(0);
175     ui.autoAwayTime->setEnabled(0);
176     ui.enableAutoAwayReason->setEnabled(0);
177     ui.enableAutoAwayReturn->setEnabled(0);
178     ui.autoAwayReasonEdit->setEnabled(0);
179     ui.autoAwayReturnEdit->setEnabled(0);
180   }
181 }
182
183 void IdentitiesDlg::nickSelectionChanged() {
184   Q_ASSERT(ui.nickList->selectedItems().size() <= 1);
185   int curidx;
186   if(ui.nickList->selectedItems().isEmpty()) curidx = -1;
187   else curidx = ui.nickList->row(ui.nickList->selectedItems()[0]);
188   ui.editNickButton->setEnabled(curidx >= 0);
189   ui.delNickButton->setEnabled(curidx >= 0);
190   ui.upNickButton->setEnabled(curidx > 0);
191   ui.downNickButton->setEnabled(curidx >= 0 && curidx < ui.nickList->count() - 1);
192 }
193
194 void IdentitiesDlg::addNick() {
195   NickEditDlg dlg(this);
196   if(dlg.exec() == QDialog::Accepted) {
197     QListWidgetItem *item = new QListWidgetItem(ui.nickList);
198     item->setText(dlg.getNick());
199     item->setFlags(item->flags() | Qt::ItemIsEditable);
200     ui.nickList->setCurrentItem(item);
201     nickSelectionChanged();
202   }
203 }
204
205 void IdentitiesDlg::editNick() {
206   NickEditDlg dlg(this, ui.nickList->currentItem()->text());
207   if(dlg.exec() == QDialog::Accepted) {
208     ui.nickList->currentItem()->setText(dlg.getNick());
209   }
210 }
211
212 void IdentitiesDlg::delNick() {
213   int row = ui.nickList->currentRow();
214   delete ui.nickList->takeItem(row);
215   if(row <= ui.nickList->count() - 1) ui.nickList->setCurrentRow(row);
216   else if(row > 0) ui.nickList->setCurrentRow(ui.nickList->count()-1);
217   nickSelectionChanged();
218 }
219
220 void IdentitiesDlg::upNick() {
221   int row = ui.nickList->currentRow();
222   QListWidgetItem *item = ui.nickList->takeItem(row);
223   ui.nickList->insertItem(row-1, item);
224   ui.nickList->setCurrentRow(row-1);
225   nickSelectionChanged();
226 }
227
228 void IdentitiesDlg::downNick() {
229   int row = ui.nickList->currentRow();
230   QListWidgetItem *item = ui.nickList->takeItem(row);
231   ui.nickList->insertItem(row+1, item);
232   ui.nickList->setCurrentRow(row+1);
233   nickSelectionChanged();
234 }
235
236 void IdentitiesDlg::accept() {
237   updateIdentity(getCurIdentity());
238   QString result = checkValidity();
239   if(result.length() == 0) {
240     Client::storeSessionData("Identities", identities);
241     // We have to care about renamed identities and update the network list appropriately...
242     QVariantMap networks = Client::retrieveSessionData("Networks").toMap();
243     foreach(QString netname, networks.keys()) {
244       QVariantMap net = networks[netname].toMap();
245       if(nameMapping.contains(net["Identity"].toString())) {
246         net["Identity"] = nameMapping[net["Identity"].toString()];
247       } else net["Identity"] = "Default";
248       networks[netname] = net;
249     }
250     Client::storeSessionData("Networks", networks);
251     QDialog::accept();
252   } else {
253     QMessageBox::warning(this, tr("Invalid Identity!"),
254                          tr("One or more of your identities do not contain all necessary information:\n\n%1\n"
255                              "Please fill in any missing information.").arg(result));
256   }
257 }
258
259 QString IdentitiesDlg::checkValidity() {
260   QString reason;
261   foreach(QString name, identities.keys()) {
262     QString r;
263     QVariantMap id = identities[name].toMap();
264     if(name == "Default") name = tr("Default Identity");
265     if(id["RealName"].toString().isEmpty()) {
266       r += tr(" You have not set a real name.");
267     }
268     if(id["Ident"].toString().isEmpty()) {
269       r += tr(" You have to specify an Ident.");
270     }
271     if(id["NickList"].toStringList().size() == 0) {
272       r += tr(" You haven't entered any nicknames.");
273     }
274     if(r.length()>0) {
275       reason += tr("[%1]%2\n").arg(name).arg(r);
276     }
277   }
278   return reason;
279 }
280
281 void IdentitiesDlg::editIdentities() {
282   updateIdentity(getCurIdentity());
283   IdentitiesEditDlg dlg(this, identities, nameMapping, createDefaultIdentity(), getCurIdentity());
284   if(dlg.exec() == QDialog::Accepted) {
285     identities = dlg.getIdentities();
286     nameMapping = dlg.getMapping();
287     ui.identityList->clear();
288     ui.identityList->addItem(tr("Default Identity"));
289     foreach(QString id, identities.keys()) {
290       if(id != "Default") ui.identityList->addItem(id);
291       if(id == dlg.getSelectedIdentity()) ui.identityList->setCurrentIndex(ui.identityList->count()-1);
292     }
293     lastIdentity = getCurIdentity();
294     updateWidgets();
295   }
296 }
297
298 /******************************************************************************/
299
300 IdentitiesEditDlg::IdentitiesEditDlg(QWidget *parent, QVariantMap _identities, QMap<QString, QString> _mapping, QVariantMap templ, QString selected)
301   : QDialog(parent) {
302   ui.setupUi(this);
303   identities = _identities;
304   mapping = _mapping;
305   identTemplate = templ;
306
307   foreach(QString name, identities.keys()) {
308     if(name == "Default") continue;
309     ui.identList->addItem(name);
310     if(name == selected) ui.identList->setCurrentRow(ui.identList->count()-1);
311   }
312   ui.identList->sortItems();
313   ui.identList->insertItem(0, tr("Default Identity"));
314   if(ui.identList->selectedItems().count()!=1) ui.identList->setCurrentRow(0);
315   selectionChanged();
316   connect(ui.identList, SIGNAL(itemSelectionChanged()), this, SLOT(selectionChanged()));
317   connect(ui.addButton, SIGNAL(clicked()), this, SLOT(addIdentity()));
318   connect(ui.duplicateButton, SIGNAL(clicked()), this, SLOT(duplicateIdentity()));
319   connect(ui.renameButton, SIGNAL(clicked()), this, SLOT(renameIdentity()));
320   connect(ui.deleteButton, SIGNAL(clicked()), this, SLOT(deleteIdentity()));
321   }
322
323   void IdentitiesEditDlg::selectionChanged() {
324     Q_ASSERT(ui.identList->selectedItems().size() == 1);
325     int idx = ui.identList->row(ui.identList->selectedItems()[0]);
326     ui.duplicateButton->setEnabled(idx >= 0);
327     ui.renameButton->setEnabled(idx > 0);
328     ui.deleteButton->setEnabled(idx > 0);
329   }
330
331   void IdentitiesEditDlg::addIdentity() {
332     RenameIdentityDlg dlg(this, identities.keys());
333     if(dlg.exec() == QDialog::Accepted) {
334       QVariantMap id = identTemplate;
335       identities[dlg.getName()] = id;
336       Q_ASSERT(!mapping.contains(dlg.getName()));
337       mapping[dlg.getName()] = dlg.getName();
338       QListWidgetItem *item = new QListWidgetItem(dlg.getName(), ui.identList);
339       sortList();
340       ui.identList->setCurrentItem(item);
341       selectionChanged();
342     }
343   }
344
345   void IdentitiesEditDlg::duplicateIdentity() {
346     RenameIdentityDlg dlg(this, identities.keys());
347     if(dlg.exec() == QDialog::Accepted) {
348       QString curname = ui.identList->currentRow() == 0 ? "Default" : ui.identList->currentItem()->text();
349       QVariant id = identities[curname];
350       identities[dlg.getName()] = id;
351       Q_ASSERT(!mapping.contains(dlg.getName()));
352       mapping[dlg.getName()] = dlg.getName();
353       QListWidgetItem *item = new QListWidgetItem(dlg.getName(), ui.identList);
354       sortList();
355       ui.identList->setCurrentItem(item);
356       selectionChanged();
357     }
358   }
359
360   void IdentitiesEditDlg::renameIdentity() {
361     QList<QString> names;
362     QString curname = ui.identList->currentItem()->text();
363     foreach(QString n, identities.keys()) {
364       if(n != curname) names.append(n);
365     }
366     RenameIdentityDlg dlg(this, names, curname);
367     if(dlg.exec() == QDialog::Accepted) {
368       QString newname = dlg.getName();
369       foreach(QString key, mapping.keys()) {
370         if(mapping[key] == curname) {
371           mapping[key] = newname;
372           break;
373         }
374       }
375       QVariant id = identities.take(curname);
376       identities[newname] = id;
377       QListWidgetItem *item = ui.identList->currentItem();
378       item->setText(newname);
379       sortList();
380       ui.identList->setCurrentItem(item);
381       selectionChanged();
382     }
383   }
384
385   void IdentitiesEditDlg::deleteIdentity() {
386     QString curname = ui.identList->currentItem()->text();
387     if(QMessageBox::question(this, tr("Delete Identity?"),
388        tr("Do you really want to delete identity \"%1\"?\nNetworks using this identity "
389            "will be reset to use the default identity.").arg(curname),
390        tr("&Delete"), tr("&Cancel"), QString(), 1, 1) == 0) {
391          delete ui.identList->takeItem(ui.identList->currentRow());
392          foreach(QString key, mapping.keys()) {
393            if(mapping[key] == curname) {
394              mapping.remove(key); break;
395            }
396          }
397          identities.remove(curname);
398          selectionChanged();
399        }
400   }
401
402   void IdentitiesEditDlg::sortList() {
403     QListWidgetItem *def = ui.identList->takeItem(0);
404     ui.identList->sortItems();
405     ui.identList->insertItem(0, def);
406   }
407
408   /******************************************************************************/
409
410   NickEditDlg::NickEditDlg(QWidget *parent, QString nick) : QDialog(parent) {
411     ui.setupUi(this);
412     ui.lineEdit->setText(nick);
413     connect(ui.lineEdit, SIGNAL(textChanged(QString)), this, SLOT(textChanged(QString)));
414     textChanged(nick);
415   }
416
417   void NickEditDlg::textChanged(QString text) {
418     ui.buttonBox->button(QDialogButtonBox::Ok)->setDisabled(text.isEmpty() || text == "");
419   }
420
421   QString NickEditDlg::getNick() {
422     return ui.lineEdit->text();
423   }
424
425   /*******************************************************************************/
426
427   RenameIdentityDlg::RenameIdentityDlg(QWidget *parent, QList<QString> _reserved, QString name) : QDialog(parent) {
428     ui.setupUi(this);
429     reserved = _reserved;
430     setWindowTitle(tr("Edit Identity Name"));
431     ui.label->setText(tr("Identity:"));
432     ui.lineEdit->setText(name);
433     connect(ui.lineEdit, SIGNAL(textChanged(QString)), this, SLOT(textChanged(QString)));
434     textChanged(name);
435   }
436
437   void RenameIdentityDlg::textChanged(QString text) {
438     if(text.length() == 0) { ui.buttonBox->button(QDialogButtonBox::Ok)->setDisabled(true); return; }
439     ui.buttonBox->button(QDialogButtonBox::Ok)->setDisabled(reserved.contains(text));
440   }
441
442   QString RenameIdentityDlg::getName() {
443     return ui.lineEdit->text();
444   }