/** @file * * Wireshark - Network traffic analyzer * By Gerald Combs * Copyright 1998 Gerald Combs * * SPDX-License-Identifier: GPL-2.0-or-later */ #include "config.h" #include #include #include #include TrafficTypesRowData::TrafficTypesRowData(int protocol, QString name) : _protocol(protocol), _name(name), _checked(false) {} int TrafficTypesRowData::protocol() const { return _protocol; } QString TrafficTypesRowData::name() const { return _name; } bool TrafficTypesRowData::checked() const { return _checked; } void TrafficTypesRowData::setChecked(bool checked) { _checked = checked; } static bool iterateProtocols(const void *key, void *value, void *userdata) { QList * protocols = (QList *)userdata; register_ct_t* ct = (register_ct_t*)value; const QString title = (const gchar*)key; int proto_id = get_conversation_proto_id(ct); TrafficTypesRowData entry(proto_id, title); protocols->append(entry); return FALSE; } TrafficTypesModel::TrafficTypesModel(GList ** recentList, QObject *parent) : QAbstractListModel(parent), _recentList(recentList) { conversation_table_iterate_tables(iterateProtocols, &_allTaps); std::sort(_allTaps.begin(), _allTaps.end(), [](TrafficTypesRowData a, TrafficTypesRowData b) { return a.name().compare(b.name(), Qt::CaseInsensitive) < 0; }); QList _protocols; for (GList * endTab = *_recentList; endTab; endTab = endTab->next) { int protoId = proto_get_id_by_short_name((const char *)endTab->data); if (protoId > -1 && ! _protocols.contains(protoId)) _protocols.append(protoId); } if (_protocols.isEmpty()) { QStringList protoNames = QStringList() << "eth" << "ip" << "ipv6" << "tcp" << "udp"; foreach(QString name, protoNames) _protocols << proto_get_id_by_filter_name(name.toStdString().c_str()); } for(int cnt = 0; cnt < _allTaps.count(); cnt++) { _allTaps[cnt].setChecked(false); if (_protocols.contains(_allTaps[cnt].protocol())) _allTaps[cnt].setChecked(true); } } int TrafficTypesModel::rowCount(const QModelIndex &) const { return (int) _allTaps.count(); } int TrafficTypesModel::columnCount(const QModelIndex &) const { return TrafficTypesModel::COL_NUM; } QVariant TrafficTypesModel::data(const QModelIndex &idx, int role) const { if (!idx.isValid()) return QVariant(); TrafficTypesRowData data = _allTaps[idx.row()]; if (role == Qt::DisplayRole) { switch(idx.column()) { case(TrafficTypesModel::COL_NAME): return data.name(); case(TrafficTypesModel::COL_PROTOCOL): return data.protocol(); } } else if (role == Qt::CheckStateRole && idx.column() == TrafficTypesModel::COL_CHECKED) { return data.checked() ? Qt::Checked : Qt::Unchecked; } else if (role == TrafficTypesModel::TRAFFIC_PROTOCOL) { return data.protocol(); } else if (role == TrafficTypesModel::TRAFFIC_IS_CHECKED) { return (bool)data.checked(); } return QVariant(); } QVariant TrafficTypesModel::headerData(int section, Qt::Orientation orientation, int role) const { if (section < 0 || role != Qt::DisplayRole || orientation != Qt::Horizontal) return QVariant(); if (section == TrafficTypesModel::COL_NAME) return tr("Protocol"); return QVariant(); } Qt::ItemFlags TrafficTypesModel::flags (const QModelIndex & idx) const { Qt::ItemFlags defaultFlags = QAbstractListModel::flags(idx); if (idx.isValid()) return defaultFlags | Qt::ItemIsUserCheckable; return defaultFlags; } bool TrafficTypesModel::setData(const QModelIndex &idx, const QVariant &value, int role) { if(!idx.isValid() || role != Qt::CheckStateRole) return false; if (_allTaps.count() <= idx.row()) return false; _allTaps[idx.row()].setChecked(value.toInt() == Qt::Checked); QList selected; prefs_clear_string_list(*_recentList); *_recentList = NULL; for (int cnt = 0; cnt < _allTaps.count(); cnt++) { if (_allTaps[cnt].checked()) { int protoId = _allTaps[cnt].protocol(); selected.append(protoId); char *title = g_strdup(proto_get_protocol_short_name(find_protocol_by_id(protoId))); *_recentList = g_list_append(*_recentList, title); } } emit protocolsChanged(selected); emit dataChanged(idx, idx); return true; } void TrafficTypesModel::selectProtocols(QList protocols) { beginResetModel(); for (int cnt = 0; cnt < _allTaps.count(); cnt++) { _allTaps[cnt].setChecked(false); if (protocols.contains(_allTaps[cnt].protocol())) _allTaps[cnt].setChecked(true); } endResetModel(); } TrafficListSortModel::TrafficListSortModel(QObject * parent) : QSortFilterProxyModel(parent) {} bool TrafficListSortModel::lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const { if (source_left.isValid() && source_left.column() == TrafficTypesModel::COL_NAME) { QString valA = source_left.data().toString(); QString valB = source_right.data().toString(); return valA.compare(valB, Qt::CaseInsensitive) <= 0; } return QSortFilterProxyModel::lessThan(source_left, source_right); } void TrafficListSortModel::setFilter(QString filter) { if ( filter.compare(_filter) != 0 ) { _filter = filter; invalidateFilter(); } } bool TrafficListSortModel::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const { if (sourceModel() && _filter.length() > 0) { QModelIndex idx = sourceModel()->index(source_row, TrafficTypesModel::COL_NAME); if (idx.isValid()) { QString name = idx.data().toString(); if (name.contains(_filter, Qt::CaseInsensitive)) return true; return false; } } return QSortFilterProxyModel::filterAcceptsRow(source_row, source_parent); } TrafficTypesList::TrafficTypesList(QWidget *parent) : QTreeView(parent) { _name = QString(); _model = nullptr; _sortModel = nullptr; setAlternatingRowColors(true); setRootIsDecorated(false); } void TrafficTypesList::setProtocolInfo(QString name, GList ** recentList) { _name = name; _sortModel = new TrafficListSortModel(this); _model = new TrafficTypesModel(recentList, this); _sortModel->setSourceModel(_model); setModel(_sortModel); setSortingEnabled(true); sortByColumn(TrafficTypesModel::COL_NAME, Qt::AscendingOrder); connect(_model, &TrafficTypesModel::protocolsChanged, this, &TrafficTypesList::protocolsChanged); resizeColumnToContents(0); resizeColumnToContents(1); } void TrafficTypesList::selectProtocols(QList protocols) { if (_model) { _model->selectProtocols(protocols); emit clearFilterList(); } } QList TrafficTypesList::protocols(bool onlySelected) const { QList entries; for (int cnt = 0; cnt < _model->rowCount(); cnt++) { QModelIndex idx = _model->index(cnt, TrafficTypesModel::COL_CHECKED); int protoId = _model->data(idx, TrafficTypesModel::TRAFFIC_PROTOCOL).toInt(); if (protoId > 0 && ! entries.contains(protoId)) { if (!onlySelected || _model->data(idx, TrafficTypesModel::TRAFFIC_IS_CHECKED).toBool()) entries.append(protoId); } } return entries; } void TrafficTypesList::filterList(QString filter) { _sortModel->setFilter(filter); }