352e370b32e73ed2dd6708b141ff384dfd2d1338
[libeap.git] / wpa_supplicant / wpa_gui-qt4 / peers.cpp
1 /*
2  * wpa_gui - Peers class
3  * Copyright (c) 2009, Atheros Communications
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 version 2 as
7  * published by the Free Software Foundation.
8  *
9  * Alternatively, this software may be distributed under the terms of BSD
10  * license.
11  *
12  * See README and COPYING for more details.
13  */
14
15 #include <cstdio>
16 #include <QImageReader>
17 #include <QMessageBox>
18
19 #include "wpa_ctrl.h"
20 #include "wpagui.h"
21 #include "stringquery.h"
22 #include "peers.h"
23
24
25 enum {
26         peer_role_address = Qt::UserRole + 1,
27         peer_role_type,
28         peer_role_uuid,
29         peer_role_details,
30         peer_role_pri_dev_type,
31         peer_role_ssid,
32         peer_role_config_methods,
33         peer_role_dev_passwd_id
34 };
35
36 /*
37  * TODO:
38  * - add current AP info (e.g., from WPS) in station mode
39  */
40
41 enum peer_type {
42         PEER_TYPE_ASSOCIATED_STATION,
43         PEER_TYPE_AP,
44         PEER_TYPE_AP_WPS,
45         PEER_TYPE_WPS_PIN_NEEDED,
46         PEER_TYPE_WPS_ER_AP,
47         PEER_TYPE_WPS_ER_AP_UNCONFIGURED,
48         PEER_TYPE_WPS_ER_ENROLLEE
49 };
50
51
52 Peers::Peers(QWidget *parent, const char *, bool, Qt::WFlags)
53         : QDialog(parent)
54 {
55         setupUi(this);
56
57         if (QImageReader::supportedImageFormats().contains(QByteArray("svg")))
58         {
59                 default_icon = new QIcon(":/icons/wpa_gui.svg");
60                 ap_icon = new QIcon(":/icons/ap.svg");
61                 laptop_icon = new QIcon(":/icons/laptop.svg");
62         } else {
63                 default_icon = new QIcon(":/icons/wpa_gui.png");
64                 ap_icon = new QIcon(":/icons/ap.png");
65                 laptop_icon = new QIcon(":/icons/laptop.png");
66         }
67
68         peers->setModel(&model);
69         peers->setResizeMode(QListView::Adjust);
70
71         peers->setContextMenuPolicy(Qt::CustomContextMenu);
72         connect(peers, SIGNAL(customContextMenuRequested(const QPoint &)),
73                 this, SLOT(context_menu(const QPoint &)));
74
75         wpagui = NULL;
76 }
77
78
79 void Peers::setWpaGui(WpaGui *_wpagui)
80 {
81         wpagui = _wpagui;
82         update_peers();
83 }
84
85
86 Peers::~Peers()
87 {
88         delete default_icon;
89         delete ap_icon;
90         delete laptop_icon;
91 }
92
93
94 void Peers::languageChange()
95 {
96         retranslateUi(this);
97 }
98
99
100 QString Peers::ItemType(int type)
101 {
102         QString title;
103         switch (type) {
104         case PEER_TYPE_ASSOCIATED_STATION:
105                 title = tr("Associated station");
106                 break;
107         case PEER_TYPE_AP:
108                 title = tr("AP");
109                 break;
110         case PEER_TYPE_AP_WPS:
111                 title = tr("WPS AP");
112                 break;
113         case PEER_TYPE_WPS_PIN_NEEDED:
114                 title = tr("WPS PIN needed");
115                 break;
116         case PEER_TYPE_WPS_ER_AP:
117                 title = tr("ER: WPS AP");
118                 break;
119         case PEER_TYPE_WPS_ER_AP_UNCONFIGURED:
120                 title = tr("ER: WPS AP (Unconfigured)");
121                 break;
122         case PEER_TYPE_WPS_ER_ENROLLEE:
123                 title = tr("ER: WPS Enrollee");
124                 break;
125         }
126         return title;
127 }
128
129
130 void Peers::context_menu(const QPoint &pos)
131 {
132         QMenu *menu = new QMenu;
133         if (menu == NULL)
134                 return;
135
136         QModelIndex idx = peers->indexAt(pos);
137         if (idx.isValid()) {
138                 ctx_item = model.itemFromIndex(idx);
139                 int type = ctx_item->data(peer_role_type).toInt();
140                 menu->addAction(Peers::ItemType(type))->setEnabled(false);
141                 menu->addSeparator();
142
143                 if (type == PEER_TYPE_ASSOCIATED_STATION ||
144                     type == PEER_TYPE_AP_WPS ||
145                     type == PEER_TYPE_WPS_PIN_NEEDED ||
146                     type == PEER_TYPE_WPS_ER_ENROLLEE) {
147                         /* TODO: only for peers that are requesting WPS PIN
148                          * method */
149                         menu->addAction(tr("Enter WPS PIN"), this,
150                                         SLOT(enter_pin()));
151                 }
152
153                 menu->addAction(tr("Properties"), this, SLOT(properties()));
154         } else {
155                 ctx_item = NULL;
156                 menu->addAction(QString("Refresh"), this, SLOT(ctx_refresh()));
157         }
158
159         menu->exec(peers->mapToGlobal(pos));
160 }
161
162
163 void Peers::enter_pin()
164 {
165         if (ctx_item == NULL)
166                 return;
167
168         int peer_type = ctx_item->data(peer_role_type).toInt();
169         QString uuid;
170         QString addr;
171         if (peer_type == PEER_TYPE_WPS_ER_ENROLLEE)
172                 uuid = ctx_item->data(peer_role_uuid).toString();
173         else
174                 addr = ctx_item->data(peer_role_address).toString();
175
176         StringQuery input(tr("PIN:"));
177         input.setWindowTitle(tr("PIN for ") + ctx_item->text());
178         if (input.exec() != QDialog::Accepted)
179                 return;
180
181         char cmd[100];
182         char reply[100];
183         size_t reply_len;
184
185         if (peer_type == PEER_TYPE_WPS_ER_ENROLLEE) {
186                 snprintf(cmd, sizeof(cmd), "WPS_ER_PIN %s %s",
187                          uuid.toAscii().constData(),
188                          input.get_string().toAscii().constData());
189         } else {
190                 snprintf(cmd, sizeof(cmd), "WPS_PIN %s %s",
191                          addr.toAscii().constData(),
192                          input.get_string().toAscii().constData());
193         }
194         reply_len = sizeof(reply) - 1;
195         if (wpagui->ctrlRequest(cmd, reply, &reply_len) < 0) {
196                 QMessageBox msg;
197                 msg.setIcon(QMessageBox::Warning);
198                 msg.setText("Failed to set the WPS PIN.");
199                 msg.exec();
200         }
201 }
202
203
204 void Peers::ctx_refresh()
205 {
206         update_peers();
207 }
208
209
210 void Peers::add_station(QString info)
211 {
212         QStringList lines = info.split(QRegExp("\\n"));
213         QString name;
214
215         for (QStringList::Iterator it = lines.begin();
216              it != lines.end(); it++) {
217                 int pos = (*it).indexOf('=') + 1;
218                 if (pos < 1)
219                         continue;
220
221                 if ((*it).startsWith("wpsDeviceName="))
222                         name = (*it).mid(pos);
223         }
224
225         if (name.isEmpty())
226                 name = lines[0];
227
228         QStandardItem *item = new QStandardItem(*laptop_icon, name);
229         if (item) {
230                 item->setData(lines[0], peer_role_address);
231                 item->setData(PEER_TYPE_ASSOCIATED_STATION,
232                               peer_role_type);
233                 item->setData(info, peer_role_details);
234                 item->setToolTip(ItemType(PEER_TYPE_ASSOCIATED_STATION));
235                 model.appendRow(item);
236         }
237 }
238
239
240 void Peers::add_stations()
241 {
242         char reply[2048];
243         size_t reply_len;
244         char cmd[30];
245         int res;
246
247         reply_len = sizeof(reply) - 1;
248         if (wpagui->ctrlRequest("STA-FIRST", reply, &reply_len) < 0)
249                 return;
250
251         do {
252                 reply[reply_len] = '\0';
253                 QString info(reply);
254                 char *txt = reply;
255                 while (*txt != '\0' && *txt != '\n')
256                         txt++;
257                 *txt++ = '\0';
258                 if (strncmp(reply, "FAIL", 4) == 0 ||
259                     strncmp(reply, "UNKNOWN", 7) == 0)
260                         break;
261
262                 add_station(info);
263
264                 reply_len = sizeof(reply) - 1;
265                 snprintf(cmd, sizeof(cmd), "STA-NEXT %s", reply);
266                 res = wpagui->ctrlRequest(cmd, reply, &reply_len);
267         } while (res >= 0);
268 }
269
270
271 void Peers::add_single_station(const char *addr)
272 {
273         char reply[2048];
274         size_t reply_len;
275         char cmd[30];
276
277         reply_len = sizeof(reply) - 1;
278         snprintf(cmd, sizeof(cmd), "STA %s", addr);
279         if (wpagui->ctrlRequest(cmd, reply, &reply_len) < 0)
280                 return;
281
282         reply[reply_len] = '\0';
283         QString info(reply);
284         char *txt = reply;
285         while (*txt != '\0' && *txt != '\n')
286                 txt++;
287         *txt++ = '\0';
288         if (strncmp(reply, "FAIL", 4) == 0 ||
289             strncmp(reply, "UNKNOWN", 7) == 0)
290                 return;
291
292         add_station(info);
293 }
294
295
296 void Peers::add_scan_results()
297 {
298         char reply[2048];
299         size_t reply_len;
300         int index;
301         char cmd[20];
302
303         index = 0;
304         while (wpagui) {
305                 snprintf(cmd, sizeof(cmd), "BSS %d", index++);
306                 if (index > 1000)
307                         break;
308
309                 reply_len = sizeof(reply) - 1;
310                 if (wpagui->ctrlRequest(cmd, reply, &reply_len) < 0)
311                         break;
312                 reply[reply_len] = '\0';
313
314                 QString bss(reply);
315                 if (bss.isEmpty() || bss.startsWith("FAIL"))
316                         break;
317
318                 QString ssid, bssid, flags, wps_name, pri_dev_type;
319
320                 QStringList lines = bss.split(QRegExp("\\n"));
321                 for (QStringList::Iterator it = lines.begin();
322                      it != lines.end(); it++) {
323                         int pos = (*it).indexOf('=') + 1;
324                         if (pos < 1)
325                                 continue;
326
327                         if ((*it).startsWith("bssid="))
328                                 bssid = (*it).mid(pos);
329                         else if ((*it).startsWith("flags="))
330                                 flags = (*it).mid(pos);
331                         else if ((*it).startsWith("ssid="))
332                                 ssid = (*it).mid(pos);
333                         else if ((*it).startsWith("wps_device_name="))
334                                 wps_name = (*it).mid(pos);
335                         else if ((*it).startsWith("wps_primary_device_type="))
336                                 pri_dev_type = (*it).mid(pos);
337                 }
338
339                 QString name = wps_name;
340                 if (name.isEmpty())
341                         name = ssid + "\n" + bssid;
342
343                 QStandardItem *item = new QStandardItem(*ap_icon, name);
344                 if (item) {
345                         item->setData(bssid, peer_role_address);
346                         int type;
347                         if (flags.contains("[WPS"))
348                                 type = PEER_TYPE_AP_WPS;
349                         else
350                                 type = PEER_TYPE_AP;
351                         item->setData(type, peer_role_type);
352
353                         for (int i = 0; i < lines.size(); i++) {
354                                 if (lines[i].length() > 60) {
355                                         lines[i].remove(
356                                                 60, lines[i].length());
357                                         lines[i] += "..";
358                                 }
359                         }
360                         item->setToolTip(ItemType(type));
361                         item->setData(lines.join("\n"), peer_role_details);
362                         if (!pri_dev_type.isEmpty())
363                                 item->setData(pri_dev_type,
364                                               peer_role_pri_dev_type);
365                         if (!ssid.isEmpty())
366                                 item->setData(ssid, peer_role_ssid);
367                         model.appendRow(item);
368                 }
369         }
370 }
371
372
373 void Peers::update_peers()
374 {
375         model.clear();
376         if (wpagui == NULL)
377                 return;
378
379         char reply[20];
380         size_t replylen = sizeof(reply) - 1;
381         wpagui->ctrlRequest("WPS_ER_START", reply, &replylen);
382
383         add_stations();
384         add_scan_results();
385 }
386
387
388 QStandardItem * Peers::find_addr(QString addr)
389 {
390         if (model.rowCount() == 0)
391                 return NULL;
392
393         QModelIndexList lst = model.match(model.index(0, 0), peer_role_address,
394                                           addr);
395         if (lst.size() == 0)
396                 return NULL;
397         return model.itemFromIndex(lst[0]);
398 }
399
400
401 QStandardItem * Peers::find_uuid(QString uuid)
402 {
403         if (model.rowCount() == 0)
404                 return NULL;
405
406         QModelIndexList lst = model.match(model.index(0, 0), peer_role_uuid,
407                                           uuid);
408         if (lst.size() == 0)
409                 return NULL;
410         return model.itemFromIndex(lst[0]);
411 }
412
413
414 void Peers::event_notify(WpaMsg msg)
415 {
416         QString text = msg.getMsg();
417
418         if (text.startsWith(WPS_EVENT_PIN_NEEDED)) {
419                 /*
420                  * WPS-PIN-NEEDED 5a02a5fa-9199-5e7c-bc46-e183d3cb32f7
421                  * 02:2a:c4:18:5b:f3
422                  * [Wireless Client|Company|cmodel|123|12345|1-0050F204-1]
423                  */
424                 QStringList items = text.split(' ');
425                 QString uuid = items[1];
426                 QString addr = items[2];
427                 QString name = "";
428
429                 QStandardItem *item = find_addr(addr);
430                 if (item)
431                         return;
432
433                 int pos = text.indexOf('[');
434                 if (pos >= 0) {
435                         int pos2 = text.lastIndexOf(']');
436                         if (pos2 >= pos) {
437                                 items = text.mid(pos + 1, pos2 - pos - 1).
438                                         split('|');
439                                 name = items[0];
440                                 items.append(addr);
441                         }
442                 }
443
444                 item = new QStandardItem(*laptop_icon, name);
445                 if (item) {
446                         item->setData(addr, peer_role_address);
447                         item->setData(PEER_TYPE_WPS_PIN_NEEDED,
448                                       peer_role_type);
449                         item->setToolTip(ItemType(PEER_TYPE_WPS_PIN_NEEDED));
450                         item->setData(items.join("\n"), peer_role_details);
451                         item->setData(items[5], peer_role_pri_dev_type);
452                         model.appendRow(item);
453                 }
454                 return;
455         }
456
457         if (text.startsWith(AP_STA_CONNECTED)) {
458                 /* AP-STA-CONNECTED 02:2a:c4:18:5b:f3 */
459                 QStringList items = text.split(' ');
460                 QString addr = items[1];
461                 QStandardItem *item = find_addr(addr);
462                 if (item == NULL || item->data(peer_role_type).toInt() !=
463                     PEER_TYPE_ASSOCIATED_STATION)
464                         add_single_station(addr.toAscii().constData());
465                 return;
466         }
467
468         if (text.startsWith(AP_STA_DISCONNECTED)) {
469                 /* AP-STA-DISCONNECTED 02:2a:c4:18:5b:f3 */
470                 QStringList items = text.split(' ');
471                 QString addr = items[1];
472
473                 if (model.rowCount() == 0)
474                         return;
475
476                 QModelIndexList lst = model.match(model.index(0, 0),
477                                                   peer_role_address, addr);
478                 for (int i = 0; i < lst.size(); i++) {
479                         QStandardItem *item = model.itemFromIndex(lst[i]);
480                         if (item && item->data(peer_role_type).toInt() ==
481                             PEER_TYPE_ASSOCIATED_STATION)
482                                 model.removeRow(lst[i].row());
483                 }
484                 return;
485         }
486
487         if (text.startsWith(WPS_EVENT_ER_AP_ADD)) {
488                 /*
489                  * WPS-ER-AP-ADD 87654321-9abc-def0-1234-56789abc0002
490                  * 02:11:22:33:44:55 pri_dev_type=6-0050F204-1 wps_state=1
491                  * |Very friendly name|Company|Long description of the model|
492                  * WAP|http://w1.fi/|http://w1.fi/hostapd/
493                  */
494                 QStringList items = text.split(' ');
495                 if (items.size() < 5)
496                         return;
497                 QString uuid = items[1];
498                 QString addr = items[2];
499                 QString pri_dev_type = items[3].mid(13);
500                 int wps_state = items[4].mid(10).toInt();
501
502                 int pos = text.indexOf('|');
503                 if (pos < 0)
504                         return;
505                 items = text.mid(pos + 1).split('|');
506                 if (items.size() < 1)
507                         return;
508
509                 QStandardItem *item = find_uuid(uuid);
510                 if (item)
511                         return;
512
513                 item = new QStandardItem(*ap_icon, items[0]);
514                 if (item) {
515                         item->setData(uuid, peer_role_uuid);
516                         item->setData(addr, peer_role_address);
517                         int type = wps_state == 2 ? PEER_TYPE_WPS_ER_AP:
518                                 PEER_TYPE_WPS_ER_AP_UNCONFIGURED;
519                         item->setData(type, peer_role_type);
520                         item->setToolTip(ItemType(type));
521                         item->setData(pri_dev_type, peer_role_pri_dev_type);
522                         item->setData(items.join(QString("\n")),
523                                       peer_role_details);
524                         model.appendRow(item);
525                 }
526
527                 return;
528         }
529
530         if (text.startsWith(WPS_EVENT_ER_AP_REMOVE)) {
531                 /* WPS-ER-AP-REMOVE 87654321-9abc-def0-1234-56789abc0002 */
532                 QStringList items = text.split(' ');
533                 if (items.size() < 2)
534                         return;
535                 if (model.rowCount() == 0)
536                         return;
537
538                 QModelIndexList lst = model.match(model.index(0, 0),
539                                                   peer_role_uuid, items[1]);
540                 for (int i = 0; i < lst.size(); i++) {
541                         QStandardItem *item = model.itemFromIndex(lst[i]);
542                         if (item &&
543                             (item->data(peer_role_type).toInt() ==
544                              PEER_TYPE_WPS_ER_AP ||
545                              item->data(peer_role_type).toInt() ==
546                              PEER_TYPE_WPS_ER_AP_UNCONFIGURED))
547                                 model.removeRow(lst[i].row());
548                 }
549                 return;
550         }
551
552         if (text.startsWith(WPS_EVENT_ER_ENROLLEE_ADD)) {
553                 /*
554                  * WPS-ER-ENROLLEE-ADD 2b7093f1-d6fb-5108-adbb-bea66bb87333
555                  * 02:66:a0:ee:17:27 M1=1 config_methods=0x14d dev_passwd_id=0
556                  * pri_dev_type=1-0050F204-1
557                  * |Wireless Client|Company|cmodel|123|12345|
558                  */
559                 QStringList items = text.split(' ');
560                 if (items.size() < 3)
561                         return;
562                 QString uuid = items[1];
563                 QString addr = items[2];
564                 QString pri_dev_type = items[6].mid(13);
565                 int config_methods = -1;
566                 int dev_passwd_id = -1;
567
568                 for (int i = 3; i < items.size(); i++) {
569                         int pos = items[i].indexOf('=') + 1;
570                         if (pos < 1)
571                                 continue;
572                         QString val = items[i].mid(pos);
573                         if (items[i].startsWith("config_methods=")) {
574                                 config_methods = val.toInt(0, 0);
575                         } else if (items[i].startsWith("dev_passwd_id=")) {
576                                 dev_passwd_id = val.toInt();
577                         }
578                 }
579
580                 int pos = text.indexOf('|');
581                 if (pos < 0)
582                         return;
583                 items = text.mid(pos + 1).split('|');
584                 if (items.size() < 1)
585                         return;
586                 QString name = items[0];
587                 if (name.length() == 0)
588                         name = addr;
589
590                 remove_enrollee_uuid(uuid);
591
592                 QStandardItem *item;
593                 item = new QStandardItem(*laptop_icon, name);
594                 if (item) {
595                         item->setData(uuid, peer_role_uuid);
596                         item->setData(addr, peer_role_address);
597                         item->setData(PEER_TYPE_WPS_ER_ENROLLEE,
598                                       peer_role_type);
599                         item->setToolTip(ItemType(PEER_TYPE_WPS_ER_ENROLLEE));
600                         item->setData(items.join(QString("\n")),
601                                       peer_role_details);
602                         item->setData(pri_dev_type, peer_role_pri_dev_type);
603                         if (config_methods >= 0)
604                                 item->setData(config_methods,
605                                               peer_role_config_methods);
606                         if (dev_passwd_id >= 0)
607                                 item->setData(dev_passwd_id,
608                                               peer_role_dev_passwd_id);
609                         model.appendRow(item);
610                 }
611
612                 return;
613         }
614
615         if (text.startsWith(WPS_EVENT_ER_ENROLLEE_REMOVE)) {
616                 /*
617                  * WPS-ER-ENROLLEE-REMOVE 2b7093f1-d6fb-5108-adbb-bea66bb87333
618                  * 02:66:a0:ee:17:27
619                  */
620                 QStringList items = text.split(' ');
621                 if (items.size() < 2)
622                         return;
623                 remove_enrollee_uuid(items[1]);
624                 return;
625         }
626 }
627
628
629 void Peers::closeEvent(QCloseEvent *)
630 {
631         if (wpagui) {
632                 char reply[20];
633                 size_t replylen = sizeof(reply) - 1;
634                 wpagui->ctrlRequest("WPS_ER_STOP", reply, &replylen);
635         }
636 }
637
638
639 void Peers::done(int r)
640 {
641         QDialog::done(r);
642         close();
643 }
644
645
646 void Peers::remove_enrollee_uuid(QString uuid)
647 {
648         if (model.rowCount() == 0)
649                 return;
650
651         QModelIndexList lst = model.match(model.index(0, 0),
652                                           peer_role_uuid, uuid);
653         for (int i = 0; i < lst.size(); i++) {
654                 QStandardItem *item = model.itemFromIndex(lst[i]);
655                 if (item && item->data(peer_role_type).toInt() ==
656                     PEER_TYPE_WPS_ER_ENROLLEE)
657                         model.removeRow(lst[i].row());
658         }
659 }
660
661
662 void Peers::properties()
663 {
664         if (ctx_item == NULL)
665                 return;
666
667         QMessageBox msg(this);
668         msg.setStandardButtons(QMessageBox::Ok);
669         msg.setDefaultButton(QMessageBox::Ok);
670         msg.setEscapeButton(QMessageBox::Ok);
671         msg.setWindowTitle(tr("Peer Properties"));
672
673         int type = ctx_item->data(peer_role_type).toInt();
674         QString title = Peers::ItemType(type);
675
676         msg.setText(title + QString("\n") + tr("Name: ") + ctx_item->text());
677
678         QVariant var;
679         QString info;
680
681         var = ctx_item->data(peer_role_address);
682         if (var.isValid())
683                 info += tr("Address: ") + var.toString() + QString("\n");
684
685         var = ctx_item->data(peer_role_uuid);
686         if (var.isValid())
687                 info += tr("UUID: ") + var.toString() + QString("\n");
688
689         var = ctx_item->data(peer_role_pri_dev_type);
690         if (var.isValid())
691                 info += tr("Primary Device Type: ") + var.toString() +
692                         QString("\n");
693
694         var = ctx_item->data(peer_role_ssid);
695         if (var.isValid())
696                 info += tr("SSID: ") + var.toString() + QString("\n");
697
698         var = ctx_item->data(peer_role_config_methods);
699         if (var.isValid()) {
700                 int methods = var.toInt();
701                 info += tr("Configuration Methods: ");
702                 if (methods & 0x0001)
703                         info += tr("[USBA]");
704                 if (methods & 0x0002)
705                         info += tr("[Ethernet]");
706                 if (methods & 0x0004)
707                         info += tr("[Label]");
708                 if (methods & 0x0008)
709                         info += tr("[Display]");
710                 if (methods & 0x0010)
711                         info += tr("[Ext. NFC Token]");
712                 if (methods & 0x0020)
713                         info += tr("[Int. NFC Token]");
714                 if (methods & 0x0040)
715                         info += tr("[NFC Interface]");
716                 if (methods & 0x0080)
717                         info += tr("[Push Button]");
718                 if (methods & 0x0100)
719                         info += tr("[Keypad]");
720                 info += "\n";
721         }
722
723         var = ctx_item->data(peer_role_dev_passwd_id);
724         if (var.isValid()) {
725                 info += tr("Device Password ID: ") + var.toString();
726                 switch (var.toInt()) {
727                 case 0:
728                         info += tr(" (Default PIN)");
729                         break;
730                 case 1:
731                         info += tr(" (User-specified PIN)");
732                         break;
733                 case 2:
734                         info += tr(" (Machine-specified PIN)");
735                         break;
736                 case 3:
737                         info += tr(" (Rekey)");
738                         break;
739                 case 4:
740                         info += tr(" (Push Button)");
741                         break;
742                 case 5:
743                         info += tr(" (Registrar-specified)");
744                         break;
745                 }
746                 info += "\n";
747         }
748
749         msg.setInformativeText(info);
750
751         var = ctx_item->data(peer_role_details);
752         if (var.isValid())
753                 msg.setDetailedText(var.toString());
754
755         msg.exec();
756 }