diff --git a/epan/proto.c b/epan/proto.c index c701d30182..d0922f6d6b 100644 --- a/epan/proto.c +++ b/epan/proto.c @@ -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); diff --git a/ui/qt/label_stack.cpp b/ui/qt/label_stack.cpp index a41132a6cc..142d097716 100644 --- a/ui/qt/label_stack.cpp +++ b/ui/qt/label_stack.cpp @@ -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 += "}"; diff --git a/ui/qt/main_status_bar.cpp b/ui/qt/main_status_bar.cpp index 90f944a148..894c2ccb51 100644 --- a/ui/qt/main_status_bar.cpp +++ b/ui/qt/main_status_bar.cpp @@ -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(""); } diff --git a/ui/qt/main_window.h b/ui/qt/main_window.h index c7492ae055..0dba4513df 100644 --- a/ui/qt/main_window.h +++ b/ui/qt/main_window.h @@ -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(); diff --git a/ui/qt/main_window_slots.cpp b/ui/qt/main_window_slots.cpp index 42717d87ff..bc221b133e 100644 --- a/ui/qt/main_window_slots.cpp +++ b/ui/qt/main_window_slots.cpp @@ -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); } diff --git a/ui/qt/packet_list.cpp b/ui/qt/packet_list.cpp index bd4a9bc0d5..d19e9f5637 100644 --- a/ui/qt/packet_list.cpp +++ b/ui/qt/packet_list.cpp @@ -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); +// " \n" +// " \n" +// " \n" +// " \n" +// " \n" + ctx_menu_.addSeparator(); +// " \n" + ctx_menu_.addSeparator(); + submenu = new QMenu(tr("Apply as Filter")); + ctx_menu_.addMenu(submenu); + submenu->addAction(window()->findChild("actionAnalyzeAAFSelected")); + submenu->addAction(window()->findChild("actionAnalyzeAAFNotSelected")); + submenu->addAction(window()->findChild("actionAnalyzeAAFAndSelected")); + submenu->addAction(window()->findChild("actionAnalyzeAAFOrSelected")); + submenu->addAction(window()->findChild("actionAnalyzeAAFAndNotSelected")); + submenu->addAction(window()->findChild("actionAnalyzeAAFOrNotSelected")); + filter_actions_ << submenu->actions(); + submenu = new QMenu(tr("Prepare a Filter")); + ctx_menu_.addMenu(submenu); + submenu->addAction(window()->findChild("actionAnalyzePAFSelected")); + submenu->addAction(window()->findChild("actionAnalyzePAFNotSelected")); + submenu->addAction(window()->findChild("actionAnalyzePAFAndSelected")); + submenu->addAction(window()->findChild("actionAnalyzePAFOrSelected")); + submenu->addAction(window()->findChild("actionAnalyzePAFAndNotSelected")); + submenu->addAction(window()->findChild("actionAnalyzePAFOrNotSelected")); + filter_actions_ << submenu->actions(); + submenu = new QMenu(tr("Colorize with Filter")); +// " \n" +// " \n" +// " \n" +// " \n" +// " \n" +// " \n" +// " \n" +// " \n" +// " \n" +// " \n" +// " \n" +// " \n" +// " \n" +// " \n" +// " \n" +// " \n" +// " \n" +// " \n" +// " \n" +// " \n" +// " \n" +// " \n" +// " \n" +// " \n" +// " \n" +// " \n" +// " \n" +// " \n" +// " \n" +// " \n" +// " \n" +// " \n" +// " \n" +// " \n" +// " \n" +// " \n" +// " \n" +// " \n" +// " \n" +// " \n" +// " \n" +// " \n" +// " \n" +// " \n" +// " \n" +// " \n" +// " \n" +// " \n" +// " \n" +// " \n" +// " \n" +// " \n" +// " \n" +// " \n" +// " \n" +// " \n" +// " \n" +// " \n" +// " \n" +// " \n" +// " \n" +// " \n" +// " \n" +// " \n" +// " \n" +// " \n" +// " \n" +// " \n" +// " \n" +// " \n" +// " \n" +// " \n" +// " \n" + ctx_menu_.addSeparator(); +// " \n" + submenu = new QMenu(tr("Copy")); + ctx_menu_.addMenu(submenu); + // " \n" + // " \n" + submenu->addAction(window()->findChild("actionEditCopyAsFilter")); + filter_actions_ << window()->findChild("actionEditCopyAsFilter"); + submenu->addSeparator(); + subsubmenu = new QMenu(tr("Bytes")); + submenu->addMenu(subsubmenu); + // " \n" + // " \n" + // " \n" + ctx_menu_.addSeparator(); +// " \n" +// " \n" + ctx_menu_.addSeparator(); +// " \n" +// " \n" +// " \n" +// " \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 diff --git a/ui/qt/packet_list.h b/ui/qt/packet_list.h index e96d95300c..36432f0bf5 100644 --- a/ui/qt/packet_list.h +++ b/ui/qt/packet_list.h @@ -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 submenus_; + QList filter_actions_; + int ctx_column_; signals: