forked from osmocom/wireshark
Qt: Speed up ProtoTreeModel with lots of items
When creating a ProtoNode, count the (non-hidden) children and put them in a QVector. This saves time having to iterate through all of a node's children (or the parent's children) each time the model or view wants to get the row or index number. Create and delete the needed ProtoNodes when the root node is changed, instead of recreating them on demand from the proto_nodes (since they're no longer a thin wrapper.) Fix #18625
This commit is contained in:
parent
52382b2592
commit
b7ed46288a
|
@ -23,9 +23,15 @@
|
||||||
// - Add ProtoTreeModel to CaptureFile
|
// - Add ProtoTreeModel to CaptureFile
|
||||||
|
|
||||||
ProtoTreeModel::ProtoTreeModel(QObject * parent) :
|
ProtoTreeModel::ProtoTreeModel(QObject * parent) :
|
||||||
QAbstractItemModel(parent),
|
QAbstractItemModel(parent)
|
||||||
root_node_(0)
|
{
|
||||||
{}
|
root_node_ = new ProtoNode(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
ProtoTreeModel::~ProtoTreeModel()
|
||||||
|
{
|
||||||
|
delete root_node_;
|
||||||
|
}
|
||||||
|
|
||||||
Qt::ItemFlags ProtoTreeModel::flags(const QModelIndex &index) const
|
Qt::ItemFlags ProtoTreeModel::flags(const QModelIndex &index) const
|
||||||
{
|
{
|
||||||
|
@ -39,44 +45,39 @@ Qt::ItemFlags ProtoTreeModel::flags(const QModelIndex &index) const
|
||||||
|
|
||||||
QModelIndex ProtoTreeModel::index(int row, int, const QModelIndex &parent) const
|
QModelIndex ProtoTreeModel::index(int row, int, const QModelIndex &parent) const
|
||||||
{
|
{
|
||||||
ProtoNode parent_node(root_node_);
|
ProtoNode *parent_node = root_node_;
|
||||||
|
|
||||||
if (parent.isValid()) {
|
if (parent.isValid()) {
|
||||||
// index is not a top level item.
|
// index is not a top level item.
|
||||||
parent_node = protoNodeFromIndex(parent);
|
parent_node = protoNodeFromIndex(parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (! parent_node.isValid())
|
if (! parent_node->isValid())
|
||||||
return QModelIndex();
|
return QModelIndex();
|
||||||
|
|
||||||
int cur_row = 0;
|
ProtoNode *child = parent_node->child(row);
|
||||||
ProtoNode::ChildIterator kids = parent_node.children();
|
if (! child) {
|
||||||
while (kids.element().isValid())
|
|
||||||
{
|
|
||||||
if (cur_row == row)
|
|
||||||
break;
|
|
||||||
cur_row++;
|
|
||||||
kids.next();
|
|
||||||
}
|
|
||||||
if (! kids.element().isValid()) {
|
|
||||||
return QModelIndex();
|
return QModelIndex();
|
||||||
}
|
}
|
||||||
|
|
||||||
return createIndex(row, 0, static_cast<void *>(kids.element().protoNode()));
|
return createIndex(row, 0, static_cast<void *>(child));
|
||||||
}
|
}
|
||||||
|
|
||||||
QModelIndex ProtoTreeModel::parent(const QModelIndex &index) const
|
QModelIndex ProtoTreeModel::parent(const QModelIndex &index) const
|
||||||
{
|
{
|
||||||
ProtoNode parent_node = protoNodeFromIndex(index).parentNode();
|
if (!index.isValid())
|
||||||
|
return QModelIndex();
|
||||||
|
|
||||||
|
ProtoNode *parent_node = protoNodeFromIndex(index)->parentNode();
|
||||||
return indexFromProtoNode(parent_node);
|
return indexFromProtoNode(parent_node);
|
||||||
}
|
}
|
||||||
|
|
||||||
int ProtoTreeModel::rowCount(const QModelIndex &parent) const
|
int ProtoTreeModel::rowCount(const QModelIndex &parent) const
|
||||||
{
|
{
|
||||||
if (parent.isValid()) {
|
if (parent.isValid()) {
|
||||||
return protoNodeFromIndex(parent).childrenCount();
|
return protoNodeFromIndex(parent)->childrenCount();
|
||||||
}
|
}
|
||||||
return ProtoNode(root_node_).childrenCount();
|
return root_node_->childrenCount();
|
||||||
}
|
}
|
||||||
|
|
||||||
// The QItemDelegate documentation says
|
// The QItemDelegate documentation says
|
||||||
|
@ -87,15 +88,18 @@ int ProtoTreeModel::rowCount(const QModelIndex &parent) const
|
||||||
// We might want to move this to a delegate regardless.
|
// We might want to move this to a delegate regardless.
|
||||||
QVariant ProtoTreeModel::data(const QModelIndex &index, int role) const
|
QVariant ProtoTreeModel::data(const QModelIndex &index, int role) const
|
||||||
{
|
{
|
||||||
ProtoNode index_node = protoNodeFromIndex(index);
|
if (!index.isValid())
|
||||||
FieldInformation finfo(index_node.protoNode());
|
return QVariant();
|
||||||
|
|
||||||
|
ProtoNode *index_node = protoNodeFromIndex(index);
|
||||||
|
FieldInformation finfo(index_node);
|
||||||
if (!finfo.isValid()) {
|
if (!finfo.isValid()) {
|
||||||
return QVariant();
|
return QVariant();
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (role) {
|
switch (role) {
|
||||||
case Qt::DisplayRole:
|
case Qt::DisplayRole:
|
||||||
return index_node.labelText();
|
return index_node->labelText();
|
||||||
case Qt::BackgroundRole:
|
case Qt::BackgroundRole:
|
||||||
{
|
{
|
||||||
switch(finfo.flag(PI_SEVERITY_MASK)) {
|
switch(finfo.flag(PI_SEVERITY_MASK)) {
|
||||||
|
@ -148,45 +152,55 @@ QVariant ProtoTreeModel::data(const QModelIndex &index, int role) const
|
||||||
void ProtoTreeModel::setRootNode(proto_node *root_node)
|
void ProtoTreeModel::setRootNode(proto_node *root_node)
|
||||||
{
|
{
|
||||||
beginResetModel();
|
beginResetModel();
|
||||||
root_node_ = root_node;
|
delete root_node_;
|
||||||
|
root_node_ = new ProtoNode(root_node);
|
||||||
endResetModel();
|
endResetModel();
|
||||||
if (!root_node) return;
|
if (!root_node) return;
|
||||||
|
|
||||||
int row_count = ProtoNode(root_node_).childrenCount();
|
int row_count = root_node_->childrenCount();
|
||||||
if (row_count < 1) return;
|
if (row_count < 1) return;
|
||||||
beginInsertRows(QModelIndex(), 0, row_count - 1);
|
beginInsertRows(QModelIndex(), 0, row_count - 1);
|
||||||
endInsertRows();
|
endInsertRows();
|
||||||
}
|
}
|
||||||
|
|
||||||
ProtoNode ProtoTreeModel::protoNodeFromIndex(const QModelIndex &index) const
|
ProtoNode* ProtoTreeModel::protoNodeFromIndex(const QModelIndex &index) const
|
||||||
{
|
{
|
||||||
return ProtoNode(static_cast<proto_node*>(index.internalPointer()));
|
return static_cast<ProtoNode*>(index.internalPointer());
|
||||||
}
|
}
|
||||||
|
|
||||||
QModelIndex ProtoTreeModel::indexFromProtoNode(ProtoNode &index_node) const
|
QModelIndex ProtoTreeModel::indexFromProtoNode(ProtoNode *index_node) const
|
||||||
{
|
{
|
||||||
int row = index_node.row();
|
if (!index_node) {
|
||||||
|
|
||||||
if (!index_node.isValid() || row < 0) {
|
|
||||||
return QModelIndex();
|
return QModelIndex();
|
||||||
}
|
}
|
||||||
|
|
||||||
return createIndex(row, 0, static_cast<void *>(index_node.protoNode()));
|
int row = index_node->row();
|
||||||
|
|
||||||
|
if (!index_node->isValid() || row < 0) {
|
||||||
|
return QModelIndex();
|
||||||
|
}
|
||||||
|
|
||||||
|
return createIndex(row, 0, static_cast<void *>(index_node));
|
||||||
}
|
}
|
||||||
|
|
||||||
struct find_hfid_ {
|
struct find_hfid_ {
|
||||||
int hfid;
|
int hfid;
|
||||||
ProtoNode node;
|
ProtoNode *node;
|
||||||
};
|
};
|
||||||
|
|
||||||
void ProtoTreeModel::foreachFindHfid(proto_node *node, gpointer find_hfid_ptr)
|
bool ProtoTreeModel::foreachFindHfid(ProtoNode *node, gpointer find_hfid_ptr)
|
||||||
{
|
{
|
||||||
struct find_hfid_ *find_hfid = (struct find_hfid_ *) find_hfid_ptr;
|
struct find_hfid_ *find_hfid = (struct find_hfid_ *) find_hfid_ptr;
|
||||||
if (PNODE_FINFO(node)->hfinfo->id == find_hfid->hfid) {
|
if (PNODE_FINFO(node->protoNode())->hfinfo->id == find_hfid->hfid) {
|
||||||
find_hfid->node = ProtoNode(node);
|
find_hfid->node = node;
|
||||||
return;
|
return true;
|
||||||
}
|
}
|
||||||
proto_tree_children_foreach(node, foreachFindHfid, find_hfid);
|
for (int i = 0; i < node->childrenCount(); i++) {
|
||||||
|
if (foreachFindHfid(node->child(i), &find_hfid)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
QModelIndex ProtoTreeModel::findFirstHfid(int hf_id)
|
QModelIndex ProtoTreeModel::findFirstHfid(int hf_id)
|
||||||
|
@ -196,9 +210,7 @@ QModelIndex ProtoTreeModel::findFirstHfid(int hf_id)
|
||||||
struct find_hfid_ find_hfid;
|
struct find_hfid_ find_hfid;
|
||||||
find_hfid.hfid = hf_id;
|
find_hfid.hfid = hf_id;
|
||||||
|
|
||||||
proto_tree_children_foreach(root_node_, foreachFindHfid, &find_hfid);
|
if (foreachFindHfid(root_node_, &find_hfid) && find_hfid.node->isValid()) {
|
||||||
|
|
||||||
if (find_hfid.node.isValid()) {
|
|
||||||
return indexFromProtoNode(find_hfid.node);
|
return indexFromProtoNode(find_hfid.node);
|
||||||
}
|
}
|
||||||
return QModelIndex();
|
return QModelIndex();
|
||||||
|
@ -206,17 +218,22 @@ QModelIndex ProtoTreeModel::findFirstHfid(int hf_id)
|
||||||
|
|
||||||
struct find_field_info_ {
|
struct find_field_info_ {
|
||||||
field_info *fi;
|
field_info *fi;
|
||||||
ProtoNode node;
|
ProtoNode *node;
|
||||||
};
|
};
|
||||||
|
|
||||||
void ProtoTreeModel::foreachFindField(proto_node *node, gpointer find_finfo_ptr)
|
bool ProtoTreeModel::foreachFindField(ProtoNode *node, gpointer find_finfo_ptr)
|
||||||
{
|
{
|
||||||
struct find_field_info_ *find_finfo = (struct find_field_info_ *) find_finfo_ptr;
|
struct find_field_info_ *find_finfo = (struct find_field_info_ *) find_finfo_ptr;
|
||||||
if (PNODE_FINFO(node) == find_finfo->fi) {
|
if (PNODE_FINFO(node->protoNode()) == find_finfo->fi) {
|
||||||
find_finfo->node = ProtoNode(node);
|
find_finfo->node = node;
|
||||||
return;
|
return true;
|
||||||
}
|
}
|
||||||
proto_tree_children_foreach(node, foreachFindField, find_finfo);
|
for (int i = 0; i < node->childrenCount(); i++) {
|
||||||
|
if (foreachFindField(node->child(i), &find_finfo)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
QModelIndex ProtoTreeModel::findFieldInformation(FieldInformation *finfo)
|
QModelIndex ProtoTreeModel::findFieldInformation(FieldInformation *finfo)
|
||||||
|
@ -228,8 +245,7 @@ QModelIndex ProtoTreeModel::findFieldInformation(FieldInformation *finfo)
|
||||||
struct find_field_info_ find_finfo;
|
struct find_field_info_ find_finfo;
|
||||||
find_finfo.fi = fi;
|
find_finfo.fi = fi;
|
||||||
|
|
||||||
proto_tree_children_foreach(root_node_, foreachFindField, &find_finfo);
|
if (foreachFindField(root_node_, &find_finfo) && find_finfo.node->isValid()) {
|
||||||
if (find_finfo.node.isValid()) {
|
|
||||||
return indexFromProtoNode(find_finfo.node);
|
return indexFromProtoNode(find_finfo.node);
|
||||||
}
|
}
|
||||||
return QModelIndex();
|
return QModelIndex();
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
#ifndef PROTO_TREE_MODEL_H
|
#ifndef PROTO_TREE_MODEL_H
|
||||||
#define PROTO_TREE_MODEL_H
|
#define PROTO_TREE_MODEL_H
|
||||||
|
|
||||||
|
#include <ui/qt/utils/field_information.h>
|
||||||
#include <ui/qt/utils/proto_node.h>
|
#include <ui/qt/utils/proto_node.h>
|
||||||
|
|
||||||
#include <QAbstractItemModel>
|
#include <QAbstractItemModel>
|
||||||
|
@ -21,6 +22,7 @@ class ProtoTreeModel : public QAbstractItemModel
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit ProtoTreeModel(QObject * parent = 0);
|
explicit ProtoTreeModel(QObject * parent = 0);
|
||||||
|
~ProtoTreeModel();
|
||||||
|
|
||||||
virtual Qt::ItemFlags flags(const QModelIndex &index) const;
|
virtual Qt::ItemFlags flags(const QModelIndex &index) const;
|
||||||
QModelIndex index(int row, int, const QModelIndex &parent = QModelIndex()) const;
|
QModelIndex index(int row, int, const QModelIndex &parent = QModelIndex()) const;
|
||||||
|
@ -31,16 +33,16 @@ public:
|
||||||
|
|
||||||
// root_node can be NULL.
|
// root_node can be NULL.
|
||||||
void setRootNode(proto_node *root_node);
|
void setRootNode(proto_node *root_node);
|
||||||
ProtoNode protoNodeFromIndex(const QModelIndex &index) const;
|
ProtoNode* protoNodeFromIndex(const QModelIndex &index) const;
|
||||||
QModelIndex indexFromProtoNode(ProtoNode &index_node) const;
|
QModelIndex indexFromProtoNode(ProtoNode *index_node) const;
|
||||||
|
|
||||||
QModelIndex findFirstHfid(int hf_id);
|
QModelIndex findFirstHfid(int hf_id);
|
||||||
QModelIndex findFieldInformation(FieldInformation *finfo);
|
QModelIndex findFieldInformation(FieldInformation *finfo);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
proto_node* root_node_;
|
ProtoNode *root_node_;
|
||||||
static void foreachFindHfid(proto_node *node, gpointer find_hfid_ptr);
|
static bool foreachFindHfid(ProtoNode *node, gpointer find_hfid_ptr);
|
||||||
static void foreachFindField(proto_node *node, gpointer find_finfo_ptr);
|
static bool foreachFindField(ProtoNode *node, gpointer find_finfo_ptr);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // PROTO_TREE_MODEL_H
|
#endif // PROTO_TREE_MODEL_H
|
||||||
|
|
|
@ -134,7 +134,7 @@ void ProtoTree::ctxCopyVisibleItems()
|
||||||
void ProtoTree::ctxCopyAsFilter()
|
void ProtoTree::ctxCopyAsFilter()
|
||||||
{
|
{
|
||||||
QModelIndex idx = selectionModel()->selectedIndexes().first();
|
QModelIndex idx = selectionModel()->selectedIndexes().first();
|
||||||
FieldInformation finfo(proto_tree_model_->protoNodeFromIndex(idx).protoNode());
|
FieldInformation finfo(proto_tree_model_->protoNodeFromIndex(idx));
|
||||||
if (finfo.isValid())
|
if (finfo.isValid())
|
||||||
{
|
{
|
||||||
epan_dissect_t *edt = cap_file_ ? cap_file_->edt : edt_;
|
epan_dissect_t *edt = cap_file_ ? cap_file_->edt : edt_;
|
||||||
|
@ -156,7 +156,7 @@ void ProtoTree::ctxCopySelectedInfo()
|
||||||
val = send->property("field_type").toInt();
|
val = send->property("field_type").toInt();
|
||||||
|
|
||||||
QModelIndex idx = selectionModel()->selectedIndexes().first();
|
QModelIndex idx = selectionModel()->selectedIndexes().first();
|
||||||
FieldInformation finfo(proto_tree_model_->protoNodeFromIndex(idx).protoNode());
|
FieldInformation finfo(proto_tree_model_->protoNodeFromIndex(idx));
|
||||||
if (! finfo.isValid())
|
if (! finfo.isValid())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
@ -194,7 +194,7 @@ void ProtoTree::ctxOpenUrlWiki()
|
||||||
if (send && send->property("field_reference").isValid())
|
if (send && send->property("field_reference").isValid())
|
||||||
is_field_reference = send->property("field_reference").toBool();
|
is_field_reference = send->property("field_reference").toBool();
|
||||||
QModelIndex idx = selectionModel()->selectedIndexes().first();
|
QModelIndex idx = selectionModel()->selectedIndexes().first();
|
||||||
FieldInformation finfo(proto_tree_model_->protoNodeFromIndex(idx).protoNode());
|
FieldInformation finfo(proto_tree_model_->protoNodeFromIndex(idx));
|
||||||
|
|
||||||
int field_id = finfo.headerInfo().id;
|
int field_id = finfo.headerInfo().id;
|
||||||
if (!proto_registrar_is_protocol(field_id) && (field_id != hf_text_only)) {
|
if (!proto_registrar_is_protocol(field_id) && (field_id != hf_text_only)) {
|
||||||
|
@ -250,7 +250,7 @@ void ProtoTree::contextMenuEvent(QContextMenuEvent *event)
|
||||||
QAction *action;
|
QAction *action;
|
||||||
|
|
||||||
bool have_subtree = false;
|
bool have_subtree = false;
|
||||||
FieldInformation *finfo = new FieldInformation(proto_tree_model_->protoNodeFromIndex(index).protoNode(), ctx_menu);
|
FieldInformation *finfo = new FieldInformation(proto_tree_model_->protoNodeFromIndex(index), ctx_menu);
|
||||||
field_info * fi = finfo->fieldInfo();
|
field_info * fi = finfo->fieldInfo();
|
||||||
bool is_selected = false;
|
bool is_selected = false;
|
||||||
epan_dissect_t *edt = cap_file_ ? cap_file_->edt : edt_;
|
epan_dissect_t *edt = cap_file_ ? cap_file_->edt : edt_;
|
||||||
|
@ -376,9 +376,10 @@ void ProtoTree::contextMenuEvent(QContextMenuEvent *event)
|
||||||
|
|
||||||
// The "text only" header field will not give preferences for the selected protocol.
|
// The "text only" header field will not give preferences for the selected protocol.
|
||||||
// Use parent in this case.
|
// Use parent in this case.
|
||||||
proto_node *node = proto_tree_model_->protoNodeFromIndex(index).protoNode();
|
ProtoNode *node = proto_tree_model_->protoNodeFromIndex(index);
|
||||||
while (node && node->finfo && node->finfo->hfinfo && node->finfo->hfinfo->id == hf_text_only)
|
while (node && node->isValid() && node->protoNode()->finfo && node->protoNode()->finfo->hfinfo && node->protoNode()->finfo->hfinfo->id == hf_text_only) {
|
||||||
node = node->parent;
|
node = node->parentNode();
|
||||||
|
}
|
||||||
|
|
||||||
FieldInformation pref_finfo(node);
|
FieldInformation pref_finfo(node);
|
||||||
proto_prefs_menu_.setModule(pref_finfo.moduleName());
|
proto_prefs_menu_.setModule(pref_finfo.moduleName());
|
||||||
|
@ -438,13 +439,8 @@ void ProtoTree::foreachTreeNode(proto_node *node, gpointer proto_tree_ptr)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Expanded state
|
// Related frames - there might be hidden FT_FRAMENUM nodes, so do this
|
||||||
if (tree_expanded(node->finfo->tree_type)) {
|
// for each proto_node and not just the ProtoNodes in the model
|
||||||
ProtoNode expand_node = ProtoNode(node);
|
|
||||||
tree_view->expand(model->indexFromProtoNode(expand_node));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Related frames
|
|
||||||
if (node->finfo->hfinfo->type == FT_FRAMENUM) {
|
if (node->finfo->hfinfo->type == FT_FRAMENUM) {
|
||||||
ft_framenum_type_t framenum_type = (ft_framenum_type_t)GPOINTER_TO_INT(node->finfo->hfinfo->strings);
|
ft_framenum_type_t framenum_type = (ft_framenum_type_t)GPOINTER_TO_INT(node->finfo->hfinfo->strings);
|
||||||
tree_view->emitRelatedFrame(node->finfo->value.value.uinteger, framenum_type);
|
tree_view->emitRelatedFrame(node->finfo->value.value.uinteger, framenum_type);
|
||||||
|
@ -453,6 +449,23 @@ void ProtoTree::foreachTreeNode(proto_node *node, gpointer proto_tree_ptr)
|
||||||
proto_tree_children_foreach(node, foreachTreeNode, proto_tree_ptr);
|
proto_tree_children_foreach(node, foreachTreeNode, proto_tree_ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ProtoTree::foreachExpand(const QModelIndex &index = QModelIndex()) {
|
||||||
|
|
||||||
|
// Restore expanded state. (Note QModelIndex() refers to the root node)
|
||||||
|
int children = proto_tree_model_->rowCount(index);
|
||||||
|
QModelIndex childIndex;
|
||||||
|
for (int child = 0; child < children; child++) {
|
||||||
|
childIndex = proto_tree_model_->index(child, 0, index);
|
||||||
|
if (childIndex.isValid()) {
|
||||||
|
ProtoNode *node = proto_tree_model_->protoNodeFromIndex(childIndex);
|
||||||
|
if (node && node->isValid() && tree_expanded(node->protoNode()->finfo->tree_type)) {
|
||||||
|
expand(childIndex);
|
||||||
|
}
|
||||||
|
foreachExpand(childIndex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// setRootNode sets the new contents for the protocol tree and subsequently
|
// setRootNode sets the new contents for the protocol tree and subsequently
|
||||||
// restores the previously expanded state.
|
// restores the previously expanded state.
|
||||||
void ProtoTree::setRootNode(proto_node *root_node) {
|
void ProtoTree::setRootNode(proto_node *root_node) {
|
||||||
|
@ -463,6 +476,7 @@ void ProtoTree::setRootNode(proto_node *root_node) {
|
||||||
|
|
||||||
disconnect(this, SIGNAL(expanded(QModelIndex)), this, SLOT(syncExpanded(QModelIndex)));
|
disconnect(this, SIGNAL(expanded(QModelIndex)), this, SLOT(syncExpanded(QModelIndex)));
|
||||||
proto_tree_children_foreach(root_node, foreachTreeNode, this);
|
proto_tree_children_foreach(root_node, foreachTreeNode, this);
|
||||||
|
foreachExpand();
|
||||||
connect(this, SIGNAL(expanded(QModelIndex)), this, SLOT(syncExpanded(QModelIndex)));
|
connect(this, SIGNAL(expanded(QModelIndex)), this, SLOT(syncExpanded(QModelIndex)));
|
||||||
|
|
||||||
updateContentWidth();
|
updateContentWidth();
|
||||||
|
@ -505,14 +519,14 @@ void ProtoTree::selectionChanged(const QItemSelection &selected, const QItemSele
|
||||||
// Find and highlight the protocol bytes. select above won't call
|
// Find and highlight the protocol bytes. select above won't call
|
||||||
// selectionChanged if the current and selected indexes are the same
|
// selectionChanged if the current and selected indexes are the same
|
||||||
// so we do this here.
|
// so we do this here.
|
||||||
FieldInformation finfo(proto_tree_model_->protoNodeFromIndex(index).protoNode(), this);
|
FieldInformation finfo(proto_tree_model_->protoNodeFromIndex(index), this);
|
||||||
if (finfo.isValid()) {
|
if (finfo.isValid()) {
|
||||||
QModelIndex parent = index;
|
QModelIndex parent = index;
|
||||||
while (parent.isValid() && parent.parent().isValid()) {
|
while (parent.isValid() && parent.parent().isValid()) {
|
||||||
parent = parent.parent();
|
parent = parent.parent();
|
||||||
}
|
}
|
||||||
if (parent.isValid()) {
|
if (parent.isValid()) {
|
||||||
FieldInformation parent_finfo(proto_tree_model_->protoNodeFromIndex(parent).protoNode());
|
FieldInformation parent_finfo(proto_tree_model_->protoNodeFromIndex(parent));
|
||||||
finfo.setParentField(parent_finfo.fieldInfo());
|
finfo.setParentField(parent_finfo.fieldInfo());
|
||||||
}
|
}
|
||||||
emit fieldSelected(&finfo);
|
emit fieldSelected(&finfo);
|
||||||
|
@ -520,7 +534,7 @@ void ProtoTree::selectionChanged(const QItemSelection &selected, const QItemSele
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProtoTree::syncExpanded(const QModelIndex &index) {
|
void ProtoTree::syncExpanded(const QModelIndex &index) {
|
||||||
FieldInformation finfo(proto_tree_model_->protoNodeFromIndex(index).protoNode());
|
FieldInformation finfo(proto_tree_model_->protoNodeFromIndex(index));
|
||||||
if (!finfo.isValid()) return;
|
if (!finfo.isValid()) return;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -533,7 +547,7 @@ void ProtoTree::syncExpanded(const QModelIndex &index) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProtoTree::syncCollapsed(const QModelIndex &index) {
|
void ProtoTree::syncCollapsed(const QModelIndex &index) {
|
||||||
FieldInformation finfo(proto_tree_model_->protoNodeFromIndex(index).protoNode());
|
FieldInformation finfo(proto_tree_model_->protoNodeFromIndex(index));
|
||||||
if (!finfo.isValid()) return;
|
if (!finfo.isValid()) return;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -612,7 +626,7 @@ void ProtoTree::itemClicked(const QModelIndex &index)
|
||||||
if (selectionModel()->selectedIndexes().isEmpty()) {
|
if (selectionModel()->selectedIndexes().isEmpty()) {
|
||||||
emit fieldSelected(0);
|
emit fieldSelected(0);
|
||||||
} else if (index == selectionModel()->selectedIndexes().first()) {
|
} else if (index == selectionModel()->selectedIndexes().first()) {
|
||||||
FieldInformation finfo(proto_tree_model_->protoNodeFromIndex(index).protoNode());
|
FieldInformation finfo(proto_tree_model_->protoNodeFromIndex(index));
|
||||||
|
|
||||||
if (finfo.isValid()) {
|
if (finfo.isValid()) {
|
||||||
emit fieldSelected(&finfo);
|
emit fieldSelected(&finfo);
|
||||||
|
@ -622,7 +636,7 @@ void ProtoTree::itemClicked(const QModelIndex &index)
|
||||||
|
|
||||||
void ProtoTree::itemDoubleClicked(const QModelIndex &index)
|
void ProtoTree::itemDoubleClicked(const QModelIndex &index)
|
||||||
{
|
{
|
||||||
FieldInformation finfo(proto_tree_model_->protoNodeFromIndex(index).protoNode());
|
FieldInformation finfo(proto_tree_model_->protoNodeFromIndex(index));
|
||||||
if (!finfo.isValid()) return;
|
if (!finfo.isValid()) return;
|
||||||
|
|
||||||
if (finfo.headerInfo().type == FT_FRAMENUM) {
|
if (finfo.headerInfo().type == FT_FRAMENUM) {
|
||||||
|
@ -679,7 +693,7 @@ void ProtoTree::saveSelectedField(QModelIndex &index)
|
||||||
selected_hfid_path_.clear();
|
selected_hfid_path_.clear();
|
||||||
QModelIndex save_index = index;
|
QModelIndex save_index = index;
|
||||||
while (save_index.isValid()) {
|
while (save_index.isValid()) {
|
||||||
FieldInformation finfo(proto_tree_model_->protoNodeFromIndex(save_index).protoNode());
|
FieldInformation finfo(proto_tree_model_->protoNodeFromIndex(save_index));
|
||||||
if (!finfo.isValid()) break;
|
if (!finfo.isValid()) break;
|
||||||
selected_hfid_path_.prepend(QPair<int,int>(save_index.row(), finfo.headerInfo().id));
|
selected_hfid_path_.prepend(QPair<int,int>(save_index.row(), finfo.headerInfo().id));
|
||||||
save_index = save_index.parent();
|
save_index = save_index.parent();
|
||||||
|
@ -697,7 +711,7 @@ void ProtoTree::restoreSelectedField()
|
||||||
int row = path_entry.first;
|
int row = path_entry.first;
|
||||||
int hf_id = path_entry.second;
|
int hf_id = path_entry.second;
|
||||||
cur_index = proto_tree_model_->index(row, 0, cur_index);
|
cur_index = proto_tree_model_->index(row, 0, cur_index);
|
||||||
FieldInformation finfo(proto_tree_model_->protoNodeFromIndex(cur_index).protoNode());
|
FieldInformation finfo(proto_tree_model_->protoNodeFromIndex(cur_index));
|
||||||
if (!finfo.isValid() || finfo.headerInfo().id != hf_id) {
|
if (!finfo.isValid() || finfo.headerInfo().id != hf_id) {
|
||||||
// Did not find the selected hfid path in the selected packet
|
// Did not find the selected hfid path in the selected packet
|
||||||
cur_index = QModelIndex();
|
cur_index = QModelIndex();
|
||||||
|
@ -780,7 +794,7 @@ bool ProtoTree::eventFilter(QObject * obj, QEvent * event)
|
||||||
> QApplication::startDragDistance())
|
> QApplication::startDragDistance())
|
||||||
{
|
{
|
||||||
QModelIndex idx = indexAt(drag_start_position_);
|
QModelIndex idx = indexAt(drag_start_position_);
|
||||||
FieldInformation finfo(proto_tree_model_->protoNodeFromIndex(idx).protoNode());
|
FieldInformation finfo(proto_tree_model_->protoNodeFromIndex(idx));
|
||||||
if (finfo.isValid())
|
if (finfo.isValid())
|
||||||
{
|
{
|
||||||
/* Hack to prevent QItemSelection taking the item which has been dragged over at start
|
/* Hack to prevent QItemSelection taking the item which has been dragged over at start
|
||||||
|
|
|
@ -71,6 +71,7 @@ private:
|
||||||
|
|
||||||
void saveSelectedField(QModelIndex &index);
|
void saveSelectedField(QModelIndex &index);
|
||||||
static void foreachTreeNode(proto_node *node, gpointer proto_tree_ptr);
|
static void foreachTreeNode(proto_node *node, gpointer proto_tree_ptr);
|
||||||
|
void foreachExpand(const QModelIndex &index);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void fieldSelected(FieldInformation *);
|
void fieldSelected(FieldInformation *);
|
||||||
|
|
|
@ -18,12 +18,12 @@ FieldInformation::FieldInformation(field_info *fi, QObject * parent)
|
||||||
parent_fi_ = NULL;
|
parent_fi_ = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
FieldInformation::FieldInformation(proto_node *node, QObject * parent)
|
FieldInformation::FieldInformation(ProtoNode *node, QObject * parent)
|
||||||
:QObject(parent)
|
:QObject(parent)
|
||||||
{
|
{
|
||||||
fi_ = NULL;
|
fi_ = NULL;
|
||||||
if (node) {
|
if (node && node->isValid()) {
|
||||||
fi_ = node->finfo;
|
fi_ = node->protoNode()->finfo;
|
||||||
}
|
}
|
||||||
parent_fi_ = NULL;
|
parent_fi_ = NULL;
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
|
|
||||||
#include <epan/proto.h>
|
#include <epan/proto.h>
|
||||||
|
|
||||||
|
#include <ui/qt/utils/proto_node.h>
|
||||||
#include "data_printer.h"
|
#include "data_printer.h"
|
||||||
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
|
@ -43,7 +44,7 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
explicit FieldInformation(field_info * fi, QObject * parent = Q_NULLPTR);
|
explicit FieldInformation(field_info * fi, QObject * parent = Q_NULLPTR);
|
||||||
explicit FieldInformation(proto_node * node, QObject * parent = Q_NULLPTR);
|
explicit FieldInformation(ProtoNode * node, QObject * parent = Q_NULLPTR);
|
||||||
|
|
||||||
bool isValid() const;
|
bool isValid() const;
|
||||||
bool isLink() const ;
|
bool isLink() const ;
|
||||||
|
|
|
@ -8,12 +8,35 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <ui/qt/utils/proto_node.h>
|
#include <ui/qt/utils/proto_node.h>
|
||||||
|
#include <ui/qt/utils/field_information.h>
|
||||||
|
|
||||||
#include <epan/prefs.h>
|
#include <epan/prefs.h>
|
||||||
|
|
||||||
ProtoNode::ProtoNode(proto_node *node) :
|
ProtoNode::ProtoNode(proto_node *node, ProtoNode *parent) :
|
||||||
node_(node)
|
node_(node), parent_(parent)
|
||||||
{
|
{
|
||||||
|
if (node_) {
|
||||||
|
|
||||||
|
int num_children = 0;
|
||||||
|
for (proto_node *child = node_->first_child; child; child = child->next) {
|
||||||
|
if (!isHidden(child)) {
|
||||||
|
num_children++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m_children.reserve(num_children);
|
||||||
|
|
||||||
|
for (proto_node *child = node_->first_child; child; child = child->next) {
|
||||||
|
if (!isHidden(child)) {
|
||||||
|
m_children.append(new ProtoNode(child, this));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ProtoNode::~ProtoNode()
|
||||||
|
{
|
||||||
|
qDeleteAll(m_children);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ProtoNode::isValid() const
|
bool ProtoNode::isValid() const
|
||||||
|
@ -26,12 +49,9 @@ bool ProtoNode::isChild() const
|
||||||
return node_ && node_->parent;
|
return node_ && node_->parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
ProtoNode ProtoNode::parentNode()
|
ProtoNode* ProtoNode::parentNode()
|
||||||
{
|
{
|
||||||
if (node_) {
|
return parent_;
|
||||||
return ProtoNode(node_->parent);
|
|
||||||
}
|
|
||||||
return ProtoNode(NULL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QString ProtoNode::labelText() const
|
QString ProtoNode::labelText() const
|
||||||
|
@ -71,15 +91,7 @@ int ProtoNode::childrenCount() const
|
||||||
{
|
{
|
||||||
if (!node_) return 0;
|
if (!node_) return 0;
|
||||||
|
|
||||||
int row_count = 0;
|
return (int)m_children.count();
|
||||||
ChildIterator kids = children();
|
|
||||||
while (kids.element().isValid())
|
|
||||||
{
|
|
||||||
row_count++;
|
|
||||||
kids.next();
|
|
||||||
}
|
|
||||||
|
|
||||||
return row_count;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int ProtoNode::row()
|
int ProtoNode::row()
|
||||||
|
@ -88,20 +100,7 @@ int ProtoNode::row()
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int cur_row = 0;
|
return (int)parent_->m_children.indexOf(const_cast<ProtoNode*>(this));
|
||||||
ProtoNode::ChildIterator kids = parentNode().children();
|
|
||||||
while (kids.element().isValid())
|
|
||||||
{
|
|
||||||
if (kids.element().protoNode() == node_) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
cur_row++;
|
|
||||||
kids.next();
|
|
||||||
}
|
|
||||||
if (! kids.element().isValid()) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
return cur_row;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ProtoNode::isExpanded() const
|
bool ProtoNode::isExpanded() const
|
||||||
|
@ -117,8 +116,17 @@ proto_node * ProtoNode::protoNode() const
|
||||||
return node_;
|
return node_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ProtoNode* ProtoNode::child(int row)
|
||||||
|
{
|
||||||
|
if (row < 0 || row >= m_children.size())
|
||||||
|
return nullptr;
|
||||||
|
return m_children.at(row);
|
||||||
|
}
|
||||||
|
|
||||||
ProtoNode::ChildIterator ProtoNode::children() const
|
ProtoNode::ChildIterator ProtoNode::children() const
|
||||||
{
|
{
|
||||||
|
/* XXX: Iterate over m_children instead?
|
||||||
|
* Somewhat faster as m_children already excludes any hidden items. */
|
||||||
proto_node *child = node_->first_child;
|
proto_node *child = node_->first_child;
|
||||||
while (child && isHidden(child)) {
|
while (child && isHidden(child)) {
|
||||||
child = child->next;
|
child = child->next;
|
||||||
|
|
|
@ -12,7 +12,9 @@
|
||||||
|
|
||||||
#include <config.h>
|
#include <config.h>
|
||||||
|
|
||||||
#include <ui/qt/utils/field_information.h>
|
#include <epan/proto.h>
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
|
||||||
class ProtoNode
|
class ProtoNode
|
||||||
{
|
{
|
||||||
|
@ -32,16 +34,18 @@ public:
|
||||||
NodePtr node;
|
NodePtr node;
|
||||||
};
|
};
|
||||||
|
|
||||||
explicit ProtoNode(proto_node * node = NULL);
|
explicit ProtoNode(proto_node * node = NULL, ProtoNode *parent = nullptr);
|
||||||
|
~ProtoNode();
|
||||||
|
|
||||||
bool isValid() const;
|
bool isValid() const;
|
||||||
bool isChild() const;
|
bool isChild() const;
|
||||||
bool isExpanded() const;
|
bool isExpanded() const;
|
||||||
|
|
||||||
proto_node *protoNode() const;
|
proto_node *protoNode() const;
|
||||||
|
ProtoNode *child(int row);
|
||||||
int childrenCount() const;
|
int childrenCount() const;
|
||||||
int row();
|
int row();
|
||||||
ProtoNode parentNode();
|
ProtoNode *parentNode();
|
||||||
|
|
||||||
QString labelText() const;
|
QString labelText() const;
|
||||||
|
|
||||||
|
@ -49,6 +53,8 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
proto_node * node_;
|
proto_node * node_;
|
||||||
|
QVector<ProtoNode*>m_children;
|
||||||
|
ProtoNode *parent_;
|
||||||
static bool isHidden(proto_node * node);
|
static bool isHidden(proto_node * node);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue