Fix comment end after SPDX identifier
[metze/wireshark/wip.git] / ui / qt / lbm_lbtrm_transport_dialog.cpp
1 /* lbm_lbtrm_transport_dialog.cpp
2  *
3  * Copyright (c) 2005-2014 Informatica Corporation. All Rights Reserved.
4  *
5  * Wireshark - Network traffic analyzer
6  * By Gerald Combs <gerald@wireshark.org>
7  * Copyright 1998 Gerald Combs
8  *
9  * SPDX-License-Identifier: GPL-2.0-or-later
10  */
11
12 #include "lbm_lbtrm_transport_dialog.h"
13 #include <ui_lbm_lbtrm_transport_dialog.h>
14
15 #include "file.h"
16
17 #include <ui/qt/utils/qt_ui_utils.h>
18 #include "wireshark_application.h"
19
20 #include <QClipboard>
21 #include <QMenu>
22 #include <QMessageBox>
23 #include <QTreeWidget>
24 #include <QTreeWidgetItemIterator>
25 #include <QMenu>
26
27 #include <epan/packet_info.h>
28 #include <epan/tap.h>
29 #include <epan/to_str.h>
30 #include <epan/dissectors/packet-lbm.h>
31 #include <wsutil/nstime.h>
32
33 namespace
34 {
35     static const int Source_AddressTransport_Column = 0;
36     static const int Source_DataFrames_Column = 1;
37     static const int Source_DataBytes_Column = 2;
38     static const int Source_DataFramesBytes_Column = 3;
39     static const int Source_DataRate_Column = 4;
40     static const int Source_RXDataFrames_Column = 5;
41     static const int Source_RXDataBytes_Column = 6;
42     static const int Source_RXDataFramesBytes_Column = 7;
43     static const int Source_RXDataRate_Column = 8;
44     static const int Source_NCFFrames_Column = 9;
45     static const int Source_NCFCount_Column = 10;
46     static const int Source_NCFBytes_Column = 11;
47     static const int Source_NCFFramesBytes_Column = 12;
48     static const int Source_NCFCountBytes_Column = 13;
49     static const int Source_NCFFramesCount_Column = 14;
50     static const int Source_NCFFramesCountBytes_Column = 15;
51     static const int Source_NCFRate_Column = 16;
52     static const int Source_SMFrames_Column = 17;
53     static const int Source_SMBytes_Column = 18;
54     static const int Source_SMFramesBytes_Column = 19;
55     static const int Source_SMRate_Column = 20;
56
57     static const int Receiver_AddressTransport_Column = 0;
58     static const int Receiver_NAKFrames_Column = 1;
59     static const int Receiver_NAKCount_Column = 2;
60     static const int Receiver_NAKBytes_Column = 3;
61     static const int Receiver_NAKRate_Column = 4;
62
63     static const int Detail_SQN_Column = 0;
64     static const int Detail_Count_Column = 1;
65     static const int Detail_Frame_Column = 2;
66
67     static const double OneKilobit = 1000.0;
68     static const double OneMegabit = OneKilobit * OneKilobit;
69     static const double OneGigabit = OneMegabit * OneKilobit;
70 }
71
72 static QString format_rate(const nstime_t & elapsed, guint64 bytes)
73 {
74     QString result;
75     double elapsed_sec;
76     double rate;
77
78     if (((elapsed.secs == 0) && (elapsed.nsecs == 0)) || (bytes == 0))
79     {
80         return (QString("0"));
81     }
82
83     elapsed_sec = elapsed.secs + (((double)elapsed.nsecs) / 1000000000.0);
84     rate = ((double)(bytes * 8)) / elapsed_sec;
85
86     // Currently rate is in bps
87     if (rate >= OneGigabit)
88     {
89         rate /= OneGigabit;
90         result = QString("%1G").arg(rate, 0, 'f', 2);
91     }
92     else if (rate >= OneMegabit)
93     {
94         rate /= OneMegabit;
95         result = QString("%1M").arg(rate, 0, 'f', 2);
96     }
97     else if (rate >= OneKilobit)
98     {
99         rate /= OneKilobit;
100         result = QString("%1K").arg(rate, 0, 'f', 2);
101     }
102     else
103     {
104         result = QString("%1").arg(rate, 0, 'f', 2);
105     }
106     return (result);
107 }
108
109 // Note:
110 // LBMLBTRMFrameEntry, LBMLBTRMSQNEntry, LBMLBTRMNCFReasonEntry, LBMLBTRMNCFSQNEntry, LBMLBTRMSourceTransportEntry, LBMLBTRMSourceEntry,
111 // LBMLBTRMReceiverTransportEntry, and LBMLBTRMReceiverEntry are all derived from  a QTreeWidgetItem. Each instantiation can exist
112 // in two places: in a QTreeWidget, and in a containing QMap.
113 //
114 // For example:
115 // - LBMLBTRMTransportDialogInfo contains a QMap of the sources (LBMLBTRMSourceEntry) and receivers (LBMLBTRMReceiverEntry)
116 // - A source (LBMLBTRMSourceEntry) contains a QMap of the source transports originating from it (LBMLBTRMSourceTransportEntry)
117 // - A source transport (LBMLBTRMSourceTransportEntry) contains QMaps of data, RX data, and SM SQNs (LBMLBTRMSQNEntry) and NCF SQNs
118 //   (LBMLBTRMNCFSQNEntry)
119 // - A data SQN (LBMLBTRMSQNEntry) contains a QMap of the frames (LBMLBTRMFrameEntry) in which that SQN appears
120 //
121 // Not all of the entries actually appear in a QTreeWidget at one time. For example, in the source details, if no specific source
122 // transport is selected, nothing is in the source details tree. If Data SQNs is selected, then those details appear in the source
123 // details tree. Switching to RX Data SQNs removes whatever is currently in the source details tree, and adds the RX details for
124 // the selected transport.
125 //
126 // The actual owner of one of the above QTreeWidgetItem-derived items is the QMap container in its parent. The item is "loaned" to
127 // the QTreeWidget for display.
128 //
129 // All of this is to explain why
130 // 1) we are frequently adding things to a QTreeWidget
131 // 2) things are removed (takeTopLevelItem) from a QTreeWidget
132 // 3) destruction involves removing all items from all QTreeWidgets (rather than letting QTreeWidget delete them)
133 // 4) the destructor for each item has the form
134 //    <for each QMap container>
135 //      for (XXXMapIterator it = m_xxx.begin(); it != m_xxx.end(); it++)
136 //      {
137 //          delete *it;
138 //      }
139 //      m_xxx.clear();
140 //    The for-loop calls the destructor for each item, while the clear() cleans up the space used by the QMap itself.
141
142 // A frame entry
143 class LBMLBTRMFrameEntry : public QTreeWidgetItem
144 {
145     public:
146         LBMLBTRMFrameEntry(guint32 frame);
147         virtual ~LBMLBTRMFrameEntry(void) { }
148         guint32 getFrame(void) { return (m_frame); }
149
150     private:
151         guint32 m_frame;
152 };
153
154 LBMLBTRMFrameEntry::LBMLBTRMFrameEntry(guint32 frame) :
155     QTreeWidgetItem(),
156     m_frame(frame)
157 {
158     setText(Detail_SQN_Column, QString(" "));
159     setText(Detail_Count_Column, QString(" "));
160     setText(Detail_Frame_Column, QString("%1").arg(m_frame));
161 }
162
163 typedef QMap<guint32, LBMLBTRMFrameEntry *> LBMLBTRMFrameMap;
164 typedef QMap<guint32, LBMLBTRMFrameEntry *>::iterator LBMLBTRMFrameMapIterator;
165
166 // A SQN (SeQuence Number) entry
167 class LBMLBTRMSQNEntry : public QTreeWidgetItem
168 {
169     public:
170         LBMLBTRMSQNEntry(guint32 sqn);
171         virtual ~LBMLBTRMSQNEntry(void);
172         void processFrame(guint32 frame);
173
174     private:
175         LBMLBTRMSQNEntry(void);
176         guint32 m_sqn;
177         guint32 m_count;
178         LBMLBTRMFrameMap m_frames;
179 };
180
181 LBMLBTRMSQNEntry::LBMLBTRMSQNEntry(guint32 sqn) :
182     QTreeWidgetItem(),
183     m_sqn(sqn),
184     m_count(0),
185     m_frames()
186 {
187     setText(Detail_SQN_Column, QString("%1").arg(m_sqn));
188     setTextAlignment(Detail_SQN_Column, Qt::AlignRight);
189     setText(Detail_Count_Column, QString("%1").arg(m_count));
190     setTextAlignment(Detail_Count_Column, Qt::AlignRight);
191     setText(Detail_Frame_Column, QString(" "));
192 }
193
194 LBMLBTRMSQNEntry::~LBMLBTRMSQNEntry(void)
195 {
196     for (LBMLBTRMFrameMapIterator it = m_frames.begin(); it != m_frames.end(); it++)
197     {
198         delete *it;
199     }
200     m_frames.clear();
201 }
202
203 void LBMLBTRMSQNEntry::processFrame(guint32 frame)
204 {
205     LBMLBTRMFrameMapIterator it;
206
207     it = m_frames.find(frame);
208     if (m_frames.end() == it)
209     {
210         LBMLBTRMFrameEntry * entry = new LBMLBTRMFrameEntry(frame);
211         m_frames.insert(frame, entry);
212         addChild(entry);
213         sortChildren(Detail_Frame_Column, Qt::AscendingOrder);
214     }
215     m_count++;
216     setText(Detail_Count_Column, QString("%1").arg(m_count));
217     setTextAlignment(Detail_Count_Column, Qt::AlignRight);
218 }
219
220 // An NCF (Nak ConFirmation) Reason entry
221 class LBMLBTRMNCFReasonEntry : public QTreeWidgetItem
222 {
223     public:
224         LBMLBTRMNCFReasonEntry(guint8 reason);
225         virtual ~LBMLBTRMNCFReasonEntry(void);
226         void processFrame(guint32 frame);
227
228     private:
229         LBMLBTRMNCFReasonEntry(void);
230         guint8 m_reason;
231         QString m_reason_string;
232         guint32 m_count;
233         LBMLBTRMFrameMap m_frames;
234 };
235
236 LBMLBTRMNCFReasonEntry::LBMLBTRMNCFReasonEntry(guint8 reason) :
237     QTreeWidgetItem(),
238     m_reason(reason),
239     m_reason_string(),
240     m_count(0),
241     m_frames()
242 {
243     switch (m_reason)
244     {
245         case LBTRM_NCF_REASON_NO_RETRY:
246             m_reason_string = "No Retry";
247             break;
248         case LBTRM_NCF_REASON_IGNORED:
249             m_reason_string = "Ignored";
250             break;
251         case LBTRM_NCF_REASON_RX_DELAY:
252             m_reason_string = "Retransmit Delay";
253             break;
254         case LBTRM_NCF_REASON_SHED:
255             m_reason_string = "Shed";
256             break;
257         default:
258             m_reason_string = QString("Unknown (%1)").arg(m_reason);
259             break;
260     }
261     setText(Detail_SQN_Column, m_reason_string);
262     setText(Detail_Count_Column, QString("%1").arg(m_count));
263     setTextAlignment(Detail_Count_Column, Qt::AlignRight);
264     setText(Detail_Frame_Column, QString(" "));
265 }
266
267 LBMLBTRMNCFReasonEntry::~LBMLBTRMNCFReasonEntry(void)
268 {
269     for (LBMLBTRMFrameMapIterator it = m_frames.begin(); it != m_frames.end(); it++)
270     {
271         delete *it;
272     }
273     m_frames.clear();
274 }
275
276 void LBMLBTRMNCFReasonEntry::processFrame(guint32 frame)
277 {
278     LBMLBTRMFrameMapIterator it;
279
280     it = m_frames.find(frame);
281     if (m_frames.end() == it)
282     {
283         LBMLBTRMFrameEntry * entry = new LBMLBTRMFrameEntry(frame);
284         m_frames.insert(frame, entry);
285         addChild(entry);
286         sortChildren(Detail_Frame_Column, Qt::AscendingOrder);
287     }
288     m_count++;
289     setText(Detail_Count_Column, QString("%1").arg(m_count));
290     setTextAlignment(Detail_Count_Column, Qt::AlignRight);
291 }
292
293 typedef QMap<guint32, LBMLBTRMNCFReasonEntry *> LBMLBTRMNCFReasonMap;
294 typedef QMap<guint32, LBMLBTRMNCFReasonEntry *>::iterator LBMLBTRMNCFReasonMapIterator;
295
296 // An NCF SQN entry
297 class LBMLBTRMNCFSQNEntry : public QTreeWidgetItem
298 {
299     public:
300         LBMLBTRMNCFSQNEntry(guint32 sqn);
301         virtual ~LBMLBTRMNCFSQNEntry(void);
302         void processFrame(guint8 reason, guint32 frame);
303
304     private:
305         LBMLBTRMNCFSQNEntry(void);
306         guint32 m_sqn;
307         guint32 m_count;
308         LBMLBTRMNCFReasonMap m_reasons;
309 };
310
311 LBMLBTRMNCFSQNEntry::LBMLBTRMNCFSQNEntry(guint32 sqn) :
312     QTreeWidgetItem(),
313     m_sqn(sqn),
314     m_count(0),
315     m_reasons()
316 {
317     setText(Detail_SQN_Column, QString("%1").arg(m_sqn));
318     setTextAlignment(Detail_SQN_Column, Qt::AlignRight);
319     setText(Detail_Count_Column, QString("%1").arg(m_count));
320     setTextAlignment(Detail_Count_Column, Qt::AlignRight);
321     setText(Detail_Frame_Column, QString(" "));
322 }
323
324 LBMLBTRMNCFSQNEntry::~LBMLBTRMNCFSQNEntry(void)
325 {
326     for (LBMLBTRMNCFReasonMapIterator it = m_reasons.begin(); it != m_reasons.end(); it++)
327     {
328         delete *it;
329     }
330     m_reasons.clear();
331 }
332
333 void LBMLBTRMNCFSQNEntry::processFrame(guint8 reason, guint32 frame)
334 {
335     LBMLBTRMNCFReasonMapIterator it;
336     LBMLBTRMNCFReasonEntry * entry = NULL;
337
338     it = m_reasons.find(reason);
339     if (m_reasons.end() == it)
340     {
341         entry = new LBMLBTRMNCFReasonEntry(reason);
342         m_reasons.insert(reason, entry);
343         addChild(entry);
344         sortChildren(Detail_Frame_Column, Qt::AscendingOrder);
345     }
346     else
347     {
348         entry = it.value();
349     }
350     m_count++;
351     setText(Detail_Count_Column, QString("%1").arg(m_count));
352     setTextAlignment(Detail_Count_Column, Qt::AlignRight);
353     entry->processFrame(frame);
354 }
355
356 typedef QMap<guint32, LBMLBTRMSQNEntry *> LBMLBTRMSQNMap;
357 typedef QMap<guint32, LBMLBTRMSQNEntry *>::iterator LBMLBTRMSQNMapIterator;
358 typedef QMap<guint32, LBMLBTRMNCFSQNEntry *> LBMLBTRMNCFSQNMap;
359 typedef QMap<guint32, LBMLBTRMNCFSQNEntry *>::iterator LBMLBTRMNCFSQNMapIterator;
360
361 // A source transport entry
362 class LBMLBTRMSourceTransportEntry : public QTreeWidgetItem
363 {
364         friend class LBMLBTRMTransportDialog;
365
366     public:
367         LBMLBTRMSourceTransportEntry(const QString & transport);
368         virtual ~LBMLBTRMSourceTransportEntry(void);
369         void processPacket(const packet_info * pinfo, const lbm_lbtrm_tap_info_t * tap_info);
370
371     protected:
372         QString m_transport;
373
374     private:
375         void fillItem(void);
376         guint64 m_data_frames;
377         guint64 m_data_bytes;
378         guint64 m_rx_data_frames;
379         guint64 m_rx_data_bytes;
380         guint64 m_ncf_frames;
381         guint64 m_ncf_count;
382         guint64 m_ncf_bytes;
383         guint64 m_sm_frames;
384         guint64 m_sm_bytes;
385         nstime_t m_first_frame_timestamp;
386         bool m_first_frame_timestamp_valid;
387         nstime_t m_last_frame_timestamp;
388
389     protected:
390         LBMLBTRMSQNMap m_data_sqns;
391         LBMLBTRMSQNMap m_rx_data_sqns;
392         LBMLBTRMNCFSQNMap m_ncf_sqns;
393         LBMLBTRMSQNMap m_sm_sqns;
394 };
395
396 LBMLBTRMSourceTransportEntry::LBMLBTRMSourceTransportEntry(const QString & transport) :
397     QTreeWidgetItem(),
398     m_transport(transport),
399     m_data_frames(0),
400     m_data_bytes(0),
401     m_rx_data_frames(0),
402     m_rx_data_bytes(0),
403     m_ncf_frames(0),
404     m_ncf_count(0),
405     m_ncf_bytes(0),
406     m_sm_frames(0),
407     m_sm_bytes(0),
408     m_first_frame_timestamp_valid(false),
409     m_data_sqns(),
410     m_rx_data_sqns(),
411     m_ncf_sqns(),
412     m_sm_sqns()
413 {
414     m_first_frame_timestamp.secs = 0;
415     m_first_frame_timestamp.nsecs = 0;
416     m_last_frame_timestamp.secs = 0;
417     m_last_frame_timestamp.nsecs = 0;
418     setText(Source_AddressTransport_Column, m_transport);
419 }
420
421 LBMLBTRMSourceTransportEntry::~LBMLBTRMSourceTransportEntry(void)
422 {
423     for (LBMLBTRMSQNMapIterator it = m_data_sqns.begin(); it != m_data_sqns.end(); ++it)
424     {
425         delete *it;
426     }
427     m_data_sqns.clear();
428
429     for (LBMLBTRMSQNMapIterator it = m_rx_data_sqns.begin(); it != m_rx_data_sqns.end(); ++it)
430     {
431         delete *it;
432     }
433     m_rx_data_sqns.clear();
434
435     for (LBMLBTRMNCFSQNMapIterator it = m_ncf_sqns.begin(); it != m_ncf_sqns.end(); ++it)
436     {
437         delete *it;
438     }
439     m_ncf_sqns.clear();
440
441     for (LBMLBTRMSQNMapIterator it = m_sm_sqns.begin(); it != m_sm_sqns.end(); ++it)
442     {
443         delete *it;
444     }
445     m_sm_sqns.clear();
446 }
447
448 void LBMLBTRMSourceTransportEntry::processPacket(const packet_info * pinfo, const lbm_lbtrm_tap_info_t * tap_info)
449 {
450     if (m_first_frame_timestamp_valid)
451     {
452         if (nstime_cmp(&(pinfo->abs_ts), &m_first_frame_timestamp) < 0)
453         {
454             nstime_copy(&(m_first_frame_timestamp), &(pinfo->abs_ts));
455         }
456     }
457     else
458     {
459         nstime_copy(&(m_first_frame_timestamp), &(pinfo->abs_ts));
460         m_first_frame_timestamp_valid = true;
461     }
462     if (nstime_cmp(&(pinfo->abs_ts), &m_last_frame_timestamp) > 0)
463     {
464         nstime_copy(&(m_last_frame_timestamp), &(pinfo->abs_ts));
465     }
466     if (tap_info->type == LBTRM_PACKET_TYPE_DATA)
467     {
468         LBMLBTRMSQNEntry * sqn = NULL;
469         LBMLBTRMSQNMapIterator it;
470
471         if (tap_info->retransmission)
472         {
473             m_rx_data_frames++;
474             m_rx_data_bytes += pinfo->fd->pkt_len;
475             it = m_rx_data_sqns.find(tap_info->sqn);
476             if (m_rx_data_sqns.end() == it)
477             {
478                 sqn = new LBMLBTRMSQNEntry(tap_info->sqn);
479                 m_rx_data_sqns.insert(tap_info->sqn, sqn);
480             }
481             else
482             {
483                 sqn = it.value();
484             }
485         }
486         else
487         {
488             m_data_frames++;
489             m_data_bytes += pinfo->fd->pkt_len;
490             it = m_data_sqns.find(tap_info->sqn);
491             if (m_data_sqns.end() == it)
492             {
493                 sqn = new LBMLBTRMSQNEntry(tap_info->sqn);
494                 m_data_sqns.insert(tap_info->sqn, sqn);
495             }
496             else
497             {
498                 sqn = it.value();
499             }
500         }
501         sqn->processFrame(pinfo->num);
502     }
503     else if (tap_info->type == LBTRM_PACKET_TYPE_NCF)
504     {
505         guint16 idx;
506         LBMLBTRMNCFSQNMapIterator it;
507         LBMLBTRMNCFSQNEntry * sqn = NULL;
508
509         m_ncf_frames++;
510         m_ncf_bytes += pinfo->fd->pkt_len;
511         m_ncf_count += (guint64)tap_info->num_sqns;
512         for (idx = 0; idx < tap_info->num_sqns; idx++)
513         {
514             it = m_ncf_sqns.find(tap_info->sqns[idx]);
515             if (m_ncf_sqns.end() == it)
516             {
517                 sqn = new LBMLBTRMNCFSQNEntry(tap_info->sqns[idx]);
518                 m_ncf_sqns.insert(tap_info->sqns[idx], sqn);
519             }
520             else
521             {
522                 sqn = it.value();
523             }
524             sqn->processFrame(tap_info->ncf_reason, pinfo->num);
525         }
526     }
527     else if (tap_info->type == LBTRM_PACKET_TYPE_SM)
528     {
529         LBMLBTRMSQNEntry * sqn = NULL;
530         LBMLBTRMSQNMapIterator it;
531
532         m_sm_frames++;
533         m_sm_bytes += pinfo->fd->pkt_len;
534         it = m_sm_sqns.find(tap_info->sqn);
535         if (m_sm_sqns.end() == it)
536         {
537             sqn = new LBMLBTRMSQNEntry(tap_info->sqn);
538             m_sm_sqns.insert(tap_info->sqn, sqn);
539         }
540         else
541         {
542             sqn = it.value();
543         }
544         sqn->processFrame(pinfo->num);
545     }
546     else
547     {
548         return;
549     }
550     fillItem();
551 }
552
553 void LBMLBTRMSourceTransportEntry::fillItem(void)
554 {
555     nstime_t delta;
556
557     nstime_delta(&delta, &m_last_frame_timestamp, &m_first_frame_timestamp);
558     setText(Source_DataFrames_Column, QString("%1").arg(m_data_frames));
559     setTextAlignment(Source_DataFrames_Column, Qt::AlignRight);
560     setText(Source_DataBytes_Column, QString("%1").arg(m_data_bytes));
561     setTextAlignment(Source_DataBytes_Column, Qt::AlignRight);
562     setText(Source_DataFramesBytes_Column, QString("%1/%2").arg(m_data_frames).arg(m_data_bytes));
563     setTextAlignment(Source_DataFramesBytes_Column, Qt::AlignHCenter);
564     setText(Source_DataRate_Column, format_rate(delta, m_data_bytes));
565     setTextAlignment(Source_DataRate_Column, Qt::AlignRight);
566     setText(Source_RXDataFrames_Column, QString("%1").arg(m_rx_data_frames));
567     setTextAlignment(Source_RXDataFrames_Column, Qt::AlignRight);
568     setText(Source_RXDataBytes_Column, QString("%1").arg(m_rx_data_bytes));
569     setTextAlignment(Source_RXDataBytes_Column, Qt::AlignRight);
570     setText(Source_RXDataFramesBytes_Column, QString("%1/%2").arg(m_rx_data_frames).arg(m_rx_data_bytes));
571     setTextAlignment(Source_RXDataFramesBytes_Column, Qt::AlignHCenter);
572     setText(Source_RXDataRate_Column, format_rate(delta, m_rx_data_bytes));
573     setTextAlignment(Source_RXDataRate_Column, Qt::AlignRight);
574     setText(Source_NCFFrames_Column, QString("%1").arg(m_ncf_frames));
575     setTextAlignment(Source_NCFFrames_Column, Qt::AlignRight);
576     setText(Source_NCFCount_Column, QString("%1").arg(m_ncf_count));
577     setTextAlignment(Source_NCFCount_Column, Qt::AlignRight);
578     setText(Source_NCFBytes_Column, QString("%1").arg(m_ncf_bytes));
579     setTextAlignment(Source_NCFBytes_Column, Qt::AlignRight);
580     setText(Source_NCFFramesBytes_Column, QString("%1/%2").arg(m_ncf_frames).arg(m_ncf_bytes));
581     setTextAlignment(Source_NCFFramesBytes_Column, Qt::AlignHCenter);
582     setText(Source_NCFCountBytes_Column, QString("%1/%2").arg(m_ncf_count).arg(m_ncf_bytes));
583     setTextAlignment(Source_NCFCountBytes_Column, Qt::AlignHCenter);
584     setText(Source_NCFFramesCount_Column, QString("%1/%2").arg(m_ncf_count).arg(m_ncf_count));
585     setTextAlignment(Source_NCFFramesCount_Column, Qt::AlignHCenter);
586     setText(Source_NCFFramesCountBytes_Column, QString("%1/%2/%3").arg(m_ncf_frames).arg(m_ncf_count).arg(m_ncf_bytes));
587     setTextAlignment(Source_NCFFramesCountBytes_Column, Qt::AlignHCenter);
588     setText(Source_NCFRate_Column, format_rate(delta, m_ncf_bytes));
589     setTextAlignment(Source_NCFRate_Column, Qt::AlignRight);
590     setText(Source_SMFrames_Column, QString("%1").arg(m_sm_frames));
591     setTextAlignment(Source_SMFrames_Column, Qt::AlignRight);
592     setText(Source_SMBytes_Column, QString("%1").arg(m_sm_bytes));
593     setTextAlignment(Source_SMBytes_Column, Qt::AlignRight);
594     setText(Source_SMFramesBytes_Column, QString("%1/%2").arg(m_sm_frames).arg(m_sm_bytes));
595     setTextAlignment(Source_SMFramesBytes_Column, Qt::AlignHCenter);
596     setText(Source_SMRate_Column, format_rate(delta, m_sm_bytes));
597     setTextAlignment(Source_SMRate_Column, Qt::AlignRight);
598 }
599
600 typedef QMap<QString, LBMLBTRMSourceTransportEntry *> LBMLBTRMSourceTransportMap;
601 typedef QMap<QString, LBMLBTRMSourceTransportEntry *>::iterator LBMLBTRMSourceTransportMapIterator;
602
603 // A source (address) entry
604 class LBMLBTRMSourceEntry : public QTreeWidgetItem
605 {
606     public:
607         LBMLBTRMSourceEntry(const QString & source_address);
608         virtual ~LBMLBTRMSourceEntry(void);
609         void processPacket(const packet_info * pinfo, const lbm_lbtrm_tap_info_t * tap_info);
610
611     private:
612         void fillItem(void);
613         QString m_address;
614         QString m_transport;
615         guint64 m_data_frames;
616         guint64 m_data_bytes;
617         guint64 m_rx_data_frames;
618         guint64 m_rx_data_bytes;
619         guint64 m_ncf_frames;
620         guint64 m_ncf_count;
621         guint64 m_ncf_bytes;
622         guint64 m_sm_frames;
623         guint64 m_sm_bytes;
624         nstime_t m_first_frame_timestamp;
625         bool m_first_frame_timestamp_valid;
626         nstime_t m_last_frame_timestamp;
627         LBMLBTRMSourceTransportMap m_transports;
628 };
629
630 LBMLBTRMSourceEntry::LBMLBTRMSourceEntry(const QString & source_address) :
631     QTreeWidgetItem(),
632     m_address(source_address),
633     m_data_frames(0),
634     m_data_bytes(0),
635     m_rx_data_frames(0),
636     m_rx_data_bytes(0),
637     m_ncf_frames(0),
638     m_ncf_count(0),
639     m_ncf_bytes(0),
640     m_sm_frames(0),
641     m_sm_bytes(0),
642     m_first_frame_timestamp_valid(false),
643     m_transports()
644 {
645     m_first_frame_timestamp.secs = 0;
646     m_first_frame_timestamp.nsecs = 0;
647     m_last_frame_timestamp.secs = 0;
648     m_last_frame_timestamp.nsecs = 0;
649     setText(Source_AddressTransport_Column, m_address);
650 }
651
652 LBMLBTRMSourceEntry::~LBMLBTRMSourceEntry(void)
653 {
654     for (LBMLBTRMSourceTransportMapIterator it = m_transports.begin(); it != m_transports.end(); ++it)
655     {
656         delete *it;
657     }
658     m_transports.clear();
659 }
660
661 void LBMLBTRMSourceEntry::processPacket(const packet_info * pinfo, const lbm_lbtrm_tap_info_t * tap_info)
662 {
663     LBMLBTRMSourceTransportEntry * transport = NULL;
664     LBMLBTRMSourceTransportMapIterator it;
665
666     if (m_first_frame_timestamp_valid)
667     {
668         if (nstime_cmp(&(pinfo->abs_ts), &m_first_frame_timestamp) < 0)
669         {
670             nstime_copy(&(m_first_frame_timestamp), &(pinfo->abs_ts));
671         }
672     }
673     else
674     {
675         nstime_copy(&(m_first_frame_timestamp), &(pinfo->abs_ts));
676         m_first_frame_timestamp_valid = true;
677     }
678     if (nstime_cmp(&(pinfo->abs_ts), &m_last_frame_timestamp) > 0)
679     {
680         nstime_copy(&(m_last_frame_timestamp), &(pinfo->abs_ts));
681     }
682     if (tap_info->type == LBTRM_PACKET_TYPE_DATA)
683     {
684         if (tap_info->retransmission)
685         {
686             m_rx_data_frames++;
687             m_rx_data_bytes += pinfo->fd->pkt_len;
688         }
689         else
690         {
691             m_data_frames++;
692             m_data_bytes += pinfo->fd->pkt_len;
693         }
694     }
695     else if (tap_info->type == LBTRM_PACKET_TYPE_NCF)
696     {
697         m_ncf_frames++;
698         m_ncf_bytes += pinfo->fd->pkt_len;
699         m_ncf_count += tap_info->num_sqns;
700     }
701     else if (tap_info->type == LBTRM_PACKET_TYPE_SM)
702     {
703         m_sm_frames++;
704         m_sm_bytes += pinfo->fd->pkt_len;
705     }
706
707     it = m_transports.find(tap_info->transport);
708     if (m_transports.end() == it)
709     {
710         transport = new LBMLBTRMSourceTransportEntry(tap_info->transport);
711         m_transports.insert(tap_info->transport, transport);
712         addChild(transport);
713         sortChildren(Source_AddressTransport_Column, Qt::AscendingOrder);
714     }
715     else
716     {
717         transport = it.value();
718     }
719     fillItem();
720     transport->processPacket(pinfo, tap_info);
721 }
722
723 void LBMLBTRMSourceEntry::fillItem(void)
724 {
725     nstime_t delta;
726
727     nstime_delta(&delta, &m_last_frame_timestamp, &m_first_frame_timestamp);
728     setText(Source_DataFrames_Column, QString("%1").arg(m_data_frames));
729     setTextAlignment(Source_DataFrames_Column, Qt::AlignRight);
730     setText(Source_DataBytes_Column, QString("%1").arg(m_data_bytes));
731     setTextAlignment(Source_DataBytes_Column, Qt::AlignRight);
732     setText(Source_DataFramesBytes_Column, QString("%1/%2").arg(m_data_frames).arg(m_data_bytes));
733     setTextAlignment(Source_DataFramesBytes_Column, Qt::AlignHCenter);
734     setText(Source_DataRate_Column, format_rate(delta, m_data_bytes));
735     setTextAlignment(Source_DataRate_Column, Qt::AlignRight);
736     setText(Source_RXDataFrames_Column, QString("%1").arg(m_rx_data_frames));
737     setTextAlignment(Source_RXDataFrames_Column, Qt::AlignRight);
738     setText(Source_RXDataBytes_Column, QString("%1").arg(m_rx_data_bytes));
739     setTextAlignment(Source_RXDataBytes_Column, Qt::AlignRight);
740     setText(Source_RXDataFramesBytes_Column, QString("%1/%2").arg(m_rx_data_frames).arg(m_rx_data_bytes));
741     setTextAlignment(Source_RXDataFramesBytes_Column, Qt::AlignHCenter);
742     setText(Source_RXDataRate_Column, format_rate(delta, m_rx_data_bytes));
743     setTextAlignment(Source_RXDataRate_Column, Qt::AlignRight);
744     setText(Source_NCFFrames_Column, QString("%1").arg(m_ncf_frames));
745     setTextAlignment(Source_NCFFrames_Column, Qt::AlignRight);
746     setText(Source_NCFCount_Column, QString("%1").arg(m_ncf_count));
747     setTextAlignment(Source_NCFCount_Column, Qt::AlignRight);
748     setText(Source_NCFBytes_Column, QString("%1").arg(m_ncf_bytes));
749     setTextAlignment(Source_NCFBytes_Column, Qt::AlignRight);
750     setText(Source_NCFFramesBytes_Column, QString("%1/%2").arg(m_ncf_frames).arg(m_ncf_bytes));
751     setTextAlignment(Source_NCFFramesBytes_Column, Qt::AlignHCenter);
752     setText(Source_NCFCountBytes_Column, QString("%1/%2").arg(m_ncf_count).arg(m_ncf_bytes));
753     setTextAlignment(Source_NCFCountBytes_Column, Qt::AlignHCenter);
754     setText(Source_NCFFramesCount_Column, QString("%1/%2").arg(m_ncf_frames).arg(m_ncf_count));
755     setTextAlignment(Source_NCFFramesCount_Column, Qt::AlignHCenter);
756     setText(Source_NCFFramesCountBytes_Column, QString("%1/%2/%3").arg(m_ncf_frames).arg(m_ncf_count).arg(m_ncf_bytes));
757     setTextAlignment(Source_NCFFramesCountBytes_Column, Qt::AlignHCenter);
758     setText(Source_NCFRate_Column, format_rate(delta, m_ncf_bytes));
759     setTextAlignment(Source_NCFRate_Column, Qt::AlignRight);
760     setText(Source_SMFrames_Column, QString("%1").arg(m_sm_frames));
761     setTextAlignment(Source_SMFrames_Column, Qt::AlignRight);
762     setText(Source_SMBytes_Column, QString("%1").arg(m_sm_bytes));
763     setTextAlignment(Source_SMBytes_Column, Qt::AlignRight);
764     setText(Source_SMFramesBytes_Column, QString("%1/%2").arg(m_sm_frames).arg(m_sm_bytes));
765     setTextAlignment(Source_SMFramesBytes_Column, Qt::AlignRight);
766     setText(Source_SMRate_Column, format_rate(delta, m_sm_bytes));
767     setTextAlignment(Source_SMRate_Column, Qt::AlignRight);
768 }
769
770 typedef QMap<QString, LBMLBTRMSourceEntry *> LBMLBTRMSourceMap;
771 typedef QMap<QString, LBMLBTRMSourceEntry *>::iterator LBMLBTRMSourceMapIterator;
772
773 // A receiver transport entry
774 class LBMLBTRMReceiverTransportEntry : public QTreeWidgetItem
775 {
776         friend class LBMLBTRMTransportDialog;
777
778     public:
779         LBMLBTRMReceiverTransportEntry(const QString & transport);
780         virtual ~LBMLBTRMReceiverTransportEntry(void);
781         void processPacket(const packet_info * pinfo, const lbm_lbtrm_tap_info_t * tap_info);
782
783     private:
784         void fillItem(void);
785         QString m_transport;
786         guint64 m_nak_frames;
787         guint64 m_nak_count;
788         guint64 m_nak_bytes;
789         nstime_t m_first_frame_timestamp;
790         bool m_first_frame_timestamp_valid;
791         nstime_t m_last_frame_timestamp;
792
793     protected:
794         LBMLBTRMSQNMap m_nak_sqns;
795 };
796
797 LBMLBTRMReceiverTransportEntry::LBMLBTRMReceiverTransportEntry(const QString & transport) :
798     QTreeWidgetItem(),
799     m_transport(transport),
800     m_nak_frames(0),
801     m_nak_count(0),
802     m_nak_bytes(0),
803     m_first_frame_timestamp_valid(false),
804     m_nak_sqns()
805 {
806     m_first_frame_timestamp.secs = 0;
807     m_first_frame_timestamp.nsecs = 0;
808     m_last_frame_timestamp.secs = 0;
809     m_last_frame_timestamp.nsecs = 0;
810     setText(Receiver_AddressTransport_Column, m_transport);
811 }
812
813 LBMLBTRMReceiverTransportEntry::~LBMLBTRMReceiverTransportEntry(void)
814 {
815     for (LBMLBTRMSQNMapIterator it = m_nak_sqns.begin(); it != m_nak_sqns.end(); ++it)
816     {
817         delete *it;
818     }
819     m_nak_sqns.clear();
820 }
821
822 void LBMLBTRMReceiverTransportEntry::processPacket(const packet_info * pinfo, const lbm_lbtrm_tap_info_t * tap_info)
823 {
824     if (m_first_frame_timestamp_valid)
825     {
826         if (nstime_cmp(&(pinfo->abs_ts), &m_first_frame_timestamp) < 0)
827         {
828             nstime_copy(&(m_first_frame_timestamp), &(pinfo->abs_ts));
829         }
830     }
831     else
832     {
833         nstime_copy(&(m_first_frame_timestamp), &(pinfo->abs_ts));
834         m_first_frame_timestamp_valid = true;
835     }
836     if (nstime_cmp(&(pinfo->abs_ts), &m_last_frame_timestamp) > 0)
837     {
838         nstime_copy(&(m_last_frame_timestamp), &(pinfo->abs_ts));
839     }
840     if (tap_info->type == LBTRM_PACKET_TYPE_NAK)
841     {
842         guint16 idx;
843         LBMLBTRMSQNEntry * sqn = NULL;
844         LBMLBTRMSQNMapIterator it;
845
846         m_nak_frames++;
847         m_nak_bytes += pinfo->fd->pkt_len;
848         m_nak_count += tap_info->num_sqns;
849         for (idx = 0; idx < tap_info->num_sqns; idx++)
850         {
851             it = m_nak_sqns.find(tap_info->sqns[idx]);
852             if (m_nak_sqns.end() == it)
853             {
854                 sqn = new LBMLBTRMSQNEntry(tap_info->sqns[idx]);
855                 m_nak_sqns.insert(tap_info->sqns[idx], sqn);
856             }
857             else
858             {
859                 sqn = it.value();
860             }
861             sqn->processFrame(pinfo->num);
862         }
863     }
864     else
865     {
866         return;
867     }
868     fillItem();
869 }
870
871 void LBMLBTRMReceiverTransportEntry::fillItem(void)
872 {
873     nstime_t delta;
874
875     nstime_delta(&delta, &m_last_frame_timestamp, &m_first_frame_timestamp);
876     setText(Receiver_NAKFrames_Column, QString("%1").arg(m_nak_frames));
877     setTextAlignment(Receiver_NAKFrames_Column, Qt::AlignRight);
878     setText(Receiver_NAKCount_Column, QString("%1").arg(m_nak_count));
879     setTextAlignment(Receiver_NAKCount_Column, Qt::AlignRight);
880     setText(Receiver_NAKBytes_Column, QString("%1").arg(m_nak_bytes));
881     setTextAlignment(Receiver_NAKBytes_Column, Qt::AlignRight);
882     setText(Receiver_NAKRate_Column, format_rate(delta, m_nak_bytes));
883     setTextAlignment(Receiver_NAKRate_Column, Qt::AlignRight);
884 }
885
886 typedef QMap<QString, LBMLBTRMReceiverTransportEntry *> LBMLBTRMReceiverTransportMap;
887 typedef QMap<QString, LBMLBTRMReceiverTransportEntry *>::iterator LBMLBTRMReceiverTransportMapIterator;
888
889 // A receiver (address) entry
890 class LBMLBTRMReceiverEntry : public QTreeWidgetItem
891 {
892     public:
893         LBMLBTRMReceiverEntry(const QString & receiver_address);
894         virtual ~LBMLBTRMReceiverEntry(void);
895         void processPacket(const packet_info * pinfo, const lbm_lbtrm_tap_info_t * tap_info);
896
897     private:
898         LBMLBTRMReceiverEntry(void);
899         void fillItem(void);
900         QString m_address;
901         QString m_transport;
902         guint64 m_nak_frames;
903         guint64 m_nak_count;
904         guint64 m_nak_bytes;
905         nstime_t m_first_frame_timestamp;
906         bool m_first_frame_timestamp_valid;
907         nstime_t m_last_frame_timestamp;
908         LBMLBTRMReceiverTransportMap m_transports;
909 };
910
911 LBMLBTRMReceiverEntry::LBMLBTRMReceiverEntry(const QString & receiver_address) :
912     QTreeWidgetItem(),
913     m_address(receiver_address),
914     m_nak_frames(0),
915     m_nak_count(0),
916     m_nak_bytes(0),
917     m_first_frame_timestamp_valid(false),
918     m_transports()
919 {
920     m_first_frame_timestamp.secs = 0;
921     m_first_frame_timestamp.nsecs = 0;
922     m_last_frame_timestamp.secs = 0;
923     m_last_frame_timestamp.nsecs = 0;
924     setText(Receiver_AddressTransport_Column, m_address);
925 }
926
927 LBMLBTRMReceiverEntry::~LBMLBTRMReceiverEntry(void)
928 {
929     for (LBMLBTRMReceiverTransportMapIterator it = m_transports.begin(); it != m_transports.end(); ++it)
930     {
931         delete *it;
932     }
933     m_transports.clear();
934 }
935
936 void LBMLBTRMReceiverEntry::processPacket(const packet_info * pinfo, const lbm_lbtrm_tap_info_t * tap_info)
937 {
938     LBMLBTRMReceiverTransportEntry * transport = NULL;
939     LBMLBTRMReceiverTransportMapIterator it;
940
941     if (m_first_frame_timestamp_valid)
942     {
943         if (nstime_cmp(&(pinfo->abs_ts), &m_first_frame_timestamp) < 0)
944         {
945             nstime_copy(&(m_first_frame_timestamp), &(pinfo->abs_ts));
946         }
947     }
948     else
949     {
950         nstime_copy(&(m_first_frame_timestamp), &(pinfo->abs_ts));
951         m_first_frame_timestamp_valid = true;
952     }
953     if (nstime_cmp(&(pinfo->abs_ts), &m_last_frame_timestamp) > 0)
954     {
955         nstime_copy(&(m_last_frame_timestamp), &(pinfo->abs_ts));
956     }
957     if (tap_info->type == LBTRM_PACKET_TYPE_NAK)
958     {
959         m_nak_frames++;
960         m_nak_bytes += pinfo->fd->pkt_len;
961         m_nak_count += tap_info->num_sqns;
962     }
963
964     it = m_transports.find(tap_info->transport);
965     if (m_transports.end() == it)
966     {
967         transport = new LBMLBTRMReceiverTransportEntry(tap_info->transport);
968         m_transports.insert(tap_info->transport, transport);
969         addChild(transport);
970         sortChildren(Receiver_AddressTransport_Column, Qt::AscendingOrder);
971     }
972     else
973     {
974         transport = it.value();
975     }
976     fillItem();
977     transport->processPacket(pinfo, tap_info);
978 }
979
980 void LBMLBTRMReceiverEntry::fillItem(void)
981 {
982     nstime_t delta;
983
984     nstime_delta(&delta, &m_last_frame_timestamp, &m_first_frame_timestamp);
985     setText(Receiver_NAKFrames_Column, QString("%1").arg(m_nak_frames));
986     setTextAlignment(Receiver_NAKFrames_Column, Qt::AlignRight);
987     setText(Receiver_NAKCount_Column, QString("%1").arg(m_nak_count));
988     setTextAlignment(Receiver_NAKCount_Column, Qt::AlignRight);
989     setText(Receiver_NAKBytes_Column, QString("%1").arg(m_nak_bytes));
990     setTextAlignment(Receiver_NAKBytes_Column, Qt::AlignRight);
991     setText(Receiver_NAKRate_Column, format_rate(delta, m_nak_bytes));
992     setTextAlignment(Receiver_NAKRate_Column, Qt::AlignRight);
993 }
994
995 typedef QMap<QString, LBMLBTRMReceiverEntry *> LBMLBTRMReceiverMap;
996 typedef QMap<QString, LBMLBTRMReceiverEntry *>::iterator LBMLBTRMReceiverMapIterator;
997
998 class LBMLBTRMTransportDialogInfo
999 {
1000     public:
1001         LBMLBTRMTransportDialogInfo(void);
1002         ~LBMLBTRMTransportDialogInfo(void);
1003         void setDialog(LBMLBTRMTransportDialog * dialog);
1004         LBMLBTRMTransportDialog * getDialog(void);
1005         void processPacket(const packet_info * pinfo, const lbm_lbtrm_tap_info_t * tap_info);
1006         void clearMaps(void);
1007
1008     private:
1009         LBMLBTRMTransportDialog * m_dialog;
1010         LBMLBTRMSourceMap m_sources;
1011         LBMLBTRMReceiverMap m_receivers;
1012 };
1013
1014 LBMLBTRMTransportDialogInfo::LBMLBTRMTransportDialogInfo(void) :
1015     m_dialog(NULL),
1016     m_sources(),
1017     m_receivers()
1018 {
1019 }
1020
1021 LBMLBTRMTransportDialogInfo::~LBMLBTRMTransportDialogInfo(void)
1022 {
1023     clearMaps();
1024 }
1025
1026 void LBMLBTRMTransportDialogInfo::setDialog(LBMLBTRMTransportDialog * dialog)
1027 {
1028     m_dialog = dialog;
1029 }
1030
1031 LBMLBTRMTransportDialog * LBMLBTRMTransportDialogInfo::getDialog(void)
1032 {
1033     return (m_dialog);
1034 }
1035
1036 void LBMLBTRMTransportDialogInfo::processPacket(const packet_info * pinfo, const lbm_lbtrm_tap_info_t * tap_info)
1037 {
1038     switch (tap_info->type)
1039     {
1040         case LBTRM_PACKET_TYPE_DATA:
1041         case LBTRM_PACKET_TYPE_SM:
1042         case LBTRM_PACKET_TYPE_NCF:
1043             {
1044                 LBMLBTRMSourceEntry * source = NULL;
1045                 LBMLBTRMSourceMapIterator it;
1046                 QString src_address = address_to_qstring(&(pinfo->src));
1047
1048                 it = m_sources.find(src_address);
1049                 if (m_sources.end() == it)
1050                 {
1051                     QTreeWidgetItem * parent = NULL;
1052                     Ui::LBMLBTRMTransportDialog * ui = NULL;
1053
1054                     source = new LBMLBTRMSourceEntry(src_address);
1055                     it = m_sources.insert(src_address, source);
1056                     ui = m_dialog->getUI();
1057                     ui->sources_TreeWidget->addTopLevelItem(source);
1058                     parent = ui->sources_TreeWidget->invisibleRootItem();
1059                     parent->sortChildren(Source_AddressTransport_Column, Qt::AscendingOrder);
1060                     ui->sources_TreeWidget->resizeColumnToContents(Source_AddressTransport_Column);
1061                 }
1062                 else
1063                 {
1064                     source = it.value();
1065                 }
1066                 source->processPacket(pinfo, tap_info);
1067             }
1068             break;
1069         case LBTRM_PACKET_TYPE_NAK:
1070             {
1071                 LBMLBTRMReceiverEntry * receiver = NULL;
1072                 LBMLBTRMReceiverMapIterator it;
1073                 QString src_address = address_to_qstring(&(pinfo->src));
1074
1075                 it = m_receivers.find(src_address);
1076                 if (m_receivers.end() == it)
1077                 {
1078                     QTreeWidgetItem * parent = NULL;
1079                     Ui::LBMLBTRMTransportDialog * ui = NULL;
1080
1081                     receiver = new LBMLBTRMReceiverEntry(src_address);
1082                     it = m_receivers.insert(src_address, receiver);
1083                     ui = m_dialog->getUI();
1084                     ui->receivers_TreeWidget->addTopLevelItem(receiver);
1085                     parent = ui->receivers_TreeWidget->invisibleRootItem();
1086                     parent->sortChildren(Receiver_AddressTransport_Column, Qt::AscendingOrder);
1087                     ui->receivers_TreeWidget->resizeColumnToContents(Receiver_AddressTransport_Column);
1088                 }
1089                 else
1090                 {
1091                     receiver = it.value();
1092                 }
1093                 receiver->processPacket(pinfo, tap_info);
1094             }
1095             break;
1096         default:
1097             break;
1098     }
1099 }
1100
1101 void LBMLBTRMTransportDialogInfo::clearMaps(void)
1102 {
1103     for (LBMLBTRMSourceMapIterator it = m_sources.begin(); it != m_sources.end(); ++it)
1104     {
1105         delete *it;
1106     }
1107     m_sources.clear();
1108
1109     for (LBMLBTRMReceiverMapIterator it = m_receivers.begin(); it != m_receivers.end(); ++it)
1110     {
1111         delete *it;
1112     }
1113     m_receivers.clear();
1114 }
1115
1116 LBMLBTRMTransportDialog::LBMLBTRMTransportDialog(QWidget * parent, capture_file * cfile) :
1117     QDialog(parent),
1118     m_ui(new Ui::LBMLBTRMTransportDialog),
1119     m_dialog_info(NULL),
1120     m_capture_file(cfile),
1121     m_current_source_transport(NULL),
1122     m_current_receiver_transport(NULL),
1123     m_source_context_menu(NULL),
1124     m_source_header(NULL)
1125 {
1126     m_ui->setupUi(this);
1127     m_dialog_info = new LBMLBTRMTransportDialogInfo();
1128
1129     m_ui->tabWidget->setCurrentIndex(0);
1130     m_ui->sources_detail_ComboBox->setCurrentIndex(0);
1131     m_ui->sources_detail_transport_Label->setText(QString(" "));
1132     m_ui->receivers_detail_transport_Label->setText(QString(" "));
1133     m_ui->stackedWidget->setCurrentIndex(0);
1134
1135     m_source_header = m_ui->sources_TreeWidget->header();
1136     m_source_context_menu = new QMenu(m_source_header);
1137
1138     m_source_context_menu->addAction(m_ui->action_SourceAutoResizeColumns);
1139     connect(m_ui->action_SourceAutoResizeColumns, SIGNAL(triggered()), this, SLOT(actionSourceAutoResizeColumns_triggered()));
1140     m_source_context_menu->addSeparator();
1141
1142     m_ui->action_SourceDataFrames->setChecked(true);
1143     m_source_context_menu->addAction(m_ui->action_SourceDataFrames);
1144     connect(m_ui->action_SourceDataFrames, SIGNAL(triggered(bool)), this, SLOT(actionSourceDataFrames_triggered(bool)));
1145     m_ui->action_SourceDataBytes->setChecked(true);
1146     m_source_context_menu->addAction(m_ui->action_SourceDataBytes);
1147     connect(m_ui->action_SourceDataBytes, SIGNAL(triggered(bool)), this, SLOT(actionSourceDataBytes_triggered(bool)));
1148     m_ui->action_SourceDataFramesBytes->setChecked(false);
1149     m_source_context_menu->addAction(m_ui->action_SourceDataFramesBytes);
1150     connect(m_ui->action_SourceDataFramesBytes, SIGNAL(triggered(bool)), this, SLOT(actionSourceDataFramesBytes_triggered(bool)));
1151     m_ui->action_SourceDataRate->setChecked(true);
1152     m_source_context_menu->addAction(m_ui->action_SourceDataRate);
1153     connect(m_ui->action_SourceDataRate, SIGNAL(triggered(bool)), this, SLOT(actionSourceDataRate_triggered(bool)));
1154
1155     m_ui->action_SourceRXDataFrames->setChecked(true);
1156     m_source_context_menu->addAction(m_ui->action_SourceRXDataFrames);
1157     connect(m_ui->action_SourceRXDataFrames, SIGNAL(triggered(bool)), this, SLOT(actionSourceRXDataFrames_triggered(bool)));
1158     m_ui->action_SourceRXDataBytes->setChecked(true);
1159     m_source_context_menu->addAction(m_ui->action_SourceRXDataBytes);
1160     connect(m_ui->action_SourceRXDataBytes, SIGNAL(triggered(bool)), this, SLOT(actionSourceRXDataBytes_triggered(bool)));
1161     m_ui->action_SourceRXDataFramesBytes->setChecked(false);
1162     m_source_context_menu->addAction(m_ui->action_SourceRXDataFramesBytes);
1163     connect(m_ui->action_SourceRXDataFramesBytes, SIGNAL(triggered(bool)), this, SLOT(actionSourceRXDataFramesBytes_triggered(bool)));
1164     m_ui->action_SourceRXDataRate->setChecked(true);
1165     m_source_context_menu->addAction(m_ui->action_SourceRXDataRate);
1166     connect(m_ui->action_SourceRXDataRate, SIGNAL(triggered(bool)), this, SLOT(actionSourceRXDataRate_triggered(bool)));
1167
1168     m_ui->action_SourceNCFFrames->setChecked(true);
1169     m_source_context_menu->addAction(m_ui->action_SourceNCFFrames);
1170     connect(m_ui->action_SourceNCFFrames, SIGNAL(triggered(bool)), this, SLOT(actionSourceNCFFrames_triggered(bool)));
1171     m_ui->action_SourceNCFCount->setChecked(true);
1172     m_source_context_menu->addAction(m_ui->action_SourceNCFCount);
1173     connect(m_ui->action_SourceNCFCount, SIGNAL(triggered(bool)), this, SLOT(actionSourceNCFCount_triggered(bool)));
1174     m_ui->action_SourceNCFBytes->setChecked(true);
1175     m_source_context_menu->addAction(m_ui->action_SourceNCFBytes);
1176     connect(m_ui->action_SourceNCFBytes, SIGNAL(triggered(bool)), this, SLOT(actionSourceNCFBytes_triggered(bool)));
1177     m_ui->action_SourceNCFFramesBytes->setChecked(false);
1178     m_source_context_menu->addAction(m_ui->action_SourceNCFFramesBytes);
1179     connect(m_ui->action_SourceNCFFramesBytes, SIGNAL(triggered(bool)), this, SLOT(actionSourceNCFFramesBytes_triggered(bool)));
1180     m_ui->action_SourceNCFCountBytes->setChecked(false);
1181     m_source_context_menu->addAction(m_ui->action_SourceNCFCountBytes);
1182     connect(m_ui->action_SourceNCFCountBytes, SIGNAL(triggered(bool)), this, SLOT(actionSourceNCFCountBytes_triggered(bool)));
1183     m_ui->action_SourceNCFFramesCount->setChecked(false);
1184     m_source_context_menu->addAction(m_ui->action_SourceNCFFramesCount);
1185     connect(m_ui->action_SourceNCFFramesCount, SIGNAL(triggered(bool)), this, SLOT(actionSourceNCFFramesCount_triggered(bool)));
1186     m_ui->action_SourceNCFFramesCountBytes->setChecked(false);
1187     m_source_context_menu->addAction(m_ui->action_SourceNCFFramesCountBytes);
1188     connect(m_ui->action_SourceNCFFramesCountBytes, SIGNAL(triggered(bool)), this, SLOT(actionSourceNCFFramesCountBytes_triggered(bool)));
1189     m_ui->action_SourceNCFRate->setChecked(true);
1190     m_source_context_menu->addAction(m_ui->action_SourceNCFRate);
1191     connect(m_ui->action_SourceNCFRate, SIGNAL(triggered(bool)), this, SLOT(actionSourceNCFRate_triggered(bool)));
1192
1193     m_ui->action_SourceSMFrames->setChecked(true);
1194     m_source_context_menu->addAction(m_ui->action_SourceSMFrames);
1195     connect(m_ui->action_SourceSMFrames, SIGNAL(triggered(bool)), this, SLOT(actionSourceSMFrames_triggered(bool)));
1196     m_ui->action_SourceSMBytes->setChecked(true);
1197     m_source_context_menu->addAction(m_ui->action_SourceSMBytes);
1198     connect(m_ui->action_SourceSMBytes, SIGNAL(triggered(bool)), this, SLOT(actionSourceSMBytes_triggered(bool)));
1199     m_ui->action_SourceSMFramesBytes->setChecked(false);
1200     m_source_context_menu->addAction(m_ui->action_SourceSMFramesBytes);
1201     connect(m_ui->action_SourceSMFramesBytes, SIGNAL(triggered(bool)), this, SLOT(actionSourceSMFramesBytes_triggered(bool)));
1202     m_ui->action_SourceSMRate->setChecked(true);
1203     m_source_context_menu->addAction(m_ui->action_SourceSMRate);
1204     connect(m_ui->action_SourceSMRate, SIGNAL(triggered(bool)), this, SLOT(actionSourceSMRate_triggered(bool)));
1205
1206     m_source_header->setContextMenuPolicy(Qt::CustomContextMenu);
1207     connect(m_source_header, SIGNAL(customContextMenuRequested(const QPoint &)), this, SLOT(custom_source_context_menuRequested(const QPoint &)));
1208
1209     m_ui->sources_TreeWidget->setColumnHidden(Source_DataFramesBytes_Column, true);
1210     m_ui->sources_TreeWidget->setColumnHidden(Source_RXDataFramesBytes_Column, true);
1211     m_ui->sources_TreeWidget->setColumnHidden(Source_NCFFramesBytes_Column, true);
1212     m_ui->sources_TreeWidget->setColumnHidden(Source_NCFCountBytes_Column, true);
1213     m_ui->sources_TreeWidget->setColumnHidden(Source_NCFFramesCount_Column, true);
1214     m_ui->sources_TreeWidget->setColumnHidden(Source_NCFFramesCountBytes_Column, true);
1215     m_ui->sources_TreeWidget->setColumnHidden(Source_SMFramesBytes_Column, true);
1216
1217     connect(this, SIGNAL(accepted()), this, SLOT(closeDialog()));
1218     connect(this, SIGNAL(rejected()), this, SLOT(closeDialog()));
1219     fillTree();
1220 }
1221
1222 LBMLBTRMTransportDialog::~LBMLBTRMTransportDialog(void)
1223 {
1224     resetSourcesDetail();
1225     resetSources();
1226     resetReceiversDetail();
1227     resetReceivers();
1228     if (m_dialog_info != NULL)
1229     {
1230         delete m_dialog_info;
1231         m_dialog_info = NULL;
1232     }
1233     delete m_source_context_menu;
1234     m_source_context_menu = NULL;
1235     delete m_ui;
1236     m_ui = NULL;
1237     m_capture_file = NULL;
1238 }
1239
1240 void LBMLBTRMTransportDialog::setCaptureFile(capture_file * cfile)
1241 {
1242     if (cfile == NULL) // We only want to know when the file closes.
1243     {
1244         m_capture_file = NULL;
1245         m_ui->displayFilterLineEdit->setEnabled(false);
1246         m_ui->applyFilterButton->setEnabled(false);
1247     }
1248 }
1249
1250 void LBMLBTRMTransportDialog::resetSources(void)
1251 {
1252     while (m_ui->sources_TreeWidget->takeTopLevelItem(0) != NULL)
1253     {}
1254 }
1255
1256 void LBMLBTRMTransportDialog::resetReceivers(void)
1257 {
1258     while (m_ui->receivers_TreeWidget->takeTopLevelItem(0) != NULL)
1259     {}
1260 }
1261
1262 void LBMLBTRMTransportDialog::resetSourcesDetail(void)
1263 {
1264     while (m_ui->sources_detail_sqn_TreeWidget->takeTopLevelItem(0) != NULL)
1265     {}
1266     while (m_ui->sources_detail_ncf_sqn_TreeWidget->takeTopLevelItem(0) != NULL)
1267     {}
1268     m_ui->sources_detail_transport_Label->setText(QString(" "));
1269     m_current_source_transport = NULL;
1270 }
1271
1272 void LBMLBTRMTransportDialog::resetReceiversDetail(void)
1273 {
1274     while (m_ui->receivers_detail_TreeWidget->takeTopLevelItem(0) != NULL)
1275     {}
1276     m_ui->receivers_detail_transport_Label->setText(QString(" "));
1277     m_current_receiver_transport = NULL;
1278 }
1279
1280 void LBMLBTRMTransportDialog::fillTree(void)
1281 {
1282     GString * error_string;
1283
1284     if (m_capture_file == NULL)
1285     {
1286         return;
1287     }
1288     m_dialog_info->setDialog(this);
1289
1290     error_string = register_tap_listener("lbm_lbtrm",
1291         (void *)m_dialog_info,
1292         m_ui->displayFilterLineEdit->text().toUtf8().constData(),
1293         TL_REQUIRES_COLUMNS,
1294         resetTap,
1295         tapPacket,
1296         drawTreeItems);
1297     if (error_string)
1298     {
1299         QMessageBox::critical(this, tr("LBT-RM Statistics failed to attach to tap"),
1300             error_string->str);
1301         g_string_free(error_string, TRUE);
1302         reject();
1303     }
1304
1305     cf_retap_packets(m_capture_file);
1306     drawTreeItems(&m_dialog_info);
1307     remove_tap_listener((void *)m_dialog_info);
1308 }
1309
1310 void LBMLBTRMTransportDialog::resetTap(void * tap_data)
1311 {
1312     LBMLBTRMTransportDialogInfo * info = (LBMLBTRMTransportDialogInfo *) tap_data;
1313     LBMLBTRMTransportDialog * dialog = info->getDialog();
1314     if (dialog == NULL)
1315     {
1316         return;
1317     }
1318     dialog->resetSourcesDetail();
1319     dialog->resetSources();
1320     dialog->resetReceiversDetail();
1321     dialog->resetReceivers();
1322     info->clearMaps();
1323 }
1324
1325 gboolean LBMLBTRMTransportDialog::tapPacket(void * tap_data, packet_info * pinfo, epan_dissect_t *, const void * tap_info)
1326 {
1327     if (pinfo->fd->flags.passed_dfilter == 1)
1328     {
1329         const lbm_lbtrm_tap_info_t * tapinfo = (const lbm_lbtrm_tap_info_t *)tap_info;
1330         LBMLBTRMTransportDialogInfo * info = (LBMLBTRMTransportDialogInfo *)tap_data;
1331
1332         info->processPacket(pinfo, tapinfo);
1333     }
1334     return (TRUE);
1335 }
1336
1337 void LBMLBTRMTransportDialog::drawTreeItems(void *)
1338 {
1339 }
1340
1341 void LBMLBTRMTransportDialog::on_applyFilterButton_clicked(void)
1342 {
1343     fillTree();
1344 }
1345
1346 void LBMLBTRMTransportDialog::closeDialog(void)
1347 {
1348     delete this;
1349 }
1350
1351 void LBMLBTRMTransportDialog::sourcesDetailCurrentChanged(int index)
1352 {
1353     // Index 0: Data
1354     // Index 1: RX data
1355     // Index 2: NCF
1356     // Index 3: SM
1357     switch (index)
1358     {
1359         case 0:
1360         case 1:
1361         case 3:
1362             m_ui->stackedWidget->setCurrentIndex(0);
1363             break;
1364         case 2:
1365             m_ui->stackedWidget->setCurrentIndex(1);
1366             break;
1367         default:
1368             return;
1369     }
1370     sourcesItemClicked(m_current_source_transport, 0);
1371 }
1372
1373 void LBMLBTRMTransportDialog::sourcesItemClicked(QTreeWidgetItem * item, int)
1374 {
1375     LBMLBTRMSourceTransportEntry * transport = dynamic_cast<LBMLBTRMSourceTransportEntry *>(item);
1376
1377     resetSourcesDetail();
1378     if (transport == NULL)
1379     {
1380         // Must be a source item, ignore it?
1381         return;
1382     }
1383     m_current_source_transport = transport;
1384     m_ui->sources_detail_transport_Label->setText(transport->m_transport);
1385     int cur_idx = m_ui->sources_detail_ComboBox->currentIndex();
1386     switch (cur_idx)
1387     {
1388         case 0:
1389             loadSourceDataDetails(transport);
1390             break;
1391         case 1:
1392             loadSourceRXDataDetails(transport);
1393             break;
1394         case 2:
1395             loadSourceNCFDetails(transport);
1396             break;
1397         case 3:
1398             loadSourceSMDetails(transport);
1399             break;
1400         default:
1401             break;
1402     }
1403 }
1404
1405 void LBMLBTRMTransportDialog::loadSourceDataDetails(LBMLBTRMSourceTransportEntry * transport)
1406 {
1407     for (LBMLBTRMSQNMapIterator it = transport->m_data_sqns.begin(); it != transport->m_data_sqns.end(); ++it)
1408     {
1409         LBMLBTRMSQNEntry * sqn = it.value();
1410         m_ui->sources_detail_sqn_TreeWidget->addTopLevelItem(sqn);
1411     }
1412 }
1413
1414 void LBMLBTRMTransportDialog::loadSourceRXDataDetails(LBMLBTRMSourceTransportEntry * transport)
1415 {
1416     for (LBMLBTRMSQNMapIterator it = transport->m_rx_data_sqns.begin(); it != transport->m_rx_data_sqns.end(); ++it)
1417     {
1418         LBMLBTRMSQNEntry * sqn = it.value();
1419         m_ui->sources_detail_sqn_TreeWidget->addTopLevelItem(sqn);
1420     }
1421 }
1422
1423 void LBMLBTRMTransportDialog::loadSourceNCFDetails(LBMLBTRMSourceTransportEntry * transport)
1424 {
1425     for (LBMLBTRMNCFSQNMapIterator it = transport->m_ncf_sqns.begin(); it != transport->m_ncf_sqns.end(); ++it)
1426     {
1427         LBMLBTRMNCFSQNEntry * sqn = it.value();
1428         m_ui->sources_detail_ncf_sqn_TreeWidget->addTopLevelItem(sqn);
1429     }
1430 }
1431
1432 void LBMLBTRMTransportDialog::loadSourceSMDetails(LBMLBTRMSourceTransportEntry * transport)
1433 {
1434     for (LBMLBTRMSQNMapIterator it = transport->m_sm_sqns.begin(); it != transport->m_sm_sqns.end(); ++it)
1435     {
1436         LBMLBTRMSQNEntry * sqn = it.value();
1437         m_ui->sources_detail_sqn_TreeWidget->addTopLevelItem(sqn);
1438     }
1439 }
1440
1441 void LBMLBTRMTransportDialog::receiversItemClicked(QTreeWidgetItem * item, int)
1442 {
1443     LBMLBTRMReceiverTransportEntry * transport = dynamic_cast<LBMLBTRMReceiverTransportEntry *>(item);
1444
1445     resetReceiversDetail();
1446     if (transport == NULL)
1447     {
1448         // Must be a receiver item, ignore it?
1449         return;
1450     }
1451     m_current_receiver_transport = transport;
1452     m_ui->receivers_detail_transport_Label->setText(transport->m_transport);
1453     loadReceiverNAKDetails(transport);
1454 }
1455
1456 void LBMLBTRMTransportDialog::loadReceiverNAKDetails(LBMLBTRMReceiverTransportEntry * transport)
1457 {
1458     for (LBMLBTRMSQNMapIterator it = transport->m_nak_sqns.begin(); it != transport->m_nak_sqns.end(); ++it)
1459     {
1460         LBMLBTRMSQNEntry * sqn = it.value();
1461         m_ui->receivers_detail_TreeWidget->addTopLevelItem(sqn);
1462     }
1463 }
1464
1465 void LBMLBTRMTransportDialog::sourcesDetailItemDoubleClicked(QTreeWidgetItem * item, int)
1466 {
1467     LBMLBTRMFrameEntry * frame = dynamic_cast<LBMLBTRMFrameEntry *>(item);
1468     if (frame == NULL)
1469     {
1470         // Must have double-clicked on something other than an expanded frame entry
1471         return;
1472     }
1473     emit goToPacket((int)frame->getFrame());
1474 }
1475
1476 void LBMLBTRMTransportDialog::receiversDetailItemDoubleClicked(QTreeWidgetItem * item, int)
1477 {
1478     LBMLBTRMFrameEntry * frame = dynamic_cast<LBMLBTRMFrameEntry *>(item);
1479     if (frame == NULL)
1480     {
1481         // Must have double-clicked on something other than an expanded frame entry
1482         return;
1483     }
1484     emit goToPacket((int)frame->getFrame());
1485 }
1486
1487 void LBMLBTRMTransportDialog::custom_source_context_menuRequested(const QPoint & pos)
1488 {
1489     m_source_context_menu->exec(m_source_header->mapToGlobal(pos));
1490 }
1491
1492 void LBMLBTRMTransportDialog::actionSourceDataFrames_triggered(bool checked)
1493 {
1494     m_ui->sources_TreeWidget->setColumnHidden(Source_DataFrames_Column, !checked);
1495 }
1496
1497 void LBMLBTRMTransportDialog::actionSourceDataBytes_triggered(bool checked)
1498 {
1499     m_ui->sources_TreeWidget->setColumnHidden(Source_DataBytes_Column, !checked);
1500 }
1501
1502 void LBMLBTRMTransportDialog::actionSourceDataFramesBytes_triggered(bool checked)
1503 {
1504     m_ui->sources_TreeWidget->setColumnHidden(Source_DataFramesBytes_Column, !checked);
1505 }
1506
1507 void LBMLBTRMTransportDialog::actionSourceDataRate_triggered(bool checked)
1508 {
1509     m_ui->sources_TreeWidget->setColumnHidden(Source_DataRate_Column, !checked);
1510 }
1511
1512 void LBMLBTRMTransportDialog::actionSourceRXDataFrames_triggered(bool checked)
1513 {
1514     m_ui->sources_TreeWidget->setColumnHidden(Source_RXDataFrames_Column, !checked);
1515 }
1516
1517 void LBMLBTRMTransportDialog::actionSourceRXDataBytes_triggered(bool checked)
1518 {
1519     m_ui->sources_TreeWidget->setColumnHidden(Source_RXDataBytes_Column, !checked);
1520 }
1521
1522 void LBMLBTRMTransportDialog::actionSourceRXDataFramesBytes_triggered(bool checked)
1523 {
1524     m_ui->sources_TreeWidget->setColumnHidden(Source_RXDataFramesBytes_Column, !checked);
1525 }
1526
1527 void LBMLBTRMTransportDialog::actionSourceRXDataRate_triggered(bool checked)
1528 {
1529     m_ui->sources_TreeWidget->setColumnHidden(Source_RXDataRate_Column, !checked);
1530 }
1531
1532 void LBMLBTRMTransportDialog::actionSourceNCFFrames_triggered(bool checked)
1533 {
1534     m_ui->sources_TreeWidget->setColumnHidden(Source_NCFFrames_Column, !checked);
1535 }
1536
1537 void LBMLBTRMTransportDialog::actionSourceNCFCount_triggered(bool checked)
1538 {
1539     m_ui->sources_TreeWidget->setColumnHidden(Source_NCFCount_Column, !checked);
1540 }
1541
1542 void LBMLBTRMTransportDialog::actionSourceNCFBytes_triggered(bool checked)
1543 {
1544     m_ui->sources_TreeWidget->setColumnHidden(Source_NCFFrames_Column, !checked);
1545 }
1546
1547 void LBMLBTRMTransportDialog::actionSourceNCFFramesBytes_triggered(bool checked)
1548 {
1549     m_ui->sources_TreeWidget->setColumnHidden(Source_NCFFramesBytes_Column, !checked);
1550 }
1551
1552 void LBMLBTRMTransportDialog::actionSourceNCFCountBytes_triggered(bool checked)
1553 {
1554     m_ui->sources_TreeWidget->setColumnHidden(Source_NCFCountBytes_Column, !checked);
1555 }
1556
1557 void LBMLBTRMTransportDialog::actionSourceNCFFramesCount_triggered(bool checked)
1558 {
1559     m_ui->sources_TreeWidget->setColumnHidden(Source_NCFFramesCount_Column, !checked);
1560 }
1561
1562 void LBMLBTRMTransportDialog::actionSourceNCFFramesCountBytes_triggered(bool checked)
1563 {
1564     m_ui->sources_TreeWidget->setColumnHidden(Source_NCFFramesCountBytes_Column, !checked);
1565 }
1566
1567 void LBMLBTRMTransportDialog::actionSourceNCFRate_triggered(bool checked)
1568 {
1569     m_ui->sources_TreeWidget->setColumnHidden(Source_NCFRate_Column, !checked);
1570 }
1571
1572 void LBMLBTRMTransportDialog::actionSourceSMFrames_triggered(bool checked)
1573 {
1574     m_ui->sources_TreeWidget->setColumnHidden(Source_SMFrames_Column, !checked);
1575 }
1576
1577 void LBMLBTRMTransportDialog::actionSourceSMBytes_triggered(bool checked)
1578 {
1579     m_ui->sources_TreeWidget->setColumnHidden(Source_SMBytes_Column, !checked);
1580 }
1581
1582 void LBMLBTRMTransportDialog::actionSourceSMFramesBytes_triggered(bool checked)
1583 {
1584     m_ui->sources_TreeWidget->setColumnHidden(Source_SMFramesBytes_Column, !checked);
1585 }
1586
1587 void LBMLBTRMTransportDialog::actionSourceSMRate_triggered(bool checked)
1588 {
1589     m_ui->sources_TreeWidget->setColumnHidden(Source_SMRate_Column, !checked);
1590 }
1591
1592 void LBMLBTRMTransportDialog::actionSourceAutoResizeColumns_triggered(void)
1593 {
1594     m_ui->sources_TreeWidget->resizeColumnToContents(Source_AddressTransport_Column);
1595     m_ui->sources_TreeWidget->resizeColumnToContents(Source_DataFrames_Column);
1596     m_ui->sources_TreeWidget->resizeColumnToContents(Source_DataBytes_Column);
1597     m_ui->sources_TreeWidget->resizeColumnToContents(Source_DataFramesBytes_Column);
1598     m_ui->sources_TreeWidget->resizeColumnToContents(Source_DataRate_Column);
1599     m_ui->sources_TreeWidget->resizeColumnToContents(Source_RXDataFrames_Column);
1600     m_ui->sources_TreeWidget->resizeColumnToContents(Source_RXDataBytes_Column);
1601     m_ui->sources_TreeWidget->resizeColumnToContents(Source_RXDataFramesBytes_Column);
1602     m_ui->sources_TreeWidget->resizeColumnToContents(Source_RXDataRate_Column);
1603     m_ui->sources_TreeWidget->resizeColumnToContents(Source_NCFFrames_Column);
1604     m_ui->sources_TreeWidget->resizeColumnToContents(Source_NCFCount_Column);
1605     m_ui->sources_TreeWidget->resizeColumnToContents(Source_NCFBytes_Column);
1606     m_ui->sources_TreeWidget->resizeColumnToContents(Source_NCFFramesBytes_Column);
1607     m_ui->sources_TreeWidget->resizeColumnToContents(Source_NCFCountBytes_Column);
1608     m_ui->sources_TreeWidget->resizeColumnToContents(Source_NCFFramesCount_Column);
1609     m_ui->sources_TreeWidget->resizeColumnToContents(Source_NCFFramesCountBytes_Column);
1610     m_ui->sources_TreeWidget->resizeColumnToContents(Source_NCFRate_Column);
1611     m_ui->sources_TreeWidget->resizeColumnToContents(Source_SMFrames_Column);
1612     m_ui->sources_TreeWidget->resizeColumnToContents(Source_SMBytes_Column);
1613     m_ui->sources_TreeWidget->resizeColumnToContents(Source_SMFramesBytes_Column);
1614     m_ui->sources_TreeWidget->resizeColumnToContents(Source_SMRate_Column);
1615 }
1616
1617 /*
1618  * Editor modelines  -  http://www.wireshark.org/tools/modelines.html
1619  *
1620  * Local variables:
1621  * c-basic-offset: 4
1622  * tab-width: 8
1623  * indent-tabs-mode: nil
1624  * End:
1625  *
1626  * vi: set shiftwidth=4 tabstop=8 expandtab:
1627  * :indentSize=4:tabSize=8:noTabs=true:
1628  */