update epan/dissectors/pidl/drsuapi/drsuapi.idl from samba
[wireshark-sm.git] / ui / qt / models / voip_calls_info_model.cpp
blobc4e4b72877ff6cf246c761ca78a5cbc59e6f2eee
1 /* voip_calls_info_model.cpp
3 * Wireshark - Network traffic analyzer
4 * By Gerald Combs <gerald@wireshark.org>
5 * Copyright 1998 Gerald Combs
7 * SPDX-License-Identifier: GPL-2.0-or-later
8 */
10 #include "voip_calls_info_model.h"
11 #include <wsutil/utf8_entities.h>
12 #include <wsutil/ws_assert.h>
13 #include <ui/qt/utils/qt_ui_utils.h>
15 #include <QDateTime>
16 #include <QTimeZone>
18 VoipCallsInfoModel::VoipCallsInfoModel(QObject *parent) :
19 QAbstractTableModel(parent),
20 mTimeOfDay_(false)
24 voip_calls_info_t *VoipCallsInfoModel::indexToCallInfo(const QModelIndex &index)
26 return VariantPointer<voip_calls_info_t>::asPtr(index.data(Qt::UserRole));
29 QVariant VoipCallsInfoModel::data(const QModelIndex &index, int role) const
31 if (!index.isValid()) {
32 return QVariant();
35 // call_info will be non-NULL since the index is valid
36 voip_calls_info_t *call_info = static_cast<voip_calls_info_t *>(callinfos_[index.row()]);
38 if (role == Qt::UserRole) {
39 return VariantPointer<voip_calls_info_t>::asQVariant(call_info);
42 if (role != Qt::DisplayRole) {
43 return QVariant();
46 switch ((Column) index.column()) {
47 case StartTime:
48 return timeData(&(call_info->start_fd->abs_ts), &(call_info->start_rel_ts));
49 case StopTime:
50 return timeData(&(call_info->stop_fd->abs_ts), &(call_info->stop_rel_ts));
51 case InitialSpeaker:
52 return address_to_display_qstring(&(call_info->initial_speaker));
53 case From:
54 return QString::fromUtf8(call_info->from_identity);
55 case To:
56 return QString::fromUtf8(call_info->to_identity);
57 case Protocol:
58 return ((call_info->protocol == VOIP_COMMON) && call_info->protocol_name) ?
59 call_info->protocol_name : voip_protocol_name[call_info->protocol];
60 case Duration:
62 unsigned callDuration = nstime_to_sec(&(call_info->stop_fd->abs_ts)) - nstime_to_sec(&(call_info->start_fd->abs_ts));
63 return QStringLiteral("%1:%2:%3").arg(callDuration / 3600, 2, 10, QChar('0')).arg((callDuration % 3600) / 60, 2, 10, QChar('0')).arg(callDuration % 60, 2, 10, QChar('0'));
65 case Packets:
66 return call_info->npackets;
67 case State:
68 return QString(voip_call_state_name[call_info->call_state]);
69 case Comments:
70 /* Add comments based on the protocol */
71 switch (call_info->protocol) {
72 case VOIP_ISUP:
74 isup_calls_info_t *isup_info = (isup_calls_info_t *)call_info->prot_info;
75 return QStringLiteral("%1-%2 %3 %4-%5")
76 .arg(isup_info->ni)
77 .arg(isup_info->opc)
78 .arg(UTF8_RIGHTWARDS_ARROW)
79 .arg(isup_info->ni)
80 .arg(isup_info->dpc);
82 break;
83 case VOIP_H323:
85 h323_calls_info_t *h323_info = (h323_calls_info_t *)call_info->prot_info;
86 bool flag = false;
87 static const QString on_str = tr("On");
88 static const QString off_str = tr("Off");
89 if (call_info->call_state == VOIP_CALL_SETUP) {
90 flag = h323_info->is_faststart_Setup;
91 } else {
92 if ((h323_info->is_faststart_Setup) && (h323_info->is_faststart_Proc)) {
93 flag = true;
96 return tr("Tunneling: %1 Fast Start: %2")
97 .arg(h323_info->is_h245Tunneling ? on_str : off_str)
98 .arg(flag ? on_str : off_str);
100 break;
101 case VOIP_COMMON:
102 default:
103 return QString::fromUtf8(call_info->call_comment);
105 case ColumnCount:
106 ws_assert_not_reached();
108 return QVariant();
111 QVariant VoipCallsInfoModel::headerData(int section, Qt::Orientation orientation, int role) const
113 if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
114 switch ((Column) section) {
115 case StartTime:
116 return tr("Start Time");
117 case StopTime:
118 return tr("Stop Time");
119 case InitialSpeaker:
120 return tr("Initial Speaker");
121 case From:
122 return tr("From");
123 case To:
124 return tr("To");
125 case Protocol:
126 return tr("Protocol");
127 case Duration:
128 return tr("Duration");
129 case Packets:
130 return tr("Packets");
131 case State:
132 return tr("State");
133 case Comments:
134 return tr("Comments");
135 case ColumnCount:
136 ws_assert_not_reached();
139 return QVariant();
142 int VoipCallsInfoModel::rowCount(const QModelIndex &parent) const
144 // there are no children
145 if (parent.isValid()) {
146 return 0;
149 return static_cast<int>(callinfos_.size());
152 int VoipCallsInfoModel::columnCount(const QModelIndex &parent) const
154 // there are no children
155 if (parent.isValid()) {
156 return 0;
159 return ColumnCount;
162 QVariant VoipCallsInfoModel::timeData(nstime_t *abs_ts, nstime_t *rel_ts) const
164 if (mTimeOfDay_) {
165 #if QT_VERSION >= QT_VERSION_CHECK(6, 5, 0)
166 return QDateTime::fromMSecsSinceEpoch(nstime_to_msec(abs_ts), QTimeZone::LocalTime).toString("yyyy-MM-dd hh:mm:ss");
167 #else
168 return QDateTime::fromMSecsSinceEpoch(nstime_to_msec(abs_ts), Qt::LocalTime).toString("yyyy-MM-dd hh:mm:ss");
169 #endif
170 } else {
171 // XXX Pull digit count from capture file precision
172 return QString::number(nstime_to_sec(rel_ts), 'f', 6);
176 void VoipCallsInfoModel::setTimeOfDay(bool timeOfDay)
178 mTimeOfDay_ = timeOfDay;
179 if (rowCount() > 0) {
180 // Update both the start and stop column in all rows.
181 emit dataChanged(index(0, StartTime), index(rowCount() - 1, StopTime));
185 bool VoipCallsInfoModel::timeOfDay() const
187 return mTimeOfDay_;
190 void VoipCallsInfoModel::updateCalls(GQueue *callsinfos)
192 if (callsinfos) {
193 qsizetype calls = callinfos_.count();
194 int cnt = 0;
195 GList *cur_call;
197 // Iterate new callsinfos and replace data in mode if required
198 cur_call = g_queue_peek_nth_link(callsinfos, 0);
199 while (cur_call && (cnt < calls)) {
200 if (callinfos_.at(cnt) != cur_call->data) {
201 // Data changed, use it
202 callinfos_.replace(cnt, cur_call->data);
204 cur_call = gxx_list_next(cur_call);
205 cnt++;
208 // Add new rows
209 cur_call = g_queue_peek_nth_link(callsinfos, rowCount());
210 unsigned extra = g_list_length(cur_call);
211 if (extra > 0) {
212 beginInsertRows(QModelIndex(), rowCount(), rowCount() + extra - 1);
213 while (cur_call && cur_call->data) {
214 voip_calls_info_t *call_info = gxx_list_data(voip_calls_info_t*, cur_call);
215 callinfos_.push_back(call_info);
216 cur_call = gxx_list_next(cur_call);
218 endInsertRows();
223 void VoipCallsInfoModel::removeAllCalls()
225 beginRemoveRows(QModelIndex(), 0, rowCount() - 1);
226 callinfos_.clear();
227 endRemoveRows();
230 // Proxy model that allows columns to be sorted.
231 VoipCallsInfoSortedModel::VoipCallsInfoSortedModel(QObject *parent) :
232 QSortFilterProxyModel(parent)
236 bool VoipCallsInfoSortedModel::lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const
238 voip_calls_info_t *a = VoipCallsInfoModel::indexToCallInfo(source_left);
239 voip_calls_info_t *b = VoipCallsInfoModel::indexToCallInfo(source_right);
241 if (a && b) {
242 switch (source_left.column()) {
243 case VoipCallsInfoModel::StartTime:
244 return nstime_cmp(&(a->start_rel_ts), &(b->start_rel_ts)) < 0;
245 case VoipCallsInfoModel::StopTime:
246 return nstime_cmp(&(a->stop_rel_ts), &(b->stop_rel_ts)) < 0;
247 case VoipCallsInfoModel::InitialSpeaker:
248 return cmp_address(&(a->initial_speaker), &(b->initial_speaker)) < 0;
252 // fallback to string cmp on other fields
253 return QSortFilterProxyModel::lessThan(source_left, source_right);