![Roland Knall](/assets/img/avatar_default.png)
This is a refactoring/redesign of the "Resolved Addresses" dialog, allowing for sorting/filtering and searching within the addresses and ports. Change-Id: I5071e92ff699323b6c93fc533eeaf92e0db334de Reviewed-on: https://code.wireshark.org/review/34398 Reviewed-by: Roland Knall <rknall@gmail.com> Petri-Dish: Roland Knall <rknall@gmail.com> Tested-by: Petri Dish Buildbot Reviewed-by: Anders Broman <a.broman58@gmail.com>
299 lines
7.8 KiB
C++
299 lines
7.8 KiB
C++
/* astringlist_list_model.cpp
|
|
*
|
|
* Wireshark - Network traffic analyzer
|
|
* By Gerald Combs <gerald@wireshark.org>
|
|
* Copyright 1998 Gerald Combs
|
|
*
|
|
* SPDX-License-Identifier: GPL-2.0-or-later
|
|
*/
|
|
|
|
#include <QSortFilterProxyModel>
|
|
#include <QStringList>
|
|
#include <QPalette>
|
|
#include <QApplication>
|
|
#include <QBrush>
|
|
|
|
#include <ui/qt/models/astringlist_list_model.h>
|
|
|
|
#include <ui/qt/utils/color_utils.h>
|
|
|
|
AStringListListModel::AStringListListModel(QObject * parent):
|
|
QAbstractTableModel(parent)
|
|
{}
|
|
|
|
AStringListListModel::~AStringListListModel() { display_data_.clear(); }
|
|
|
|
void AStringListListModel::appendRow(const QStringList & display_strings, const QString & row_tooltip, const QModelIndex &parent)
|
|
{
|
|
QStringList columns = headerColumns();
|
|
if ( display_strings.count() != columns.count() )
|
|
return;
|
|
|
|
emit beginInsertRows(parent, rowCount(), rowCount());
|
|
display_data_ << display_strings;
|
|
tooltip_data_ << row_tooltip;
|
|
emit endInsertRows();
|
|
}
|
|
|
|
int AStringListListModel::rowCount(const QModelIndex &) const
|
|
{
|
|
return display_data_.count();
|
|
}
|
|
|
|
int AStringListListModel::columnCount(const QModelIndex &parent) const
|
|
{
|
|
if ( rowCount(parent) == 0 )
|
|
return 0;
|
|
|
|
return headerColumns().count();
|
|
}
|
|
|
|
QVariant AStringListListModel::headerData(int section, Qt::Orientation orientation, int role) const
|
|
{
|
|
if ( orientation == Qt::Vertical )
|
|
return QVariant();
|
|
|
|
QStringList columns = headerColumns();
|
|
if ( role == Qt::DisplayRole && section < columns.count() )
|
|
return QVariant::fromValue(columns[section]);
|
|
|
|
return QVariant();
|
|
}
|
|
|
|
QVariant AStringListListModel::data(const QModelIndex &index, int role) const
|
|
{
|
|
if ( ! index.isValid() || index.row() >= rowCount() )
|
|
return QVariant();
|
|
|
|
if ( role == Qt::DisplayRole )
|
|
{
|
|
QStringList data = display_data_.at(index.row());
|
|
|
|
if ( index.column() < columnCount() )
|
|
return QVariant::fromValue(data.at(index.column()));
|
|
}
|
|
else if ( role == Qt::ToolTipRole )
|
|
{
|
|
QString tooltip = tooltip_data_.at(index.row());
|
|
if (!tooltip.isEmpty()) {
|
|
return tooltip;
|
|
}
|
|
}
|
|
|
|
return QVariant();
|
|
}
|
|
|
|
AStringListListSortFilterProxyModel::AStringListListSortFilterProxyModel(QObject * parent)
|
|
: QSortFilterProxyModel(parent)
|
|
{
|
|
filter_ = QString();
|
|
types_[-1] = FilterByContains;
|
|
}
|
|
|
|
bool AStringListListSortFilterProxyModel::lessThan(const QModelIndex &left, const QModelIndex &right) const
|
|
{
|
|
QString leftData = left.data().toString();
|
|
QString rightData = right.data().toString();
|
|
|
|
if ( numericColumns_.contains(left.column()) || numericColumns_.contains(right.column() ) )
|
|
{
|
|
float left = leftData.toFloat();
|
|
float right = rightData.toFloat();
|
|
|
|
return left < right;
|
|
}
|
|
|
|
return leftData.compare(rightData, sortCaseSensitivity()) < 0;
|
|
}
|
|
|
|
void AStringListListSortFilterProxyModel::setFilter(const QString & filter)
|
|
{
|
|
filter_ = filter;
|
|
invalidateFilter();
|
|
}
|
|
|
|
static bool AContainsB(const QVariant &a, const QVariant &b, Qt::CaseSensitivity cs)
|
|
{
|
|
if ( ! a.canConvert(QVariant::String) || ! b.canConvert(QVariant::String) )
|
|
return false;
|
|
return a.toString().contains(b.toString(), cs);
|
|
}
|
|
|
|
static bool AStartsWithB(const QVariant &a, const QVariant &b, Qt::CaseSensitivity cs)
|
|
{
|
|
if ( ! a.canConvert(QVariant::String) || ! b.canConvert(QVariant::String) )
|
|
return false;
|
|
return a.toString().startsWith(b.toString(), cs);
|
|
}
|
|
|
|
static bool AIsEquivalentToB(const QVariant &a, const QVariant &b, Qt::CaseSensitivity)
|
|
{
|
|
return a == b;
|
|
}
|
|
|
|
bool AStringListListSortFilterProxyModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const
|
|
{
|
|
if ( columnsToFilter_.count() == 0 )
|
|
return true;
|
|
|
|
foreach(int column, columnsToFilter_)
|
|
{
|
|
if ( column >= columnCount() )
|
|
continue;
|
|
|
|
QModelIndex chkIdx = sourceModel()->index(sourceRow, column, sourceParent);
|
|
QString dataString = chkIdx.data().toString();
|
|
|
|
/* Default is filter by string a contains string b */
|
|
bool (*compareFunc)(const QVariant&, const QVariant&, Qt::CaseSensitivity) = AContainsB;
|
|
if ( types_.keys().contains(column) )
|
|
{
|
|
switch (types_.value(column, FilterByContains))
|
|
{
|
|
case FilterByStart:
|
|
compareFunc = AStartsWithB;
|
|
break;
|
|
case FilterByEquivalent:
|
|
compareFunc = AIsEquivalentToB;
|
|
break;
|
|
case FilterNone:
|
|
return true;
|
|
break;
|
|
default:
|
|
compareFunc = AContainsB;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if ( compareFunc(dataString, filter_, filterCaseSensitivity()) )
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
void AStringListListSortFilterProxyModel::setFilterType(AStringListListFilterType type, int column)
|
|
{
|
|
if ( column >= -1 && column < columnCount() )
|
|
{
|
|
if ( ! types_.keys().contains(column) )
|
|
{
|
|
types_.insert(column, type);
|
|
invalidateFilter();
|
|
}
|
|
else if ( types_.keys().contains(column) && type != types_[column] )
|
|
{
|
|
types_[column] = type;
|
|
invalidateFilter();
|
|
}
|
|
}
|
|
}
|
|
|
|
void AStringListListSortFilterProxyModel::setColumnToFilter(int column)
|
|
{
|
|
if ( column < columnCount() && ! columnsToFilter_.contains(column) )
|
|
{
|
|
columnsToFilter_.append(column);
|
|
invalidateFilter();
|
|
}
|
|
}
|
|
|
|
void AStringListListSortFilterProxyModel::clearColumnsToFilter()
|
|
{
|
|
columnsToFilter_.clear();
|
|
invalidateFilter();
|
|
}
|
|
|
|
void AStringListListSortFilterProxyModel::clearHiddenColumns()
|
|
{
|
|
hiddenColumns_.clear();
|
|
invalidateFilter();
|
|
}
|
|
|
|
void AStringListListSortFilterProxyModel::setColumnToHide(int col)
|
|
{
|
|
if ( ! hiddenColumns_.contains(col) && col > -1 && sourceModel() && sourceModel()->columnCount() > col )
|
|
{
|
|
hiddenColumns_ << col;
|
|
invalidateFilter();
|
|
}
|
|
}
|
|
|
|
bool AStringListListSortFilterProxyModel::filterAcceptsColumn(int sourceColumn, const QModelIndex &sourceParent) const
|
|
{
|
|
QModelIndex realIndex = sourceModel()->index(0, sourceColumn, sourceParent);
|
|
|
|
if ( ! realIndex.isValid() )
|
|
return false;
|
|
|
|
if ( hiddenColumns_.contains(sourceColumn) )
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
void AStringListListSortFilterProxyModel::clearNumericColumns()
|
|
{
|
|
numericColumns_.clear();
|
|
invalidateFilter();
|
|
}
|
|
|
|
void AStringListListSortFilterProxyModel::setColumnAsNumeric(int col)
|
|
{
|
|
if ( ! numericColumns_.contains(col) && col > -1 && sourceModel() && sourceModel()->columnCount() > col )
|
|
{
|
|
numericColumns_ << col;
|
|
invalidateFilter();
|
|
}
|
|
}
|
|
|
|
AStringListListUrlProxyModel::AStringListListUrlProxyModel(QObject * parent):
|
|
QIdentityProxyModel(parent)
|
|
{}
|
|
|
|
void AStringListListUrlProxyModel::setUrlColumn(int column)
|
|
{
|
|
if ( column < columnCount() && ! urls_.contains(column) )
|
|
urls_ << column;
|
|
}
|
|
|
|
bool AStringListListUrlProxyModel::isUrlColumn(int column) const
|
|
{
|
|
return urls_.contains(column);
|
|
}
|
|
|
|
QVariant AStringListListUrlProxyModel::data(const QModelIndex &index, int role) const
|
|
{
|
|
QVariant result = QIdentityProxyModel::data(index, role);
|
|
|
|
if ( urls_.contains(index.column()) )
|
|
{
|
|
if ( role == Qt::ForegroundRole )
|
|
{
|
|
if ( result.canConvert(QVariant::Brush) )
|
|
{
|
|
QBrush selected = result.value<QBrush>();
|
|
selected.setColor(ColorUtils::themeLinkBrush().color());
|
|
return selected;
|
|
}
|
|
} else if ( role == Qt::TextColorRole ) {
|
|
return QApplication::palette().link().color();
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
/*
|
|
* 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:
|
|
*/
|