Qt: Remember selected item in packet tree

Previously, changing a packet in the packet list would lose the
currently selected field item in the packet tree. After this patch, this
issue no longer occurs because the selected field is focussed again.

The approach is to remember the header field ID on the path from a field
to its root. Limitations of the current simple approach is that multiple
fields/trees under a tree might result in the wrong selection. This is
better than nothing though.

This patch greatly helps analyzing a capture file which has the same
format, except that I need to check a data source for decrypted data.
Previously I would have to scroll down and select the field to see the
data source which also made it impossible to quickly switch between
packets and compare them.

Change-Id: Ic113ca9245fd9faa10f91182794c50cfde8d10f4
Reviewed-on: https://code.wireshark.org/review/14697
Reviewed-by: Alexis La Goutte <alexis.lagoutte@gmail.com>
Tested-by: Alexis La Goutte <alexis.lagoutte@gmail.com>
Reviewed-by: Peter Wu <peter@lekensteyn.nl>
This commit is contained in:
Peter Wu 2016-03-30 00:47:12 +02:00
parent 959fe0e18b
commit fd4808fbec
3 changed files with 45 additions and 0 deletions

View File

@ -503,6 +503,8 @@ void PacketList::selectionChanged (const QItemSelection & selected, const QItemS
if (fi && proto_tree_) {
proto_tree_->selectField(fi);
}
} else if (!cap_file_->search_in_progress) {
proto_tree_->restoreSelectedField();
}
}

View File

@ -433,6 +433,8 @@ void ProtoTree::updateSelectionStatus(QTreeWidgetItem* item)
item_info.append(QString(tr(", %1 bytes")).arg(finfo_length));
}
saveSelectedField(item);
emit protoItemSelected("");
emit protoItemSelected(NULL);
emit protoItemSelected(item_info);
@ -602,6 +604,44 @@ void ProtoTree::selectField(field_info *fi)
}
}
// Remember the currently focussed field based on:
// - current hf_id (obviously)
// - parent items (to avoid selecting a text item in a different tree)
// - position within a tree if there are multiple items (wishlist)
static QList<int> serializeAsPath(QTreeWidgetItem *item)
{
QList<int> path;
do {
field_info *fi = item->data(0, Qt::UserRole).value<field_info *>();
path.prepend(fi->hfinfo->id);
} while ((item = item->parent()));
return path;
}
void ProtoTree::saveSelectedField(QTreeWidgetItem *item)
{
selected_field_path_ = serializeAsPath(item);
}
// Try to focus a tree item which was previously also visible
void ProtoTree::restoreSelectedField()
{
if (selected_field_path_.isEmpty()) {
return;
}
int last_hf_id = selected_field_path_.last();
QTreeWidgetItemIterator iter(this);
while (*iter) {
field_info *fi = (*iter)->data(0, Qt::UserRole).value<field_info *>();
if (last_hf_id == fi->hfinfo->id &&
serializeAsPath(*iter) == selected_field_path_) {
setCurrentItem(*iter);
scrollToItem(*iter);
break;
}
iter++;
}
}
/*
* Editor modelines
*

View File

@ -45,6 +45,8 @@ public:
void selectField(field_info *fi);
void closeContextMenu();
void clear();
void saveSelectedField(QTreeWidgetItem *);
void restoreSelectedField();
protected:
virtual void contextMenuEvent(QContextMenuEvent *event);
@ -60,6 +62,7 @@ private:
QList<QAction *> copy_actions_;
QFont mono_font_;
int column_resize_timer_;
QList<int> selected_field_path_;
signals:
void protoItemSelected(const QString &);