Add a context menu to the packet list and fill in the

apply/match-related actions. Have matchSelectedFilter figure out our
filter strings, which lets us remove duplicate code in the apply/match
action slots. Remove some leftover code from an experiment.

Adjust the temporary message colors in the status bar and label stack.

Add a NULL check to construct_match_selected_string.

svn path=/trunk/; revision=46449
This commit is contained in:
Gerald Combs 2012-12-07 20:08:00 +00:00
parent 4ca2e780bf
commit c9d4240196
7 changed files with 244 additions and 134 deletions

View File

@ -6948,6 +6948,9 @@ construct_match_selected_string(field_info *finfo, epan_dissect_t *edt,
guint8 c;
gchar is_signed_num = FALSE;
if (!finfo)
return FALSE;
hfinfo = finfo->hfinfo;
DISSECTOR_ASSERT(hfinfo);
abbrev_len = (int) strlen(hfinfo->abbrev);

View File

@ -64,11 +64,12 @@ void LabelStack::fillLabel() {
if (si->ctx == temporary_ctx_) {
style_sheet += QString(
" border-radius: 0.25em;"
" color: black;"
" background-color: #%1;"
)
.arg(tango_butter_4, 6, 16, QChar('0'));
" border-radius: 0.25em;"
" color: #%1;"
" background-color: #%2;"
)
.arg(tango_aluminium_6, 6, 16, QChar('0'))
.arg(tango_butter_2, 6, 16, QChar('0'));
}
style_sheet += "}";

View File

@ -293,10 +293,12 @@ void MainStatusBar::toggleBackground(bool enabled)
if (enabled) {
setStyleSheet(QString(
"QStatusBar {"
" background-color: #%1;"
" color: #%1;"
" background-color: #%2;"
"}"
)
.arg(tango_butter_4, 6, 16, QChar('0')));
.arg(tango_aluminium_6, 6, 16, QChar('0'))
.arg(tango_butter_2, 6, 16, QChar('0')));
} else {
setStyleSheet("");
}

View File

@ -204,7 +204,7 @@ private slots:
void on_actionGoGoToPacket_triggered();
void resetPreviousFocus();
void matchSelectedFilter(QString &field_filter, MainWindow::MatchSelected filter_type, bool apply = false, bool copy_only = false);
void matchSelectedFilter(MainWindow::MatchSelected filter_type, bool apply = false, bool copy_only = false);
void on_actionAnalyzeAAFSelected_triggered();
void on_actionAnalyzeAAFNotSelected_triggered();
void on_actionAnalyzeAAFAndSelected_triggered();

View File

