wireshark/ui/qt/models/astringlist_list_model.cpp

306 lines
8.1 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 static_cast<int>(display_data_.count());
}
int AStringListListModel::columnCount(const QModelIndex &parent) const
{
if (rowCount(parent) == 0)
return 0;
return static_cast<int>(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 leftD = leftData.toFloat();
float rightD = rightData.toFloat();
return leftD < rightD;
}
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 (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
if (! a.canConvert<QString>() || ! b.canConvert<QString>())
#else
if (! a.canConvert(QVariant::String) || ! b.canConvert(QVariant::String))
#endif
return false;
return a.toString().contains(b.toString(), cs);
}
static bool AStartsWithB(const QVariant &a, const QVariant &b, Qt::CaseSensitivity cs)
{
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
if (! a.canConvert<QString>() || ! b.canConvert<QString>())
#else
if (! a.canConvert(QVariant::String) || ! b.canConvert(QVariant::String))
#endif
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::setColumnsToFilter(QList<int> columns)
{
bool hasBeenAdded = false;
foreach (int column, columns) {
if (column < columnCount() && ! columnsToFilter_.contains(column)) {
columnsToFilter_.append(column);
hasBeenAdded = true;
}
}
if (hasBeenAdded)
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 (role == Qt::ForegroundRole && urls_.contains(index.column())
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
&& result.canConvert<QBrush>())
#else
&& result.canConvert(QVariant::Brush))
#endif
{
QBrush selected = result.value<QBrush>();
selected.setColor(ColorUtils::themeLinkBrush().color());
return selected;
}
return result;
}