wireshark/ui/qt/models/interface_sort_filter_model...

384 lines
9.9 KiB
C++

/* interface_sort_filter_model.cpp
* Proxy model for the display of interface data for the interface tree
*
* Wireshark - Network traffic analyzer
* By Gerald Combs <gerald@wireshark.org>
* Copyright 1998 Gerald Combs
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#include <ui/qt/models/interface_tree_model.h>
#include <ui/qt/models/interface_tree_cache_model.h>
#include <ui/qt/models/interface_sort_filter_model.h>
#include <glib.h>
#include <epan/prefs.h>
#include <ui/preference_utils.h>
#include <ui/qt/utils/qt_ui_utils.h>
#include "main_application.h"
#include <QAbstractItemModel>
InterfaceSortFilterModel::InterfaceSortFilterModel(QObject *parent) :
QSortFilterProxyModel(parent)
{
resetAllFilter();
}
void InterfaceSortFilterModel::resetAllFilter()
{
_filterHidden = true;
_filterTypes = true;
_invertTypeFilter = false;
_storeOnChange = false;
#ifdef HAVE_PCAP_REMOTE
_remoteDisplay = true;
#endif
/* Adding all columns, to have a default setting */
for (int col = 0; col < IFTREE_COL_MAX; col++)
_columns.append((InterfaceTreeColumns)col);
invalidateFilter();
invalidate();
}
void InterfaceSortFilterModel::setStoreOnChange(bool storeOnChange)
{
_storeOnChange = storeOnChange;
if (storeOnChange)
{
connect(mainApp, &MainApplication::preferencesChanged, this, &InterfaceSortFilterModel::resetPreferenceData);
resetPreferenceData();
}
}
void InterfaceSortFilterModel::setFilterHidden(bool filter)
{
_filterHidden = filter;
invalidate();
}
#ifdef HAVE_PCAP_REMOTE
void InterfaceSortFilterModel::setRemoteDisplay(bool remoteDisplay)
{
_remoteDisplay = remoteDisplay;
invalidate();
}
bool InterfaceSortFilterModel::remoteDisplay()
{
return _remoteDisplay;
}
void InterfaceSortFilterModel::toggleRemoteDisplay()
{
_remoteDisplay = ! _remoteDisplay;
if (_storeOnChange)
{
prefs.gui_interfaces_remote_display = ! _remoteDisplay;
prefs_main_write();
}
invalidateFilter();
invalidate();
}
bool InterfaceSortFilterModel::remoteInterfacesExist()
{
bool exist = false;
if (sourceModel()->rowCount() == 0)
return exist;
for (int idx = 0; idx < sourceModel()->rowCount() && ! exist; idx++)
exist = ((InterfaceTreeModel *)sourceModel())->isRemote(idx);
return exist;
}
#endif
void InterfaceSortFilterModel::setFilterByType(bool filter, bool invert)
{
_filterTypes = filter;
_invertTypeFilter = invert;
invalidate();
}
void InterfaceSortFilterModel::resetPreferenceData()
{
displayHiddenTypes.clear();
QString stored_prefs(prefs.gui_interfaces_hide_types);
if (stored_prefs.length() > 0)
{
QStringList ifTypesStored = stored_prefs.split(',');
QStringList::const_iterator it = ifTypesStored.constBegin();
while (it != ifTypesStored.constEnd())
{
int i_val = (*it).toInt();
if (! displayHiddenTypes.contains(i_val))
displayHiddenTypes.append(i_val);
++it;
}
}
#if 0
// Disabled until bug 13354 is fixed
_filterHidden = ! prefs.gui_interfaces_show_hidden;
#endif
#ifdef HAVE_PCAP_REMOTE
_remoteDisplay = prefs.gui_interfaces_remote_display;
#endif
invalidate();
}
bool InterfaceSortFilterModel::filterHidden() const
{
return _filterHidden;
}
void InterfaceSortFilterModel::toggleFilterHidden()
{
_filterHidden = ! _filterHidden;
if (_storeOnChange)
{
prefs.gui_interfaces_show_hidden = ! _filterHidden;
prefs_main_write();
}
invalidateFilter();
invalidate();
}
bool InterfaceSortFilterModel::filterByType() const
{
return _filterTypes;
}
int InterfaceSortFilterModel::interfacesHidden()
{
#ifdef HAVE_LIBPCAP
if (! global_capture_opts.all_ifaces)
return 0;
#endif
return sourceModel()->rowCount() - rowCount();
}
QList<int> InterfaceSortFilterModel::typesDisplayed()
{
QList<int> shownTypes;
if (sourceModel()->rowCount() == 0)
return shownTypes;
for (int idx = 0; idx < sourceModel()->rowCount(); idx++)
{
int type = ((InterfaceTreeModel *)sourceModel())->getColumnContent(idx, IFTREE_COL_TYPE).toInt();
bool hidden = ((InterfaceTreeModel *)sourceModel())->getColumnContent(idx, IFTREE_COL_HIDDEN).toBool();
if (! hidden)
{
if (! shownTypes.contains(type))
shownTypes.append(type);
}
}
return shownTypes;
}
void InterfaceSortFilterModel::setInterfaceTypeVisible(int ifType, bool visible)
{
if (visible && displayHiddenTypes.contains(ifType))
displayHiddenTypes.removeAll(ifType);
else if (! visible && ! displayHiddenTypes.contains(ifType))
displayHiddenTypes.append(ifType);
else
/* Nothing should have changed */
return;
if (_storeOnChange)
{
QString new_pref;
QList<int>::const_iterator it = displayHiddenTypes.constBegin();
while (it != displayHiddenTypes.constEnd())
{
new_pref.append(QString("%1,").arg(*it));
++it;
}
if (new_pref.length() > 0)
new_pref = new_pref.left(new_pref.length() - 1);
prefs.gui_interfaces_hide_types = qstring_strdup(new_pref);
prefs_main_write();
}
invalidateFilter();
invalidate();
}
void InterfaceSortFilterModel::toggleTypeVisibility(int ifType)
{
bool checked = isInterfaceTypeShown(ifType);
setInterfaceTypeVisible(ifType, checked ? false : true);
}
bool InterfaceSortFilterModel::isInterfaceTypeShown(int ifType) const
{
bool result = false;
if (displayHiddenTypes.size() == 0)
result = true;
else if (! displayHiddenTypes.contains(ifType))
result = true;
return ((_invertTypeFilter && ! result) || (! _invertTypeFilter && result) );
}
bool InterfaceSortFilterModel::filterAcceptsRow(int sourceRow, const QModelIndex & sourceParent) const
{
QModelIndex realIndex = sourceModel()->index(sourceRow, 0, sourceParent);
if (! realIndex.isValid())
return false;
#ifdef HAVE_LIBPCAP
int idx = realIndex.row();
/* No data loaded, we do not display anything */
if (sourceModel()->rowCount() == 0)
return false;
int type = -1;
bool hidden = false;
if (dynamic_cast<InterfaceTreeCacheModel*>(sourceModel()) != 0)
{
type = ((InterfaceTreeCacheModel *)sourceModel())->getColumnContent(idx, IFTREE_COL_TYPE).toInt();
hidden = ((InterfaceTreeCacheModel *)sourceModel())->getColumnContent(idx, IFTREE_COL_HIDDEN, Qt::UserRole).toBool();
}
else if (dynamic_cast<InterfaceTreeModel*>(sourceModel()) != 0)
{
type = ((InterfaceTreeModel *)sourceModel())->getColumnContent(idx, IFTREE_COL_TYPE).toInt();
hidden = ((InterfaceTreeModel *)sourceModel())->getColumnContent(idx, IFTREE_COL_HIDDEN, Qt::UserRole).toBool();
}
else
return false;
if (hidden && _filterHidden)
return false;
if (_filterTypes && ! isInterfaceTypeShown(type))
{
#ifdef HAVE_PCAP_REMOTE
/* Remote interfaces have the if type IF_WIRED, therefore would be filtered, if not explicitly checked here */
if (type != IF_WIRED || ! ((InterfaceTreeModel *)sourceModel())->isRemote(idx))
#endif
return false;
}
#ifdef HAVE_PCAP_REMOTE
if (((InterfaceTreeModel *)sourceModel())->isRemote(idx))
{
if (! _remoteDisplay)
return false;
}
#endif
#endif
return true;
}
bool InterfaceSortFilterModel::filterAcceptsColumn(int sourceColumn, const QModelIndex & sourceParent) const
{
QModelIndex realIndex = sourceModel()->index(0, sourceColumn, sourceParent);
if (! realIndex.isValid())
return false;
if (! _columns.contains((InterfaceTreeColumns)sourceColumn))
return false;
return true;
}
void InterfaceSortFilterModel::setColumns(QList<InterfaceTreeColumns> columns)
{
_columns.clear();
_columns.append(columns);
}
int InterfaceSortFilterModel::mapSourceToColumn(InterfaceTreeColumns mdlIndex)
{
if (! _columns.contains(mdlIndex))
return -1;
return static_cast<int>(_columns.indexOf(mdlIndex, 0));
}
QModelIndex InterfaceSortFilterModel::mapToSource(const QModelIndex &proxyIndex) const
{
if (! proxyIndex.isValid())
return QModelIndex();
if (! sourceModel())
return QModelIndex();
QModelIndex baseIndex = QSortFilterProxyModel::mapToSource(proxyIndex);
QModelIndex newIndex = sourceModel()->index(baseIndex.row(), _columns.at(proxyIndex.column()));
return newIndex;
}
QModelIndex InterfaceSortFilterModel::mapFromSource(const QModelIndex &sourceIndex) const
{
if (! sourceIndex.isValid())
return QModelIndex();
else if (! _columns.contains((InterfaceTreeColumns) sourceIndex.column()) )
return QModelIndex();
QModelIndex newIndex = QSortFilterProxyModel::mapFromSource(sourceIndex);
return index(newIndex.row(), static_cast<int>(_columns.indexOf((InterfaceTreeColumns) sourceIndex.column())));
}
QString InterfaceSortFilterModel::interfaceError()
{
QString result;
InterfaceTreeModel * sourceModel = dynamic_cast<InterfaceTreeModel *>(this->sourceModel());
if (sourceModel != NULL)
result = sourceModel->interfaceError();
if (result.size() == 0 && rowCount() == 0)
result = tr("No interfaces to be displayed. %1 interfaces hidden.").arg(interfacesHidden());
return result;
}
bool InterfaceSortFilterModel::lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const
{
bool leftActive = source_left.sibling(source_left.row(), InterfaceTreeColumns::IFTREE_COL_ACTIVE).data(Qt::UserRole).toBool();
bool rightActive = source_right.sibling(source_right.row(), InterfaceTreeColumns::IFTREE_COL_ACTIVE).data(Qt::UserRole).toBool();
if (rightActive && ! leftActive)
return true;
return QSortFilterProxyModel::lessThan(source_left, source_right);
}