Qt: Implement total columns for traffic tables
Implement a column type, which will show total values for traffic columns. Implements #15071
This commit is contained in:
parent
0640b711ea
commit
51d5cb42b2
@ -638,6 +638,10 @@ add_conversation_table_data_with_conv_id(
|
|||||||
new_conv_item.tx_frames = 0;
|
new_conv_item.tx_frames = 0;
|
||||||
new_conv_item.rx_bytes = 0;
|
new_conv_item.rx_bytes = 0;
|
||||||
new_conv_item.tx_bytes = 0;
|
new_conv_item.tx_bytes = 0;
|
||||||
|
new_conv_item.rx_frames_total = 0;
|
||||||
|
new_conv_item.tx_frames_total = 0;
|
||||||
|
new_conv_item.rx_bytes_total = 0;
|
||||||
|
new_conv_item.tx_bytes_total = 0;
|
||||||
|
|
||||||
if (ts) {
|
if (ts) {
|
||||||
memcpy(&new_conv_item.start_time, ts, sizeof(new_conv_item.start_time));
|
memcpy(&new_conv_item.start_time, ts, sizeof(new_conv_item.start_time));
|
||||||
@ -782,6 +786,10 @@ add_hostlist_table_data(conv_hash_t *ch, const address *addr, guint32 port, gboo
|
|||||||
host.tx_frames=0;
|
host.tx_frames=0;
|
||||||
host.rx_bytes=0;
|
host.rx_bytes=0;
|
||||||
host.tx_bytes=0;
|
host.tx_bytes=0;
|
||||||
|
host.rx_frames_total=0;
|
||||||
|
host.tx_frames_total=0;
|
||||||
|
host.rx_bytes_total=0;
|
||||||
|
host.tx_bytes_total=0;
|
||||||
host.modified = TRUE;
|
host.modified = TRUE;
|
||||||
host.filtered = TRUE;
|
host.filtered = TRUE;
|
||||||
|
|
||||||
|
@ -111,10 +111,10 @@ typedef struct _conversation_item_t {
|
|||||||
guint64 rx_bytes; /**< number of received bytes */
|
guint64 rx_bytes; /**< number of received bytes */
|
||||||
guint64 tx_bytes; /**< number of transmitted bytes */
|
guint64 tx_bytes; /**< number of transmitted bytes */
|
||||||
|
|
||||||
guint64 rx_frames_total; /**< number of received packets */
|
guint64 rx_frames_total; /**< number of received packets total */
|
||||||
guint64 tx_frames_total; /**< number of transmitted packets */
|
guint64 tx_frames_total; /**< number of transmitted packets total */
|
||||||
guint64 rx_bytes_total; /**< number of received bytes */
|
guint64 rx_bytes_total; /**< number of received bytes total */
|
||||||
guint64 tx_bytes_total; /**< number of transmitted bytes */
|
guint64 tx_bytes_total; /**< number of transmitted bytes total */
|
||||||
|
|
||||||
nstime_t start_time; /**< relative start time for the conversation */
|
nstime_t start_time; /**< relative start time for the conversation */
|
||||||
nstime_t stop_time; /**< relative stop time for the conversation */
|
nstime_t stop_time; /**< relative stop time for the conversation */
|
||||||
@ -135,10 +135,10 @@ typedef struct _hostlist_talker_t {
|
|||||||
guint64 rx_bytes; /**< number of received bytes */
|
guint64 rx_bytes; /**< number of received bytes */
|
||||||
guint64 tx_bytes; /**< number of transmitted bytes */
|
guint64 tx_bytes; /**< number of transmitted bytes */
|
||||||
|
|
||||||
guint64 rx_frames_total; /**< number of received packets */
|
guint64 rx_frames_total; /**< number of received packets total */
|
||||||
guint64 tx_frames_total; /**< number of transmitted packets */
|
guint64 tx_frames_total; /**< number of transmitted packets total */
|
||||||
guint64 rx_bytes_total; /**< number of received bytes */
|
guint64 rx_bytes_total; /**< number of received bytes total */
|
||||||
guint64 tx_bytes_total; /**< number of transmitted bytes */
|
guint64 tx_bytes_total; /**< number of transmitted bytes total */
|
||||||
|
|
||||||
gboolean modified; /**< new to redraw the row */
|
gboolean modified; /**< new to redraw the row */
|
||||||
gboolean filtered; /**< the entry contains only filtered data */
|
gboolean filtered; /**< the entry contains only filtered data */
|
||||||
|
@ -30,10 +30,13 @@
|
|||||||
#include <QWidget>
|
#include <QWidget>
|
||||||
#include <QDateTime>
|
#include <QDateTime>
|
||||||
|
|
||||||
|
static QString formatString(qlonglong value)
|
||||||
|
{
|
||||||
|
return gchar_free_to_qstring(format_size(value, FORMAT_SIZE_UNIT_NONE, FORMAT_SIZE_PREFIX_SI));
|
||||||
|
}
|
||||||
|
|
||||||
ATapDataModel::ATapDataModel(dataModelType type, int protoId, QString filter, QObject *parent):
|
ATapDataModel::ATapDataModel(dataModelType type, int protoId, QString filter, QObject *parent):
|
||||||
QAbstractListModel(parent),
|
QAbstractListModel(parent)
|
||||||
_protoId(protoId),
|
|
||||||
_filter(filter)
|
|
||||||
{
|
{
|
||||||
hash_.conv_array = nullptr;
|
hash_.conv_array = nullptr;
|
||||||
hash_.hashtable = nullptr;
|
hash_.hashtable = nullptr;
|
||||||
@ -44,6 +47,9 @@ ATapDataModel::ATapDataModel(dataModelType type, int protoId, QString filter, QO
|
|||||||
_absoluteTime = false;
|
_absoluteTime = false;
|
||||||
_nanoseconds = false;
|
_nanoseconds = false;
|
||||||
|
|
||||||
|
_protoId = protoId;
|
||||||
|
_filter = filter;
|
||||||
|
|
||||||
_minRelStartTime = 0;
|
_minRelStartTime = 0;
|
||||||
_maxRelStopTime = 0;
|
_maxRelStopTime = 0;
|
||||||
|
|
||||||
@ -102,8 +108,8 @@ bool ATapDataModel::enableTap()
|
|||||||
|
|
||||||
/* The errorString is ignored. If this is not working, there is nothing really the user may do about
|
/* The errorString is ignored. If this is not working, there is nothing really the user may do about
|
||||||
* it, so the error is only interesting to the developer.*/
|
* it, so the error is only interesting to the developer.*/
|
||||||
GString * errorString = register_tap_listener(tap().toUtf8().constData(), hash(), _filter.toUtf8().constData(), 0,
|
GString * errorString = register_tap_listener(tap().toUtf8().constData(), hash(), _filter.toUtf8().constData(),
|
||||||
&ATapDataModel::tapReset, conversationPacketHandler(), &ATapDataModel::tapDraw, nullptr);
|
TL_IGNORE_DISPLAY_FILTER, &ATapDataModel::tapReset, conversationPacketHandler(), &ATapDataModel::tapDraw, nullptr);
|
||||||
if (errorString && errorString->len > 0) {
|
if (errorString && errorString->len > 0) {
|
||||||
_disableTap = true;
|
_disableTap = true;
|
||||||
emit tapListenerChanged(false);
|
emit tapListenerChanged(false);
|
||||||
@ -209,7 +215,7 @@ void ATapDataModel::updateData(GArray * newData)
|
|||||||
endResetModel();
|
endResetModel();
|
||||||
|
|
||||||
if (_type == ATapDataModel::DATAMODEL_CONVERSATION)
|
if (_type == ATapDataModel::DATAMODEL_CONVERSATION)
|
||||||
((ConversationDataModel *)(this))->updateData();
|
((ConversationDataModel *)(this))->doDataUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ATapDataModel::resolveNames() const
|
bool ATapDataModel::resolveNames() const
|
||||||
@ -273,7 +279,7 @@ void ATapDataModel::setFilter(QString filter)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
_filter = filter;
|
_filter = filter;
|
||||||
GString * errorString = set_tap_dfilter(&hash_, !filter.isEmpty() ? filter.toUtf8().constData() : nullptr);
|
GString * errorString = set_tap_dfilter(&hash_, !_filter.isEmpty() ? _filter.toUtf8().constData() : nullptr);
|
||||||
if (errorString && errorString->len > 0) {
|
if (errorString && errorString->len > 0) {
|
||||||
/* If this fails, chances are that the main system failed as well. Silently exiting as the
|
/* If this fails, chances are that the main system failed as well. Silently exiting as the
|
||||||
* user cannot react to it */
|
* user cannot react to it */
|
||||||
@ -284,6 +290,11 @@ void ATapDataModel::setFilter(QString filter)
|
|||||||
g_string_free(errorString, TRUE);
|
g_string_free(errorString, TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString ATapDataModel::filter() const
|
||||||
|
{
|
||||||
|
return _filter;
|
||||||
|
}
|
||||||
|
|
||||||
ATapDataModel::dataModelType ATapDataModel::modelType() const
|
ATapDataModel::dataModelType ATapDataModel::modelType() const
|
||||||
{
|
{
|
||||||
return _type;
|
return _type;
|
||||||
@ -294,6 +305,12 @@ bool ATapDataModel::portsAreHidden() const
|
|||||||
return (get_conversation_hide_ports(registerTable()));
|
return (get_conversation_hide_ports(registerTable()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ATapDataModel::showTotalColumn() const
|
||||||
|
{
|
||||||
|
/* Implemented to ensure future changes may be done more easily */
|
||||||
|
return _filter.length() > 0;
|
||||||
|
}
|
||||||
|
|
||||||
EndpointDataModel::EndpointDataModel(int protoId, QString filter, QObject *parent) :
|
EndpointDataModel::EndpointDataModel(int protoId, QString filter, QObject *parent) :
|
||||||
ATapDataModel(ATapDataModel::DATAMODEL_ENDPOINT, protoId, filter, parent)
|
ATapDataModel(ATapDataModel::DATAMODEL_ENDPOINT, protoId, filter, parent)
|
||||||
{}
|
{}
|
||||||
@ -303,6 +320,8 @@ int EndpointDataModel::columnCount(const QModelIndex &) const
|
|||||||
int columnMax = ENDP_NUM_COLUMNS;
|
int columnMax = ENDP_NUM_COLUMNS;
|
||||||
if (portsAreHidden())
|
if (portsAreHidden())
|
||||||
columnMax--;
|
columnMax--;
|
||||||
|
if (showTotalColumn())
|
||||||
|
columnMax += 2;
|
||||||
return columnMax;
|
return columnMax;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -315,6 +334,14 @@ QVariant EndpointDataModel::headerData(int section, Qt::Orientation orientation,
|
|||||||
if (portsAreHidden() && section >= ENDP_COLUMN_PORT)
|
if (portsAreHidden() && section >= ENDP_COLUMN_PORT)
|
||||||
column += 1;
|
column += 1;
|
||||||
|
|
||||||
|
if (showTotalColumn())
|
||||||
|
{
|
||||||
|
if (column == ENDP_COLUMN_PKT_AB || column == ENDP_COLUMN_BYTES_AB)
|
||||||
|
column += 8;
|
||||||
|
else if (column > ENDP_COLUMN_BYTES_AB)
|
||||||
|
column -= 2;
|
||||||
|
}
|
||||||
|
|
||||||
if (role == Qt::DisplayRole) {
|
if (role == Qt::DisplayRole) {
|
||||||
switch (column) {
|
switch (column) {
|
||||||
case 0:
|
case 0:
|
||||||
@ -341,6 +368,10 @@ QVariant EndpointDataModel::headerData(int section, Qt::Orientation orientation,
|
|||||||
return tr("AS Number"); break;
|
return tr("AS Number"); break;
|
||||||
case 11:
|
case 11:
|
||||||
return tr("AS Organization"); break;
|
return tr("AS Organization"); break;
|
||||||
|
case 12:
|
||||||
|
return tr("Total Packets"); break;
|
||||||
|
case 13:
|
||||||
|
return tr("Percent filtered"); break;
|
||||||
}
|
}
|
||||||
} else if (role == Qt::TextAlignmentRole) {
|
} else if (role == Qt::TextAlignmentRole) {
|
||||||
if (section == ENDP_COLUMN_ADDR)
|
if (section == ENDP_COLUMN_ADDR)
|
||||||
@ -351,11 +382,6 @@ QVariant EndpointDataModel::headerData(int section, Qt::Orientation orientation,
|
|||||||
return QVariant();
|
return QVariant();
|
||||||
}
|
}
|
||||||
|
|
||||||
static QString formatString(qlonglong value)
|
|
||||||
{
|
|
||||||
return gchar_free_to_qstring(format_size(value, FORMAT_SIZE_UNIT_NONE, FORMAT_SIZE_PREFIX_SI));
|
|
||||||
}
|
|
||||||
|
|
||||||
QVariant EndpointDataModel::data(const QModelIndex &idx, int role) const
|
QVariant EndpointDataModel::data(const QModelIndex &idx, int role) const
|
||||||
{
|
{
|
||||||
if (! idx.isValid())
|
if (! idx.isValid())
|
||||||
@ -378,12 +404,18 @@ QVariant EndpointDataModel::data(const QModelIndex &idx, int role) const
|
|||||||
QString ipAddress(addr);
|
QString ipAddress(addr);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (role == Qt::DisplayRole || role == ATapDataModel::UNFORMATTED_DISPLAYDATA) {
|
|
||||||
|
|
||||||
int column = idx.column();
|
int column = idx.column();
|
||||||
if (portsAreHidden() && idx.column() >= ENDP_COLUMN_PORT)
|
if (portsAreHidden() && idx.column() >= ENDP_COLUMN_PORT)
|
||||||
column += 1;
|
column += 1;
|
||||||
|
|
||||||
|
if (showTotalColumn()) {
|
||||||
|
if (column == ENDP_COLUMN_PKT_AB || column == ENDP_COLUMN_BYTES_AB)
|
||||||
|
column += 8;
|
||||||
|
else if (column > ENDP_COLUMN_BYTES_AB)
|
||||||
|
column -= 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (role == Qt::DisplayRole || role == ATapDataModel::UNFORMATTED_DISPLAYDATA) {
|
||||||
switch (column) {
|
switch (column) {
|
||||||
case ENDP_COLUMN_ADDR: {
|
case ENDP_COLUMN_ADDR: {
|
||||||
char* addr_str = get_conversation_address(NULL, &item->myaddress, _resolveNames);
|
char* addr_str = get_conversation_address(NULL, &item->myaddress, _resolveNames);
|
||||||
@ -401,7 +433,10 @@ QVariant EndpointDataModel::data(const QModelIndex &idx, int role) const
|
|||||||
return quint32(item->port);
|
return quint32(item->port);
|
||||||
}
|
}
|
||||||
case ENDP_COLUMN_PACKETS:
|
case ENDP_COLUMN_PACKETS:
|
||||||
return (qlonglong)(item->tx_frames + item->rx_frames);
|
{
|
||||||
|
qlonglong packets = (qlonglong)(item->tx_frames + item->rx_frames);
|
||||||
|
return packets;
|
||||||
|
}
|
||||||
case ENDP_COLUMN_BYTES:
|
case ENDP_COLUMN_BYTES:
|
||||||
return role == Qt::DisplayRole ? formatString((qlonglong)(item->tx_bytes + item->rx_bytes)) :
|
return role == Qt::DisplayRole ? formatString((qlonglong)(item->tx_bytes + item->rx_bytes)) :
|
||||||
QVariant((qlonglong)(item->tx_bytes + item->rx_bytes));
|
QVariant((qlonglong)(item->tx_bytes + item->rx_bytes));
|
||||||
@ -433,6 +468,22 @@ QVariant EndpointDataModel::data(const QModelIndex &idx, int role) const
|
|||||||
return QVariant(mmdb_lookup->as_org);
|
return QVariant(mmdb_lookup->as_org);
|
||||||
}
|
}
|
||||||
return QVariant();
|
return QVariant();
|
||||||
|
case 12:
|
||||||
|
{
|
||||||
|
if (showTotalColumn())
|
||||||
|
return (qlonglong)(item->tx_frames_total + item->rx_frames_total);
|
||||||
|
return QVariant();
|
||||||
|
}
|
||||||
|
case 13:
|
||||||
|
{
|
||||||
|
if (showTotalColumn()) {
|
||||||
|
qlonglong totalPackets = (qlonglong)(item->tx_frames_total + item->rx_frames_total);
|
||||||
|
qlonglong packets = (qlonglong)(item->tx_frames + item->rx_frames);
|
||||||
|
double percent = totalPackets == 0 ? 0 : packets * 100 / totalPackets;
|
||||||
|
return QString::number(percent, 'f', 2) + "%";
|
||||||
|
}
|
||||||
|
return QVariant();
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
return QVariant();
|
return QVariant();
|
||||||
}
|
}
|
||||||
@ -442,6 +493,8 @@ QVariant EndpointDataModel::data(const QModelIndex &idx, int role) const
|
|||||||
return Qt::AlignRight;
|
return Qt::AlignRight;
|
||||||
} else if (role == ATapDataModel::DISPLAY_FILTER) {
|
} else if (role == ATapDataModel::DISPLAY_FILTER) {
|
||||||
return QString(get_hostlist_filter(item));
|
return QString(get_hostlist_filter(item));
|
||||||
|
} else if (role == ATapDataModel::ROW_IS_FILTERED) {
|
||||||
|
return (bool)item->filtered && showTotalColumn();
|
||||||
}
|
}
|
||||||
#ifdef HAVE_MAXMINDDB
|
#ifdef HAVE_MAXMINDDB
|
||||||
else if (role == ATapDataModel::GEODATA_AVAILABLE) {
|
else if (role == ATapDataModel::GEODATA_AVAILABLE) {
|
||||||
@ -460,7 +513,7 @@ ConversationDataModel::ConversationDataModel(int protoId, QString filter, QObjec
|
|||||||
ATapDataModel(ATapDataModel::DATAMODEL_CONVERSATION, protoId, filter, parent)
|
ATapDataModel(ATapDataModel::DATAMODEL_CONVERSATION, protoId, filter, parent)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
void ConversationDataModel::updateData()
|
void ConversationDataModel::doDataUpdate()
|
||||||
{
|
{
|
||||||
_minRelStartTime = 0;
|
_minRelStartTime = 0;
|
||||||
_maxRelStopTime = 0;
|
_maxRelStopTime = 0;
|
||||||
@ -490,6 +543,8 @@ int ConversationDataModel::columnCount(const QModelIndex &) const
|
|||||||
int columnMax = CONV_NUM_COLUMNS;
|
int columnMax = CONV_NUM_COLUMNS;
|
||||||
if (portsAreHidden())
|
if (portsAreHidden())
|
||||||
columnMax -= 2;
|
columnMax -= 2;
|
||||||
|
if (showTotalColumn())
|
||||||
|
columnMax += 2;
|
||||||
return columnMax;
|
return columnMax;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -506,6 +561,13 @@ QVariant ConversationDataModel::headerData(int section, Qt::Orientation orientat
|
|||||||
if (column > CONV_COLUMN_DST_ADDR)
|
if (column > CONV_COLUMN_DST_ADDR)
|
||||||
column++;
|
column++;
|
||||||
}
|
}
|
||||||
|
if (showTotalColumn())
|
||||||
|
{
|
||||||
|
if (column == CONV_COLUMN_PKT_AB || column == CONV_COLUMN_BYTES_AB)
|
||||||
|
column += 8;
|
||||||
|
else if (column > CONV_COLUMN_BYTES_AB)
|
||||||
|
column -= 2;
|
||||||
|
}
|
||||||
|
|
||||||
if (role == Qt::DisplayRole) {
|
if (role == Qt::DisplayRole) {
|
||||||
switch (column) {
|
switch (column) {
|
||||||
@ -537,6 +599,10 @@ QVariant ConversationDataModel::headerData(int section, Qt::Orientation orientat
|
|||||||
return tr("Bits/s A " UTF8_RIGHTWARDS_ARROW " B"); break;
|
return tr("Bits/s A " UTF8_RIGHTWARDS_ARROW " B"); break;
|
||||||
case 13:
|
case 13:
|
||||||
return tr("Bits/s B " UTF8_RIGHTWARDS_ARROW " A"); break;
|
return tr("Bits/s B " UTF8_RIGHTWARDS_ARROW " A"); break;
|
||||||
|
case 14:
|
||||||
|
return tr("Total Packets"); break;
|
||||||
|
case 15:
|
||||||
|
return tr("Percent filtered"); break;
|
||||||
}
|
}
|
||||||
} else if (role == Qt::TextAlignmentRole) {
|
} else if (role == Qt::TextAlignmentRole) {
|
||||||
if (column == CONV_COLUMN_SRC_ADDR || column == CONV_COLUMN_DST_ADDR)
|
if (column == CONV_COLUMN_SRC_ADDR || column == CONV_COLUMN_DST_ADDR)
|
||||||
@ -580,6 +646,12 @@ QVariant ConversationDataModel::data(const QModelIndex &idx, int role) const
|
|||||||
bpsCalculated = true;
|
bpsCalculated = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (showTotalColumn()) {
|
||||||
|
if (column == CONV_COLUMN_PKT_AB || column == CONV_COLUMN_BYTES_AB)
|
||||||
|
column += 8;
|
||||||
|
else if (column > CONV_COLUMN_BYTES_AB)
|
||||||
|
column -= 2;
|
||||||
|
}
|
||||||
if (role == Qt::DisplayRole || role == ATapDataModel::UNFORMATTED_DISPLAYDATA) {
|
if (role == Qt::DisplayRole || role == ATapDataModel::UNFORMATTED_DISPLAYDATA) {
|
||||||
switch(column) {
|
switch(column) {
|
||||||
case CONV_COLUMN_SRC_ADDR:
|
case CONV_COLUMN_SRC_ADDR:
|
||||||
@ -651,6 +723,22 @@ QVariant ConversationDataModel::data(const QModelIndex &idx, int role) const
|
|||||||
return bpsCalculated ? (role == Qt::DisplayRole ? formatString(bps_ab) : QVariant((qlonglong)bps_ab)): QVariant();
|
return bpsCalculated ? (role == Qt::DisplayRole ? formatString(bps_ab) : QVariant((qlonglong)bps_ab)): QVariant();
|
||||||
case CONV_COLUMN_BPS_BA:
|
case CONV_COLUMN_BPS_BA:
|
||||||
return bpsCalculated ? (role == Qt::DisplayRole ? formatString(bps_ba) : QVariant((qlonglong)bps_ba)): QVariant();
|
return bpsCalculated ? (role == Qt::DisplayRole ? formatString(bps_ba) : QVariant((qlonglong)bps_ba)): QVariant();
|
||||||
|
case 14:
|
||||||
|
{
|
||||||
|
if (showTotalColumn())
|
||||||
|
return (qlonglong)(conv_item->tx_frames_total + conv_item->rx_frames_total);
|
||||||
|
return (qlonglong) 0;
|
||||||
|
}
|
||||||
|
case 15:
|
||||||
|
{
|
||||||
|
if (showTotalColumn()) {
|
||||||
|
qlonglong totalPackets = (qlonglong)(conv_item->tx_frames_total + conv_item->rx_frames_total);
|
||||||
|
qlonglong packets = (qlonglong)(conv_item->tx_frames + conv_item->rx_frames);
|
||||||
|
double percent = totalPackets == 0 ? 0 : packets * 100 / totalPackets;
|
||||||
|
return QString::number(percent, 'f', 2) + "%";
|
||||||
|
}
|
||||||
|
return (qlonglong) 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else if (role == Qt::ToolTipRole) {
|
} else if (role == Qt::ToolTipRole) {
|
||||||
if (column == CONV_COLUMN_START || column == CONV_COLUMN_DURATION)
|
if (column == CONV_COLUMN_START || column == CONV_COLUMN_DURATION)
|
||||||
@ -675,6 +763,8 @@ QVariant ConversationDataModel::data(const QModelIndex &idx, int role) const
|
|||||||
return (int)(conv_item->etype);
|
return (int)(conv_item->etype);
|
||||||
} else if (role == ATapDataModel::CONVERSATION_ID) {
|
} else if (role == ATapDataModel::CONVERSATION_ID) {
|
||||||
return (int)(conv_item->conv_id);
|
return (int)(conv_item->conv_id);
|
||||||
|
} else if (role == ATapDataModel::ROW_IS_FILTERED) {
|
||||||
|
return (bool)conv_item->filtered && showTotalColumn();
|
||||||
}
|
}
|
||||||
|
|
||||||
return QVariant();
|
return QVariant();
|
||||||
|
@ -46,7 +46,8 @@ public:
|
|||||||
#endif
|
#endif
|
||||||
TIMELINE_DATA,
|
TIMELINE_DATA,
|
||||||
ENDPOINT_DATATYPE,
|
ENDPOINT_DATATYPE,
|
||||||
CONVERSATION_ID
|
CONVERSATION_ID,
|
||||||
|
ROW_IS_FILTERED
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
@ -106,6 +107,13 @@ public:
|
|||||||
*/
|
*/
|
||||||
void setFilter(QString filter);
|
void setFilter(QString filter);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Return a filter set for the model
|
||||||
|
*
|
||||||
|
* @return QString the filter string for the model
|
||||||
|
*/
|
||||||
|
QString filter() const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Is the model set to resolve names in address and ports columns
|
* @brief Is the model set to resolve names in address and ports columns
|
||||||
*
|
*
|
||||||
@ -203,8 +211,8 @@ protected:
|
|||||||
void updateData(GArray * data);
|
void updateData(GArray * data);
|
||||||
|
|
||||||
dataModelType _type;
|
dataModelType _type;
|
||||||
|
|
||||||
GArray * storage_;
|
GArray * storage_;
|
||||||
|
QString _filter;
|
||||||
|
|
||||||
bool _absoluteTime;
|
bool _absoluteTime;
|
||||||
bool _nanoseconds;
|
bool _nanoseconds;
|
||||||
@ -216,9 +224,10 @@ protected:
|
|||||||
|
|
||||||
register_ct_t* registerTable() const;
|
register_ct_t* registerTable() const;
|
||||||
|
|
||||||
|
bool showTotalColumn() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int _protoId;
|
int _protoId;
|
||||||
QString _filter;
|
|
||||||
|
|
||||||
QMap<QString, QVariant> _lookUp;
|
QMap<QString, QVariant> _lookUp;
|
||||||
|
|
||||||
@ -286,7 +295,7 @@ public:
|
|||||||
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
|
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
|
||||||
QVariant data(const QModelIndex &idx, int role = Qt::DisplayRole) const;
|
QVariant data(const QModelIndex &idx, int role = Qt::DisplayRole) const;
|
||||||
|
|
||||||
void updateData();
|
void doDataUpdate();
|
||||||
|
|
||||||
conv_item_t * itemForRow(int row);
|
conv_item_t * itemForRow(int row);
|
||||||
|
|
||||||
|
@ -66,6 +66,24 @@ int TabData::protoId() const
|
|||||||
return _protoId;
|
return _protoId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TrafficDataFilterProxy::TrafficDataFilterProxy(QObject *parent) :
|
||||||
|
QSortFilterProxyModel(parent)
|
||||||
|
{}
|
||||||
|
|
||||||
|
bool TrafficDataFilterProxy::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const
|
||||||
|
{
|
||||||
|
ATapDataModel * dataModel = qobject_cast<ATapDataModel *>(sourceModel());
|
||||||
|
if (dataModel) {
|
||||||
|
bool isFiltered = dataModel->data(dataModel->index(source_row, 0), ATapDataModel::ROW_IS_FILTERED).toBool();
|
||||||
|
if (dataModel->filter().length() > 0)
|
||||||
|
return ! isFiltered;
|
||||||
|
}
|
||||||
|
|
||||||
|
return QSortFilterProxyModel::filterAcceptsRow(source_row, source_parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static gboolean iterateProtocols(const void *key, void *value, void *userdata)
|
static gboolean iterateProtocols(const void *key, void *value, void *userdata)
|
||||||
{
|
{
|
||||||
QMap<int, QString> *protocols = (QMap<int, QString> *)userdata;
|
QMap<int, QString> *protocols = (QMap<int, QString> *)userdata;
|
||||||
@ -211,7 +229,7 @@ QTreeView * TrafficTab::createTree(int protoId)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QSortFilterProxyModel * proxyModel = new QSortFilterProxyModel();
|
TrafficDataFilterProxy * proxyModel = new TrafficDataFilterProxy();
|
||||||
proxyModel->setSourceModel(model);
|
proxyModel->setSourceModel(model);
|
||||||
tree->setModel(proxyModel);
|
tree->setModel(proxyModel);
|
||||||
|
|
||||||
@ -221,13 +239,13 @@ QTreeView * TrafficTab::createTree(int protoId)
|
|||||||
|
|
||||||
tree->sortByColumn(0, Qt::AscendingOrder);
|
tree->sortByColumn(0, Qt::AscendingOrder);
|
||||||
|
|
||||||
connect(proxyModel, &QSortFilterProxyModel::modelReset, this, [tree]() {
|
connect(proxyModel, &TrafficDataFilterProxy::modelReset, this, [tree]() {
|
||||||
if (tree->model()->rowCount() > 0) {
|
if (tree->model()->rowCount() > 0) {
|
||||||
for (int col = 0; col < tree->model()->columnCount(); col++)
|
for (int col = 0; col < tree->model()->columnCount(); col++)
|
||||||
tree->resizeColumnToContents(col);
|
tree->resizeColumnToContents(col);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
connect(proxyModel, &QSortFilterProxyModel::modelReset, this, &TrafficTab::modelReset);
|
connect(proxyModel, &TrafficDataFilterProxy::modelReset, this, &TrafficTab::modelReset);
|
||||||
}
|
}
|
||||||
|
|
||||||
return tree;
|
return tree;
|
||||||
@ -339,7 +357,7 @@ void TrafficTab::doCurrentIndexChange(const QModelIndex & cur, const QModelIndex
|
|||||||
if (! cur.isValid())
|
if (! cur.isValid())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const QSortFilterProxyModel * proxy = qobject_cast<const QSortFilterProxyModel *>(cur.model());
|
const TrafficDataFilterProxy * proxy = qobject_cast<const TrafficDataFilterProxy *>(cur.model());
|
||||||
if (! proxy)
|
if (! proxy)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -371,10 +389,10 @@ QVariant TrafficTab::currentItemData(int role)
|
|||||||
|
|
||||||
void TrafficTab::modelReset()
|
void TrafficTab::modelReset()
|
||||||
{
|
{
|
||||||
if (! qobject_cast<QSortFilterProxyModel *>(sender()))
|
if (! qobject_cast<TrafficDataFilterProxy *>(sender()))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
QSortFilterProxyModel * qsfpm = qobject_cast<QSortFilterProxyModel *>(sender());
|
TrafficDataFilterProxy * qsfpm = qobject_cast<TrafficDataFilterProxy *>(sender());
|
||||||
if (! qobject_cast<ATapDataModel *>(qsfpm->sourceModel()))
|
if (! qobject_cast<ATapDataModel *>(qsfpm->sourceModel()))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -408,8 +426,8 @@ ATapDataModel * TrafficTab::modelForWidget(QWidget * searchWidget)
|
|||||||
{
|
{
|
||||||
if (qobject_cast<QTreeView *>(searchWidget)) {
|
if (qobject_cast<QTreeView *>(searchWidget)) {
|
||||||
QTreeView * tree = qobject_cast<QTreeView *>(searchWidget);
|
QTreeView * tree = qobject_cast<QTreeView *>(searchWidget);
|
||||||
if (qobject_cast<QSortFilterProxyModel *>(tree->model())) {
|
if (qobject_cast<TrafficDataFilterProxy *>(tree->model())) {
|
||||||
QSortFilterProxyModel * qsfpm = qobject_cast<QSortFilterProxyModel *>(tree->model());
|
TrafficDataFilterProxy * qsfpm = qobject_cast<TrafficDataFilterProxy *>(tree->model());
|
||||||
if (qobject_cast<ATapDataModel *>(qsfpm->sourceModel())) {
|
if (qobject_cast<ATapDataModel *>(qsfpm->sourceModel())) {
|
||||||
return qobject_cast<ATapDataModel *>(qsfpm->sourceModel());
|
return qobject_cast<ATapDataModel *>(qsfpm->sourceModel());
|
||||||
}
|
}
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
#include <QFile>
|
#include <QFile>
|
||||||
#include <QUrl>
|
#include <QUrl>
|
||||||
#include <QAbstractItemDelegate>
|
#include <QAbstractItemDelegate>
|
||||||
|
#include <QSortFilterProxyModel>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Callback for creating an ATapDataModel
|
* @brief Callback for creating an ATapDataModel
|
||||||
@ -62,6 +63,17 @@ private:
|
|||||||
|
|
||||||
Q_DECLARE_METATYPE(TabData)
|
Q_DECLARE_METATYPE(TabData)
|
||||||
|
|
||||||
|
class TrafficDataFilterProxy : public QSortFilterProxyModel
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
TrafficDataFilterProxy(QObject *parent = nullptr);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief A QTabWidget class, providing tap information
|
* @brief A QTabWidget class, providing tap information
|
||||||
*
|
*
|
||||||
|
Loading…
x
Reference in New Issue
Block a user