summaryrefslogtreecommitdiff
path: root/ui/qt/voip_calls_info_model.cpp
diff options
context:
space:
mode:
authorPeter Wu <peter@lekensteyn.nl>2017-02-13 01:36:58 +0100
committerPeter Wu <peter@lekensteyn.nl>2017-03-24 23:02:30 +0000
commitb4bc6c72c79fa121753cf94ae179ea73f1e911dd (patch)
treec07058dcabd11590f7e56f25e35aa4ffae45fa97 /ui/qt/voip_calls_info_model.cpp
parentbff74696df796fca83df72fc7cec7cb917ebb205 (diff)
downloadwireshark-b4bc6c72c79fa121753cf94ae179ea73f1e911dd.tar.gz
Qt: refactor Voip Calls Dialog into Model/View
Functional improvements: - "Time of day" option is now propagated to the CSV/YAML export. - The sorting order is preserved in the CSV/YAML export. Other changes: - Convert column name identifiers to enum. - CSV output will now always be quoted (previously numbers like packet count were not quoted, but since CSV has no numeric type it should be OK to add quotes). Side-effect of model design decision. - Instead of clearing the widgets and re-adding all calls, now it will add new calls to the model. Not tested with a live capture, if the column data can change, maybe a dataChanged signal is needed. Due to this patch, it should be easier to add a filter for finding calls easier (e.g. by From, IP, etc.). Note: extra QList is used in the model to ensure a O(1) lookup of calls (rather than O(n) for GQueue). Change-Id: Ie08462aae038d9c3daf1cc7a152b948724689017 Reviewed-on: https://code.wireshark.org/review/20084 Petri-Dish: Peter Wu <peter@lekensteyn.nl> Tested-by: Petri Dish Buildbot <buildbot-no-reply@wireshark.org> Reviewed-by: Peter Wu <peter@lekensteyn.nl>
Diffstat (limited to 'ui/qt/voip_calls_info_model.cpp')
-rw-r--r--ui/qt/voip_calls_info_model.cpp246
1 files changed, 246 insertions, 0 deletions
diff --git a/ui/qt/voip_calls_info_model.cpp b/ui/qt/voip_calls_info_model.cpp
new file mode 100644
index 0000000000..144829411d
--- /dev/null
+++ b/ui/qt/voip_calls_info_model.cpp
@@ -0,0 +1,246 @@
+/* voip_calls_info_model.cpp
+ *
+ * Wireshark - Network traffic analyzer
+ * By Gerald Combs <gerald@wireshark.org>
+ * Copyright 1998 Gerald Combs
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "voip_calls_info_model.h"
+#include <wsutil/utf8_entities.h>
+#include "qt_ui_utils.h"
+
+#include <QDateTime>
+
+VoipCallsInfoModel::VoipCallsInfoModel(QObject *parent) :
+ QAbstractTableModel(parent),
+ mTimeOfDay_(false)
+{
+}
+
+voip_calls_info_t *VoipCallsInfoModel::indexToCallInfo(const QModelIndex &index)
+{
+ return VariantPointer<voip_calls_info_t>::asPtr(index.data(Qt::UserRole));
+}
+
+QVariant VoipCallsInfoModel::data(const QModelIndex &index, int role) const
+{
+ if (!index.isValid()) {
+ return QVariant();
+ }
+
+ // call_info will be non-NULL since the index is valid
+ voip_calls_info_t *call_info = static_cast<voip_calls_info_t *>(callinfos_[index.row()]);
+
+ if (role == Qt::UserRole) {
+ return VariantPointer<voip_calls_info_t>::asQVariant(call_info);
+ }
+
+ if (role != Qt::DisplayRole) {
+ return QVariant();
+ }
+
+ switch ((Column) index.column()) {
+ case StartTime:
+ return timeData(&(call_info->start_fd->abs_ts), &(call_info->start_rel_ts));
+ case StopTime:
+ return timeData(&(call_info->stop_fd->abs_ts), &(call_info->stop_rel_ts));
+ case InitialSpeaker:
+ return address_to_display_qstring(&(call_info->initial_speaker));
+ case From:
+ return call_info->from_identity;
+ case To:
+ return call_info->to_identity;
+ case Protocol:
+ return ((call_info->protocol == VOIP_COMMON) && call_info->protocol_name) ?
+ call_info->protocol_name : voip_protocol_name[call_info->protocol];
+ case Duration:
+ {
+ guint callDuration = nstime_to_sec(&(call_info->stop_fd->abs_ts)) - nstime_to_sec(&(call_info->start_fd->abs_ts));
+ return QString("%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'));
+ }
+ case Packets:
+ return call_info->npackets;
+ case State:
+ return QString(voip_call_state_name[call_info->call_state]);
+ case Comments:
+ /* Add comments based on the protocol */
+ switch (call_info->protocol) {
+ case VOIP_ISUP:
+ {
+ isup_calls_info_t *isup_info = (isup_calls_info_t *)call_info->prot_info;
+ return QString("%1-%2 %3 %4-%5")
+ .arg(isup_info->ni)
+ .arg(isup_info->opc)
+ .arg(UTF8_RIGHTWARDS_ARROW)
+ .arg(isup_info->ni)
+ .arg(isup_info->dpc);
+ }
+ break;
+ case VOIP_H323:
+ {
+ h323_calls_info_t *h323_info = (h323_calls_info_t *)call_info->prot_info;
+ gboolean flag = FALSE;
+ static const QString on_str = tr("On");
+ static const QString off_str = tr("Off");
+ if (call_info->call_state == VOIP_CALL_SETUP) {
+ flag = h323_info->is_faststart_Setup;
+ } else {
+ if ((h323_info->is_faststart_Setup) && (h323_info->is_faststart_Proc)) {
+ flag = TRUE;
+ }
+ }
+ return tr("Tunneling: %1 Fast Start: %2")
+ .arg(h323_info->is_h245Tunneling ? on_str : off_str)
+ .arg(flag ? on_str : off_str);
+ }
+ break;
+ case VOIP_COMMON:
+ default:
+ return call_info->call_comment;
+ }
+ case ColumnCount:
+ g_assert_not_reached();
+ }
+ return QVariant();
+}
+
+QVariant VoipCallsInfoModel::headerData(int section, Qt::Orientation orientation, int role) const
+{
+ if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
+ switch ((Column) section) {
+ case StartTime:
+ return tr("Start Time");
+ case StopTime:
+ return tr("Stop Time");
+ case InitialSpeaker:
+ return tr("Initial Speaker");
+ case From:
+ return tr("From");
+ case To:
+ return tr("To");
+ case Protocol:
+ return tr("Protocol");
+ case Duration:
+ return tr("Duration");
+ case Packets:
+ return tr("Packets");
+ case State:
+ return tr("State");
+ case Comments:
+ return tr("Comments");
+ case ColumnCount:
+ g_assert_not_reached();
+ }
+ }
+ return QVariant();
+}
+
+int VoipCallsInfoModel::rowCount(const QModelIndex &parent) const
+{
+ // there are no children
+ if (parent.isValid()) {
+ return 0;
+ }
+
+ return callinfos_.size();
+}
+
+int VoipCallsInfoModel::columnCount(const QModelIndex &parent) const
+{
+ // there are no children
+ if (parent.isValid()) {
+ return 0;
+ }
+
+ return ColumnCount;
+}
+
+QVariant VoipCallsInfoModel::timeData(nstime_t *abs_ts, nstime_t *rel_ts) const
+{
+ if (mTimeOfDay_) {
+ return QDateTime::fromTime_t(nstime_to_sec(abs_ts)).toTimeSpec(Qt::LocalTime).toString("yyyy-MM-dd hh:mm:ss");
+ } else {
+ // XXX Pull digit count from capture file precision
+ return QString::number(nstime_to_sec(rel_ts), 'f', 6);
+ }
+}
+
+void VoipCallsInfoModel::setTimeOfDay(bool timeOfDay)
+{
+ mTimeOfDay_ = timeOfDay;
+ if (rowCount() > 0) {
+ // Update both the start and stop column in all rows.
+ emit dataChanged(index(0, StartTime), index(rowCount() - 1, StopTime));
+ }
+}
+
+void VoipCallsInfoModel::updateCalls(GQueue *callsinfos)
+{
+ if (callsinfos) {
+ GList *cur_call = g_queue_peek_nth_link(callsinfos, rowCount());
+ guint extra = g_list_length(cur_call);
+ if (extra > 0) {
+ beginInsertRows(QModelIndex(), rowCount(), rowCount() + extra - 1);
+ while (cur_call && cur_call->data) {
+ voip_calls_info_t *call_info = (voip_calls_info_t*) cur_call->data;
+ callinfos_.push_back(call_info);
+ cur_call = g_list_next(cur_call);
+ }
+ endInsertRows();
+ }
+ }
+}
+
+
+// Proxy model that allows columns to be sorted.
+VoipCallsInfoSortedModel::VoipCallsInfoSortedModel(QObject *parent) :
+ QSortFilterProxyModel(parent)
+{
+}
+
+bool VoipCallsInfoSortedModel::lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const
+{
+ voip_calls_info_t *a = VoipCallsInfoModel::indexToCallInfo(source_left);
+ voip_calls_info_t *b = VoipCallsInfoModel::indexToCallInfo(source_right);
+
+ if (a && b) {
+ switch (source_left.column()) {
+ case VoipCallsInfoModel::StartTime:
+ return nstime_cmp(&(a->start_rel_ts), &(b->start_rel_ts)) < 0;
+ case VoipCallsInfoModel::StopTime:
+ return nstime_cmp(&(a->stop_rel_ts), &(b->stop_rel_ts)) < 0;
+ case VoipCallsInfoModel::InitialSpeaker:
+ return cmp_address(&(a->initial_speaker), &(b->initial_speaker)) < 0;
+ }
+ }
+
+ // fallback to string cmp on other fields
+ return QSortFilterProxyModel::lessThan(source_left, source_right);
+}
+
+/*
+ * Editor modelines
+ *
+ * Local Variables:
+ * c-basic-offset: 4
+ * tab-width: 8
+ * indent-tabs-mode: nil
+ * End:
+ *
+ * ex: set shiftwidth=4 tabstop=8 expandtab:
+ * :indentSize=4:tabSize=8:noTabs=true:
+ */