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
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>
18 VoipCallsInfoModel::VoipCallsInfoModel(QObject
*parent
) :
19 QAbstractTableModel(parent
),
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()) {
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
) {
46 switch ((Column
) index
.column()) {
48 return timeData(&(call_info
->start_fd
->abs_ts
), &(call_info
->start_rel_ts
));
50 return timeData(&(call_info
->stop_fd
->abs_ts
), &(call_info
->stop_rel_ts
));
52 return address_to_display_qstring(&(call_info
->initial_speaker
));
54 return QString::fromUtf8(call_info
->from_identity
);
56 return QString::fromUtf8(call_info
->to_identity
);
58 return ((call_info
->protocol
== VOIP_COMMON
) && call_info
->protocol_name
) ?
59 call_info
->protocol_name
: voip_protocol_name
[call_info
->protocol
];
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'));
66 return call_info
->npackets
;
68 return QString(voip_call_state_name
[call_info
->call_state
]);
70 /* Add comments based on the protocol */
71 switch (call_info
->protocol
) {
74 isup_calls_info_t
*isup_info
= (isup_calls_info_t
*)call_info
->prot_info
;
75 return QStringLiteral("%1-%2 %3 %4-%5")
78 .arg(UTF8_RIGHTWARDS_ARROW
)
85 h323_calls_info_t
*h323_info
= (h323_calls_info_t
*)call_info
->prot_info
;
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
;
92 if ((h323_info
->is_faststart_Setup
) && (h323_info
->is_faststart_Proc
)) {
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
);
103 return QString::fromUtf8(call_info
->call_comment
);
106 ws_assert_not_reached();
111 QVariant
VoipCallsInfoModel::headerData(int section
, Qt::Orientation orientation
, int role
) const
113 if (orientation
== Qt::Horizontal
&& role
== Qt::DisplayRole
) {
114 switch ((Column
) section
) {
116 return tr("Start Time");
118 return tr("Stop Time");
120 return tr("Initial Speaker");
126 return tr("Protocol");
128 return tr("Duration");
130 return tr("Packets");
134 return tr("Comments");
136 ws_assert_not_reached();
142 int VoipCallsInfoModel::rowCount(const QModelIndex
&parent
) const
144 // there are no children
145 if (parent
.isValid()) {
149 return static_cast<int>(callinfos_
.size());
152 int VoipCallsInfoModel::columnCount(const QModelIndex
&parent
) const
154 // there are no children
155 if (parent
.isValid()) {
162 QVariant
VoipCallsInfoModel::timeData(nstime_t
*abs_ts
, nstime_t
*rel_ts
) const
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");
168 return QDateTime::fromMSecsSinceEpoch(nstime_to_msec(abs_ts
), Qt::LocalTime
).toString("yyyy-MM-dd hh:mm:ss");
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
190 void VoipCallsInfoModel::updateCalls(GQueue
*callsinfos
)
193 qsizetype calls
= callinfos_
.count();
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
);
209 cur_call
= g_queue_peek_nth_link(callsinfos
, rowCount());
210 unsigned extra
= g_list_length(cur_call
);
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
);
223 void VoipCallsInfoModel::removeAllCalls()
225 beginRemoveRows(QModelIndex(), 0, rowCount() - 1);
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
);
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
);