forked from osmocom/wireshark
Qt: Packet list column sorting.
Sorting behavior should be identical to GTK+. Pass the correct position to beginInsertRows. Add a list of to-do items to packet_list.cpp. Change-Id: Ie6ab4b9f2d780a2af430d0f90529edca5485dada Reviewed-on: https://code.wireshark.org/review/4481 Reviewed-by: Gerald Combs <gerald@wireshark.org>
This commit is contained in:
parent
5051ae1cbe
commit
798eb97053
|
@ -23,6 +23,10 @@
|
|||
#ifndef __FRAME_DATA_H__
|
||||
#define __FRAME_DATA_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#include <epan/tvbuff.h>
|
||||
#include <wsutil/nstime.h>
|
||||
#include "ws_symbol_export.h"
|
||||
|
@ -119,6 +123,10 @@ WS_DLL_PUBLIC void frame_data_set_after_dissect(frame_data *fdata,
|
|||
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* __FRAME_DATA__ */
|
||||
|
||||
/*
|
||||
|
|
|
@ -1578,7 +1578,7 @@ void MainWindow::setMenusForCaptureInProgress(bool capture_in_progress) {
|
|||
|
||||
main_ui_->actionSummary->setEnabled(capture_in_progress);
|
||||
|
||||
qDebug() << "FIX: packet list heading menu sensitivity";
|
||||
// XXX Fix packet list heading menu sensitivity
|
||||
// set_menu_sensitivity(ui_manager_packet_list_heading, "/PacketListHeadingPopup/SortAscending",
|
||||
// !capture_in_progress);
|
||||
// set_menu_sensitivity(ui_manager_packet_list_heading, "/PacketListHeadingPopup/SortDescending",
|
||||
|
|
|
@ -47,12 +47,17 @@
|
|||
|
||||
#include "frame_tvbuff.h"
|
||||
|
||||
#include <QTreeWidget>
|
||||
#include <QContextMenuEvent>
|
||||
#include <QHeaderView>
|
||||
#include <QMessageBox>
|
||||
#include <QScrollBar>
|
||||
#include <QTabWidget>
|
||||
#include <QTextEdit>
|
||||
#include <QScrollBar>
|
||||
#include <QContextMenuEvent>
|
||||
#include <QMessageBox>
|
||||
#include <QTreeWidget>
|
||||
|
||||
// To do:
|
||||
// - Heading context menus
|
||||
// - Catch column reordering and rebuild the column list accoringly.
|
||||
|
||||
// If we ever add the ability to open multiple capture files we might be
|
||||
// able to use something like QMap<capture_file *, PacketList *> to match
|
||||
|
@ -231,15 +236,16 @@ PacketList::PacketList(QWidget *parent) :
|
|||
{
|
||||
QMenu *submenu, *subsubmenu;
|
||||
|
||||
setItemsExpandable(FALSE);
|
||||
setRootIsDecorated(FALSE);
|
||||
setSortingEnabled(TRUE);
|
||||
setUniformRowHeights(TRUE);
|
||||
setItemsExpandable(false);
|
||||
setRootIsDecorated(false);
|
||||
setSortingEnabled(true);
|
||||
setUniformRowHeights(true);
|
||||
setAccessibleName("Packet list");
|
||||
setItemDelegateForColumn(0, &related_packet_delegate_);
|
||||
|
||||
packet_list_model_ = new PacketListModel(this, cap_file_);
|
||||
setModel(packet_list_model_);
|
||||
sortByColumn(-1, Qt::AscendingOrder);
|
||||
|
||||
// XXX We might want to reimplement setParent() and fill in the context
|
||||
// menu there.
|
||||
|
@ -387,6 +393,7 @@ PacketList::PacketList(QWidget *parent) :
|
|||
g_assert(gbl_cur_packet_list == NULL);
|
||||
gbl_cur_packet_list = this;
|
||||
|
||||
connect(packet_list_model_, SIGNAL(goToPacket(int)), this, SLOT(goToPacket(int)));
|
||||
connect(wsApp, SIGNAL(addressResolutionChanged()), this, SLOT(updateAll()));
|
||||
}
|
||||
|
||||
|
@ -615,7 +622,7 @@ void PacketList::clear() {
|
|||
/* XXX is this correct in all cases?
|
||||
* Reset the sort column, use packetlist as model in case the list is frozen.
|
||||
*/
|
||||
sortByColumn(0, Qt::AscendingOrder);
|
||||
sortByColumn(-1, Qt::AscendingOrder);
|
||||
setColumnVisibility();
|
||||
}
|
||||
|
||||
|
@ -718,7 +725,7 @@ QString &PacketList::getFilterFromRowAndColumn()
|
|||
QString PacketList::packetComment()
|
||||
{
|
||||
int row = currentIndex().row();
|
||||
frame_data *fdata;
|
||||
const frame_data *fdata;
|
||||
char *pkt_comment;
|
||||
|
||||
if (!cap_file_ || !packet_list_model_) return NULL;
|
||||
|
|
|
@ -76,7 +76,7 @@ int PacketListModel::packetNumberToRow(int packet_num) const
|
|||
|
||||
guint PacketListModel::recreateVisibleRows()
|
||||
{
|
||||
int pos = visible_rows_.count() + 1;
|
||||
int pos = visible_rows_.count();
|
||||
PacketListRecord *record;
|
||||
|
||||
beginResetModel();
|
||||
|
@ -135,6 +135,103 @@ void PacketListModel::setMonospaceFont(const QFont &mono_font)
|
|||
recreateVisibleRows();
|
||||
}
|
||||
|
||||
// The Qt MVC documentation suggests using QSortFilterProxyModel for sorting
|
||||
// and filtering. That seems like overkill but it might be something we want
|
||||
// to do in the future.
|
||||
|
||||
int PacketListModel::sort_column_;
|
||||
int PacketListModel::text_sort_column_;
|
||||
Qt::SortOrder PacketListModel::sort_order_;
|
||||
capture_file *PacketListModel::sort_cap_file_;
|
||||
|
||||
void PacketListModel::sort(int column, Qt::SortOrder order)
|
||||
{
|
||||
if (!cap_file_ || visible_rows_.length() < 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
sort_column_ = column;
|
||||
text_sort_column_ = PacketListRecord::textColumn(column);
|
||||
sort_order_ = order;
|
||||
sort_cap_file_ = cap_file_;
|
||||
|
||||
beginResetModel();
|
||||
qSort(visible_rows_.begin(), visible_rows_.end(), recordLessThan);
|
||||
for (int i = 0; i < visible_rows_.count(); i++) {
|
||||
number_to_row_[visible_rows_[i]->frameData()->num] = i;
|
||||
}
|
||||
endResetModel();
|
||||
|
||||
if (cap_file_->current_frame) {
|
||||
emit goToPacket(cap_file_->current_frame->num);
|
||||
}
|
||||
}
|
||||
|
||||
bool PacketListModel::recordLessThan(PacketListRecord *r1, PacketListRecord *r2)
|
||||
{
|
||||
int cmp_val = 0;
|
||||
|
||||
// Wherein we try to cram the logic of packet_list_compare_records,
|
||||
// _packet_list_compare_records, and packet_list_compare_custom from
|
||||
// gtk/packet_list_store.c into one function
|
||||
|
||||
if (sort_column_ < 0) {
|
||||
// No column.
|
||||
cmp_val = frame_data_compare(sort_cap_file_->epan, r1->frameData(), r2->frameData(), COL_NUMBER);
|
||||
} else if (text_sort_column_ < 0) {
|
||||
// Column comes directly from frame data
|
||||
cmp_val = frame_data_compare(sort_cap_file_->epan, r1->frameData(), r2->frameData(), sort_cap_file_->cinfo.col_fmt[sort_column_]);
|
||||
} else {
|
||||
if (r1->columnString(sort_cap_file_, sort_column_).toByteArray().data() == r2->columnString(sort_cap_file_, sort_column_).toByteArray().data()) {
|
||||
cmp_val = 0;
|
||||
} else if (sort_cap_file_->cinfo.col_fmt[sort_column_] == COL_CUSTOM) {
|
||||
header_field_info *hfi;
|
||||
|
||||
// Column comes from custom data
|
||||
hfi = proto_registrar_get_byname(sort_cap_file_->cinfo.col_custom_field[sort_column_]);
|
||||
|
||||
if (hfi == NULL) {
|
||||
cmp_val = frame_data_compare(sort_cap_file_->epan, r1->frameData(), r2->frameData(), COL_NUMBER);
|
||||
} else if ((hfi->strings == NULL) &&
|
||||
(((IS_FT_INT(hfi->type) || IS_FT_UINT(hfi->type)) &&
|
||||
((hfi->display == BASE_DEC) || (hfi->display == BASE_DEC_HEX) ||
|
||||
(hfi->display == BASE_OCT))) ||
|
||||
(hfi->type == FT_DOUBLE) || (hfi->type == FT_FLOAT) ||
|
||||
(hfi->type == FT_BOOLEAN) || (hfi->type == FT_FRAMENUM) ||
|
||||
(hfi->type == FT_RELATIVE_TIME)))
|
||||
{
|
||||
/* Attempt to convert to numbers */
|
||||
bool ok_r1, ok_r2;
|
||||
double num_r1 = r1->columnString(sort_cap_file_, sort_column_).toDouble(&ok_r1);
|
||||
double num_r2 = r2->columnString(sort_cap_file_, sort_column_).toDouble(&ok_r2);
|
||||
|
||||
if (!ok_r1 && !ok_r2) {
|
||||
cmp_val = 0;
|
||||
} else if (!ok_r1 || num_r1 < num_r2) {
|
||||
cmp_val = -1;
|
||||
} else if (!ok_r2 || num_r1 > num_r2) {
|
||||
cmp_val = 1;
|
||||
}
|
||||
} else {
|
||||
cmp_val = strcmp(r1->columnString(sort_cap_file_, sort_column_).toByteArray().data(), r2->columnString(sort_cap_file_, sort_column_).toByteArray().data());
|
||||
}
|
||||
} else {
|
||||
cmp_val = strcmp(r1->columnString(sort_cap_file_, sort_column_).toByteArray().data(), r2->columnString(sort_cap_file_, sort_column_).toByteArray().data());
|
||||
}
|
||||
|
||||
if (cmp_val == 0) {
|
||||
// Last resort. Compare column numbers.
|
||||
cmp_val = frame_data_compare(sort_cap_file_->epan, r1->frameData(), r2->frameData(), COL_NUMBER);
|
||||
}
|
||||
}
|
||||
|
||||
if (sort_order_ == Qt::AscendingOrder) {
|
||||
return cmp_val < 0;
|
||||
} else {
|
||||
return cmp_val > 0;
|
||||
}
|
||||
}
|
||||
|
||||
int PacketListModel::rowCount(const QModelIndex &parent) const
|
||||
{
|
||||
if (parent.column() >= prefs.num_cols)
|
||||
|
@ -158,7 +255,7 @@ QVariant PacketListModel::data(const QModelIndex &index, int role) const
|
|||
PacketListRecord *record = static_cast<PacketListRecord*>(index.internalPointer());
|
||||
if (!record)
|
||||
return QVariant();
|
||||
frame_data *fdata = record->frameData();
|
||||
const frame_data *fdata = record->frameData();
|
||||
if (!fdata)
|
||||
return QVariant();
|
||||
|
||||
|
@ -242,7 +339,7 @@ QVariant PacketListModel::headerData(int section, Qt::Orientation orientation,
|
|||
gint PacketListModel::appendPacket(frame_data *fdata)
|
||||
{
|
||||
PacketListRecord *record = new PacketListRecord(fdata);
|
||||
gint pos = visible_rows_.count() + 1;
|
||||
gint pos = visible_rows_.count();
|
||||
|
||||
physical_rows_ << record;
|
||||
|
||||
|
|
|
@ -65,9 +65,11 @@ public:
|
|||
int columnTextSize(const char *str);
|
||||
|
||||
signals:
|
||||
void goToPacket(int);
|
||||
|
||||
public slots:
|
||||
void setMonospaceFont(const QFont &mono_font);
|
||||
void sort(int column, Qt::SortOrder order = Qt::AscendingOrder);
|
||||
|
||||
private:
|
||||
capture_file *cap_file_;
|
||||
|
@ -78,6 +80,12 @@ private:
|
|||
QMap<int, int> number_to_row_;
|
||||
|
||||
int header_height_;
|
||||
|
||||
static int sort_column_;
|
||||
static int text_sort_column_;
|
||||
static Qt::SortOrder sort_order_;
|
||||
static capture_file *sort_cap_file_;
|
||||
static bool recordLessThan(PacketListRecord *r1, PacketListRecord *r2);
|
||||
};
|
||||
|
||||
#endif // PACKET_LIST_MODEL_H
|
||||
|
|
|
@ -33,7 +33,7 @@
|
|||
|
||||
#include <QStringList>
|
||||
|
||||
QMap<int, int> cinfo_column_;
|
||||
QMap<int, int> PacketListRecord::cinfo_column_;
|
||||
|
||||
PacketListRecord::PacketListRecord(frame_data *frameData) :
|
||||
fdata_(frameData),
|
||||
|
@ -42,7 +42,7 @@ PacketListRecord::PacketListRecord(frame_data *frameData) :
|
|||
{
|
||||
}
|
||||
|
||||
QVariant PacketListRecord::columnString(capture_file *cap_file, int column)
|
||||
const QVariant PacketListRecord::columnString(capture_file *cap_file, int column)
|
||||
{
|
||||
// packet_list_store.c:packet_list_get_value
|
||||
g_assert(fdata_);
|
||||
|
@ -58,10 +58,6 @@ QVariant PacketListRecord::columnString(capture_file *cap_file, int column)
|
|||
return col_text_.value(column, QByteArray());
|
||||
}
|
||||
|
||||
frame_data *PacketListRecord::frameData() {
|
||||
return fdata_;
|
||||
}
|
||||
|
||||
void PacketListRecord::resetColumns(column_info *cinfo)
|
||||
{
|
||||
if (!cinfo) {
|
||||
|
|
|
@ -40,8 +40,10 @@ class PacketListRecord
|
|||
public:
|
||||
PacketListRecord(frame_data *frameData);
|
||||
// Return the string value for a column. Data is cached if possible.
|
||||
QVariant columnString(capture_file *cap_file, int column);
|
||||
frame_data *frameData();
|
||||
const QVariant columnString(capture_file *cap_file, int column);
|
||||
frame_data *frameData() const { return fdata_; }
|
||||
// packet_list->col_to_text in gtk/packet_list_store.c
|
||||
static int textColumn(int column) { return cinfo_column_.value(column, -1); }
|
||||
|
||||
int columnTextSize(const char *str);
|
||||
static void resetColumns(column_info *cinfo);
|
||||
|
@ -52,6 +54,8 @@ private:
|
|||
QList<QByteArray> col_text_;
|
||||
|
||||
frame_data *fdata_;
|
||||
static QMap<int, int> cinfo_column_;
|
||||
|
||||
|
||||
/** Has this record been columnized? */
|
||||
// gboolean columnized_;
|
||||
|
|
|
@ -38,7 +38,7 @@ void RelatedPacketDelegate::paint(QPainter *painter, const QStyleOptionViewItem
|
|||
optv4.decorationSize.setWidth(en_w);
|
||||
QStyledItemDelegate::paint(painter, optv4, index);
|
||||
|
||||
frame_data *fd;
|
||||
const frame_data *fd;
|
||||
PacketListRecord *record = static_cast<PacketListRecord*>(index.internalPointer());
|
||||
if (!record || (fd = record->frameData()) == NULL) {
|
||||
return;
|
||||
|
|
|
@ -67,7 +67,7 @@ void packet_list_thaw(void);
|
|||
void packet_list_next(void);
|
||||
void packet_list_prev(void);
|
||||
guint packet_list_append(column_info *cinfo, frame_data *fdata);
|
||||
frame_data * packet_list_get_row_data(gint row);
|
||||
frame_data *packet_list_get_row_data(gint row);
|
||||
void packet_list_set_selected_row(gint row);
|
||||
void packet_list_enable_color(gboolean enable);
|
||||
void packet_list_queue_draw(void);
|
||||
|
|
Loading…
Reference in New Issue