@ -942,11 +942,7 @@ void MainWindow::on_actionEditCopyValue_triggered()
void MainWindow::on_actionEditCopyAsFilter_triggered()
{
if (!cap_file_) return;
QString filter = proto_construct_match_selected_string(cap_file_->finfo_selected,
cap_file_->edt);
matchSelectedFilter(filter, MatchSelectedReplace, false, true);
matchSelectedFilter(MatchSelectedReplace, false, true);
}
// View Menu
@ -958,13 +954,25 @@ void MainWindow::on_actionEditCopyAsFilter_triggered()
// Analyze Menu
// XXX This should probably be somewhere else.
void MainWindow::matchSelectedFilter(QString &field_filter, MainWindow::MatchSelected filter_type, bool apply, bool copy_only)
void MainWindow::matchSelectedFilter(MainWindow::MatchSelected filter_type, bool apply, bool copy_only)
{
QString field_filter;
QString cur_filter;
QString new_filter;
if (field_filter.length() < 1) {
QString err = tr("Couldn't build a filter. Try another item.");
if (packet_list_->contextMenuActive()) {
field_filter = packet_list_->getFilterFromRowAndColumn();
} else if (cap_file_ && cap_file_->finfo_selected) {
field_filter = proto_construct_match_selected_string(cap_file_->finfo_selected,
cap_file_->edt);
} else {
return;
}
if (field_filter.isEmpty()) {
QString err = tr("No filter available. Try another ");
err.append(packet_list_->contextMenuActive() ? "column" : "item");
err.append(".");
main_ui_->statusBar->pushTemporaryStatus(err);
return;
}
@ -1028,158 +1036,62 @@ void MainWindow::matchSelectedFilter(QString &field_filter, MainWindow::MatchSel
void MainWindow::on_actionAnalyzeAAFSelected_triggered()
{
QString filter;
if (packet_list_->contextMenuActive()) {
// filter = packet_list_->getSelectedColumnFilter();
} else {
filter = proto_construct_match_selected_string(cap_file_->finfo_selected,
cap_file_->edt);
}
matchSelectedFilter(filter, MatchSelectedReplace, true, false);
matchSelectedFilter(MatchSelectedReplace, true, false);
}
void MainWindow::on_actionAnalyzeAAFNotSelected_triggered()
{
QString filter;
if (packet_list_->contextMenuActive()) {
// filter = packet_list_->getSelectedColumnFilter();
} else {
filter = proto_construct_match_selected_string(cap_file_->finfo_selected,
cap_file_->edt);
}
matchSelectedFilter(filter, MatchSelectedNot, true, false);
matchSelectedFilter(MatchSelectedNot, true, false);
}
void MainWindow::on_actionAnalyzeAAFAndSelected_triggered()
{
QString filter;
if (packet_list_->contextMenuActive()) {
// filter = packet_list_->getSelectedColumnFilter();
} else {
filter = proto_construct_match_selected_string(cap_file_->finfo_selected,
cap_file_->edt);
}
matchSelectedFilter(filter, MatchSelectedAnd, true, false);
matchSelectedFilter(MatchSelectedAnd, true, false);
}
void MainWindow::on_actionAnalyzeAAFOrSelected_triggered()
{
QString filter;
if (packet_list_->contextMenuActive()) {
// filter = packet_list_->getSelectedColumnFilter();
} else {
filter = proto_construct_match_selected_string(cap_file_->finfo_selected,
cap_file_->edt);
}
matchSelectedFilter(filter, MatchSelectedOr, true, false);
matchSelectedFilter(MatchSelectedOr, true, false);
}
void MainWindow::on_actionAnalyzeAAFAndNotSelected_triggered()
{
QString filter;
if (packet_list_->contextMenuActive()) {
// filter = packet_list_->getSelectedColumnFilter();
} else {
filter = proto_construct_match_selected_string(cap_file_->finfo_selected,
cap_file_->edt);
}
matchSelectedFilter(filter, MatchSelectedAndNot, true, false);
matchSelectedFilter(MatchSelectedAndNot, true, false);
}
void MainWindow::on_actionAnalyzeAAFOrNotSelected_triggered()
{
QString filter;
if (packet_list_->contextMenuActive()) {
// filter = packet_list_->getSelectedColumnFilter();
} else {
filter = proto_construct_match_selected_string(cap_file_->finfo_selected,
cap_file_->edt);
}
matchSelectedFilter(filter, MatchSelectedOrNot, true, false);
matchSelectedFilter(MatchSelectedOrNot, true, false);
}
void MainWindow::on_actionAnalyzePAFSelected_triggered()
{
QString filter;
if (packet_list_->contextMenuActive()) {
// filter = packet_list_->getSelectedColumnFilter();
} else {
filter = proto_construct_match_selected_string(cap_file_->finfo_selected,
cap_file_->edt);
}
matchSelectedFilter(filter, MatchSelectedReplace, false, false);
matchSelectedFilter(MatchSelectedReplace, false, false);
}
void MainWindow::on_actionAnalyzePAFNotSelected_triggered()
{
QString filter;
if (packet_list_->contextMenuActive()) {
// filter = packet_list_->getSelectedColumnFilter();
} else {
filter = proto_construct_match_selected_string(cap_file_->finfo_selected,
cap_file_->edt);
}
matchSelectedFilter(filter, MatchSelectedNot, false, false);
matchSelectedFilter(MatchSelectedNot, false, false);
}
void MainWindow::on_actionAnalyzePAFAndSelected_triggered()
{
QString filter;
if (packet_list_->contextMenuActive()) {
// filter = packet_list_->getSelectedColumnFilter();
} else {
filter = proto_construct_match_selected_string(cap_file_->finfo_selected,
cap_file_->edt);
}
matchSelectedFilter(filter, MatchSelectedAnd, false, false);
matchSelectedFilter(MatchSelectedAnd, false, false);
}
void MainWindow::on_actionAnalyzePAFOrSelected_triggered()
{
QString filter;
if (packet_list_->contextMenuActive()) {
// filter = packet_list_->getSelectedColumnFilter();
} else {
filter = proto_construct_match_selected_string(cap_file_->finfo_selected,
cap_file_->edt);
}
matchSelectedFilter(filter, MatchSelectedOr, false, false);
matchSelectedFilter(MatchSelectedOr, false, false);
}
void MainWindow::on_actionAnalyzePAFAndNotSelected_triggered()
{
QString filter;
if (packet_list_->contextMenuActive()) {
// filter = packet_list_->getSelectedColumnFilter();
} else {
filter = proto_construct_match_selected_string(cap_file_->finfo_selected,
cap_file_->edt);
}
matchSelectedFilter(filter, MatchSelectedAndNot, false, false);
matchSelectedFilter(MatchSelectedAndNot, false, false);
}
void MainWindow::on_actionAnalyzePAFOrNotSelected_triggered()
{
QString filter;
if (packet_list_->contextMenuActive()) {
// filter = packet_list_->getSelectedColumnFilter();
} else {
filter = proto_construct_match_selected_string(cap_file_->finfo_selected,
cap_file_->edt);
}
matchSelectedFilter(filter, MatchSelectedOrNot, false, false);
matchSelectedFilter(MatchSelectedOrNot, false, false);
}

View File

@ -217,19 +217,146 @@ PacketList::PacketList(QWidget *parent) :
QTreeView(parent),
proto_tree_(NULL),
byte_view_tab_(NULL),
cap_file_(NULL)
cap_file_(NULL),
ctx_column_(-1)
{
QMenu *submenu, *subsubmenu;
setItemsExpandable(FALSE);
setRootIsDecorated(FALSE);
setSortingEnabled(TRUE);
setUniformRowHeights(TRUE);
setAccessibleName("Packet list");
packet_list_model_ = new PacketListModel(this, cap_file_);
setModel(packet_list_model_);
packet_list_model_->setColorEnabled(true); // We don't yet fetch color settings.
// packet_list_model_->setColorEnabled(recent.packet_list_colorize);
// " <menuitem name='MarkPacket' action='/MarkPacket'/>\n"
// " <menuitem name='IgnorePacket' action='/IgnorePacket'/>\n"
// " <menuitem name='SetTimeReference' action='/Set Time Reference'/>\n"
// " <menuitem name='TimeShift' action='/TimeShift'/>\n"
// " <menuitem name='AddEditPktComment' action='/Edit/AddEditPktComment'/>\n"
ctx_menu_.addSeparator();
// " <menuitem name='ManuallyResolveAddress' action='/ManuallyResolveAddress'/>\n"
ctx_menu_.addSeparator();
submenu = new QMenu(tr("Apply as Filter"));
ctx_menu_.addMenu(submenu);
submenu->addAction(window()->findChild<QAction *>("actionAnalyzeAAFSelected"));
submenu->addAction(window()->findChild<QAction *>("actionAnalyzeAAFNotSelected"));
submenu->addAction(window()->findChild<QAction *>("actionAnalyzeAAFAndSelected"));
submenu->addAction(window()->findChild<QAction *>("actionAnalyzeAAFOrSelected"));
submenu->addAction(window()->findChild<QAction *>("actionAnalyzeAAFAndNotSelected"));
submenu->addAction(window()->findChild<QAction *>("actionAnalyzeAAFOrNotSelected"));
filter_actions_ << submenu->actions();
submenu = new QMenu(tr("Prepare a Filter"));
ctx_menu_.addMenu(submenu);
submenu->addAction(window()->findChild<QAction *>("actionAnalyzePAFSelected"));
submenu->addAction(window()->findChild<QAction *>("actionAnalyzePAFNotSelected"));
submenu->addAction(window()->findChild<QAction *>("actionAnalyzePAFAndSelected"));
submenu->addAction(window()->findChild<QAction *>("actionAnalyzePAFOrSelected"));
submenu->addAction(window()->findChild<QAction *>("actionAnalyzePAFAndNotSelected"));
submenu->addAction(window()->findChild<QAction *>("actionAnalyzePAFOrNotSelected"));
filter_actions_ << submenu->actions();
submenu = new QMenu(tr("Colorize with Filter"));
// " <menu name= 'ConversationFilter' action='/Conversation Filter'>\n"
// " <menuitem name='Ethernet' action='/Conversation Filter/Ethernet'/>\n"
// " <menuitem name='IP' action='/Conversation Filter/IP'/>\n"
// " <menuitem name='TCP' action='/Conversation Filter/TCP'/>\n"
// " <menuitem name='UDP' action='/Conversation Filter/UDP'/>\n"
// " <menuitem name='PN-CBA' action='/Conversation Filter/PN-CBA'/>\n"
// " <menu name= 'ColorizeConversation' action='/Colorize Conversation'>\n"
// " <menu name= 'Ethernet' action='/Colorize Conversation/Ethernet'>\n"
// " <menuitem name='Color1' action='/Colorize Conversation/Ethernet/Color 1'/>\n"
// " <menuitem name='Color2' action='/Colorize Conversation/Ethernet/Color 2'/>\n"
// " <menuitem name='Color3' action='/Colorize Conversation/Ethernet/Color 3'/>\n"
// " <menuitem name='Color4' action='/Colorize Conversation/Ethernet/Color 4'/>\n"
// " <menuitem name='Color5' action='/Colorize Conversation/Ethernet/Color 5'/>\n"
// " <menuitem name='Color6' action='/Colorize Conversation/Ethernet/Color 6'/>\n"
// " <menuitem name='Color7' action='/Colorize Conversation/Ethernet/Color 7'/>\n"
// " <menuitem name='Color8' action='/Colorize Conversation/Ethernet/Color 8'/>\n"
// " <menuitem name='Color9' action='/Colorize Conversation/Ethernet/Color 9'/>\n"
// " <menuitem name='Color10' action='/Colorize Conversation/Ethernet/Color 10'/>\n"
// " <menuitem name='NewColoringRule' action='/Colorize Conversation/Ethernet/New Coloring Rule'/>\n"
// " <menu name= 'IP' action='/Colorize Conversation/IP'>\n"
// " <menuitem name='Color1' action='/Colorize Conversation/IP/Color 1'/>\n"
// " <menuitem name='Color2' action='/Colorize Conversation/IP/Color 2'/>\n"
// " <menuitem name='Color3' action='/Colorize Conversation/IP/Color 3'/>\n"
// " <menuitem name='Color4' action='/Colorize Conversation/IP/Color 4'/>\n"
// " <menuitem name='Color5' action='/Colorize Conversation/IP/Color 5'/>\n"
// " <menuitem name='Color6' action='/Colorize Conversation/IP/Color 6'/>\n"
// " <menuitem name='Color7' action='/Colorize Conversation/IP/Color 7'/>\n"
// " <menuitem name='Color8' action='/Colorize Conversation/IP/Color 8'/>\n"
// " <menuitem name='Color9' action='/Colorize Conversation/IP/Color 9'/>\n"
// " <menuitem name='Color10' action='/Colorize Conversation/IP/Color 10'/>\n"
// " <menuitem name='NewColoringRule' action='/Colorize Conversation/IP/New Coloring Rule'/>\n"
// " <menu name= 'TCP' action='/Colorize Conversation/TCP'>\n"
// " <menuitem name='Color1' action='/Colorize Conversation/TCP/Color 1'/>\n"
// " <menuitem name='Color2' action='/Colorize Conversation/TCP/Color 2'/>\n"
// " <menuitem name='Color3' action='/Colorize Conversation/TCP/Color 3'/>\n"
// " <menuitem name='Color4' action='/Colorize Conversation/TCP/Color 4'/>\n"
// " <menuitem name='Color5' action='/Colorize Conversation/TCP/Color 5'/>\n"
// " <menuitem name='Color6' action='/Colorize Conversation/TCP/Color 6'/>\n"
// " <menuitem name='Color7' action='/Colorize Conversation/TCP/Color 7'/>\n"
// " <menuitem name='Color8' action='/Colorize Conversation/TCP/Color 8'/>\n"
// " <menuitem name='Color9' action='/Colorize Conversation/TCP/Color 9'/>\n"
// " <menuitem name='Color10' action='/Colorize Conversation/TCP/Color 10'/>\n"
// " <menuitem name='NewColoringRule' action='/Colorize Conversation/TCP/New Coloring Rule'/>\n"
// " <menu name= 'UDP' action='/Colorize Conversation/UDP'>\n"
// " <menuitem name='Color1' action='/Colorize Conversation/UDP/Color 1'/>\n"
// " <menuitem name='Color2' action='/Colorize Conversation/UDP/Color 2'/>\n"
// " <menuitem name='Color3' action='/Colorize Conversation/UDP/Color 3'/>\n"
// " <menuitem name='Color4' action='/Colorize Conversation/UDP/Color 4'/>\n"
// " <menuitem name='Color5' action='/Colorize Conversation/UDP/Color 5'/>\n"
// " <menuitem name='Color6' action='/Colorize Conversation/UDP/Color 6'/>\n"
// " <menuitem name='Color7' action='/Colorize Conversation/UDP/Color 7'/>\n"
// " <menuitem name='Color8' action='/Colorize Conversation/UDP/Color 8'/>\n"
// " <menuitem name='Color9' action='/Colorize Conversation/UDP/Color 9'/>\n"
// " <menuitem name='Color10' action='/Colorize Conversation/UDP/Color 10'/>\n"
// " <menuitem name='NewColoringRule' action='/Colorize Conversation/UDP/New Coloring Rule'/>\n"
// " <menu name= 'PN-CBA' action='/Colorize Conversation/PN-CBA'>\n"
// " <menuitem name='Color1' action='/Colorize Conversation/PN-CBA/Color 1'/>\n"
// " <menuitem name='Color2' action='/Colorize Conversation/PN-CBA/Color 2'/>\n"
// " <menuitem name='Color3' action='/Colorize Conversation/PN-CBA/Color 3'/>\n"
// " <menuitem name='Color4' action='/Colorize Conversation/PN-CBA/Color 4'/>\n"
// " <menuitem name='Color5' action='/Colorize Conversation/PN-CBA/Color 5'/>\n"
// " <menuitem name='Color6' action='/Colorize Conversation/PN-CBA/Color 6'/>\n"
// " <menuitem name='Color7' action='/Colorize Conversation/PN-CBA/Color 7'/>\n"
// " <menuitem name='Color8' action='/Colorize Conversation/PN-CBA/Color 8'/>\n"
// " <menuitem name='Color9' action='/Colorize Conversation/PN-CBA/Color 9'/>\n"
// " <menuitem name='Color10' action='/Colorize Conversation/PN-CBA/Color 10'/>\n"
// " <menuitem name='NewColoringRule' action='/Colorize Conversation/PN-CBA/New Coloring Rule'/>\n"
// " <menu name= 'SCTP' action='/SCTP'>\n"
// " <menuitem name='AnalysethisAssociation' action='/SCTP/Analyse this Association'/>\n"
// " <menuitem name='PrepareFilterforthisAssociation' action='/SCTP/Prepare Filter for this Association'/>\n"
// " <menuitem name='FollowTCPStream' action='/Follow TCP Stream'/>\n"
// " <menuitem name='FollowUDPStream' action='/Follow UDP Stream'/>\n"
// " <menuitem name='FollowSSLStream' action='/Follow SSL Stream'/>\n"
ctx_menu_.addSeparator();
// " <menu name= 'Copy' action='/Copy'>\n"
submenu = new QMenu(tr("Copy"));
ctx_menu_.addMenu(submenu);
// " <menuitem name='SummaryTxt' action='/Copy/SummaryTxt'/>\n"
// " <menuitem name='SummaryCSV' action='/Copy/SummaryCSV'/>\n"
submenu->addAction(window()->findChild<QAction *>("actionEditCopyAsFilter"));
filter_actions_ << window()->findChild<QAction *>("actionEditCopyAsFilter");
submenu->addSeparator();
subsubmenu = new QMenu(tr("Bytes"));
submenu->addMenu(subsubmenu);
// " <menuitem name='OffsetHexText' action='/Copy/Bytes/OffsetHexText'/>\n"
// " <menuitem name='OffsetHex' action='/Copy/Bytes/OffsetHex'/>\n"
// " <menuitem name='PrintableTextOnly' action='/Copy/Bytes/PrintableTextOnly'/>\n"
ctx_menu_.addSeparator();
// " <menuitem name='HexStream' action='/Copy/Bytes/HexStream'/>\n"
// " <menuitem name='BinaryStream' action='/Copy/Bytes/BinaryStream'/>\n"
ctx_menu_.addSeparator();
// " <menuitem name='ProtocolPreferences' action='/ProtocolPreferences'/>\n"
// " <menuitem name='DecodeAs' action='/DecodeAs'/>\n"
// " <menuitem name='Print' action='/Print'/>\n"
// " <menuitem name='ShowPacketinNewWindow' action='/ShowPacketinNewWindow'/>\n"
g_assert(gbl_cur_packet_list == NULL);
gbl_cur_packet_list = this;
}
@ -303,16 +430,17 @@ void PacketList::selectionChanged (const QItemSelection & selected, const QItemS
void PacketList::contextMenuEvent(QContextMenuEvent *event)
{
foreach (QMenu *submenu, submenus_) {
foreach (QAction *a, submenu->actions()) {
a->setData(true);
}
bool fa_enabled = filter_actions_[0]->isEnabled();
QAction *act;
foreach (act, filter_actions_) {
act->setEnabled(true);
}
ctx_column_ = columnAt(event->x());
ctx_menu_.exec(event->globalPos());
foreach (QMenu *submenu, submenus_) {
foreach (QAction *a, submenu->actions()) {
a->setData(QVariant());
}
ctx_column_ = -1;
foreach (act, filter_actions_) {
act->setEnabled(fa_enabled);
}
}
@ -369,7 +497,68 @@ void PacketList::writeRecent(FILE *rf) {
bool PacketList::contextMenuActive()
{
return ctx_menu_.isVisible();
return ctx_column_ >= 0 ? true : false;
}
QString &PacketList::getFilterFromRowAndColumn()
{
frame_data *fdata;
QString &filter = *new QString();
int row = currentIndex().row();
if (!cap_file_ || !packet_list_model_ || ctx_column_ < 0 || ctx_column_ >= cap_file_->cinfo.num_cols) return filter;
fdata = (frame_data *) packet_list_model_->getRowFdata(row);
if (fdata != NULL) {
epan_dissect_t edt;
if (!cf_read_frame(cap_file_, fdata))
return filter; /* error reading the frame */
/* proto tree, visible. We need a proto tree if there's custom columns */
epan_dissect_init(&edt, have_custom_cols(&cap_file_->cinfo), FALSE);
col_custom_prime_edt(&edt, &cap_file_->cinfo);
epan_dissect_run(&edt, &cap_file_->phdr, cap_file_->pd, fdata, &cap_file_->cinfo);
epan_dissect_fill_in_columns(&edt, TRUE, TRUE);
if ((cap_file_->cinfo.col_custom_occurrence[ctx_column_]) ||
(strchr (cap_file_->cinfo.col_expr.col_expr_val[ctx_column_], ',') == NULL))
{
/* Only construct the filter when a single occurrence is displayed
* otherwise we might end up with a filter like "ip.proto==1,6".
*
* Or do we want to be able to filter on multiple occurrences so that
* the filter might be calculated as "ip.proto==1 && ip.proto==6"
* instead?
*/
if (strlen(cap_file_->cinfo.col_expr.col_expr[ctx_column_]) != 0 &&
strlen(cap_file_->cinfo.col_expr.col_expr_val[ctx_column_]) != 0) {
/* leak a little but safer than ep_ here */
if (cap_file_->cinfo.col_fmt[ctx_column_] == COL_CUSTOM) {
header_field_info *hfi = proto_registrar_get_byname(cap_file_->cinfo.col_custom_field[ctx_column_]);
if (hfi->parent == -1) {
/* Protocol only */
filter.append(cap_file_->cinfo.col_expr.col_expr[ctx_column_]);
} else if (hfi->type == FT_STRING) {
/* Custom string, add quotes */
filter.append(QString("%1 == \"%2\"")
.arg(cap_file_->cinfo.col_expr.col_expr[ctx_column_])
.arg(cap_file_->cinfo.col_expr.col_expr_val[ctx_column_]));
}
}
if (filter.isEmpty()) {
filter.append(QString("%1 == %2")
.arg(cap_file_->cinfo.col_expr.col_expr[ctx_column_])
.arg(cap_file_->cinfo.col_expr.col_expr_val[ctx_column_]));
}
}
}
epan_dissect_cleanup(&edt);
}
return filter;
}
// Slots

View File

@ -45,6 +45,7 @@ public:
void clear();
void writeRecent(FILE *rf);
bool contextMenuActive();
QString &getFilterFromRowAndColumn();
protected:
void showEvent (QShowEvent *event);
@ -58,6 +59,8 @@ private:
capture_file *cap_file_;
QMenu ctx_menu_;
QList<QMenu *> submenus_;
QList<QAction *> filter_actions_;
int ctx_column_;
signals: