diff options
Diffstat (limited to 'ui/qt/packet_list.cpp')
-rw-r--r-- | ui/qt/packet_list.cpp | 213 |
1 files changed, 123 insertions, 90 deletions
diff --git a/ui/qt/packet_list.cpp b/ui/qt/packet_list.cpp index ae6f0f51..896c66fe 100644 --- a/ui/qt/packet_list.cpp +++ b/ui/qt/packet_list.cpp @@ -11,8 +11,6 @@ #include "config.h" -#include <glib.h> - #include "file.h" #include <epan/epan.h> @@ -36,6 +34,7 @@ #include "ui/util.h" #include "wiretap/wtap_opttypes.h" +#include "wsutil/filesystem.h" #include "wsutil/str_util.h" #include <wsutil/wslog.h> @@ -49,6 +48,7 @@ #include "main_application.h" #include <ui/qt/utils/data_printer.h> #include <ui/qt/utils/frame_information.h> +#include <ui/qt/utils/profile_switcher.h> #include <ui/qt/utils/variant_pointer.h> #include <ui/qt/models/pref_models.h> #include <ui/qt/widgets/packet_list_header.h> @@ -93,7 +93,7 @@ // 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 // capture files against packet lists and models. -static PacketList *gbl_cur_packet_list = NULL; +static PacketList *gbl_cur_packet_list; const int max_comments_to_fetch_ = 20000000; // Arbitrary const int overlay_update_interval_ = 100; // 250; // Milliseconds. @@ -102,18 +102,18 @@ const int overlay_update_interval_ = 100; // 250; // Milliseconds. /* * Given a frame_data structure, scroll to and select the row in the * packet list corresponding to that frame. If there is no such - * row, return FALSE, otherwise return TRUE. + * row, return false, otherwise return true. */ -gboolean +bool packet_list_select_row_from_data(frame_data *fdata_needle) { if (! gbl_cur_packet_list || ! gbl_cur_packet_list->model()) - return FALSE; + return false; PacketListModel * model = qobject_cast<PacketListModel *>(gbl_cur_packet_list->model()); if (! model) - return FALSE; + return false; model->flushVisibleRows(); int row = -1; @@ -132,10 +132,32 @@ packet_list_select_row_from_data(frame_data *fdata_needle) gbl_cur_packet_list->selectionModel()->clearSelection(); gbl_cur_packet_list->selectionModel()->setCurrentIndex(model->index(row, 0), QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows); gbl_cur_packet_list->scrollTo(gbl_cur_packet_list->currentIndex(), PacketList::PositionAtCenter); - return TRUE; + return true; } - return FALSE; + return false; +} + +/* + * Given a field_info, select the field (which will scroll to it in + * the main ProtoTree, etc.) This is kind of an odd place for it, + * but we call this when performing Find Packet in lieu of changing the + * selected frame (the function above), because we found a match in the + * same frame as the currently selected one. + */ +bool +packet_list_select_finfo(field_info *fi) +{ + if (! gbl_cur_packet_list || ! gbl_cur_packet_list->model()) + return false; + + if (fi) { + FieldInformation finfo(fi, gbl_cur_packet_list); + emit gbl_cur_packet_list->fieldSelected(&finfo); + } else { + emit gbl_cur_packet_list->fieldSelected(0); + } + return true; } void @@ -180,21 +202,21 @@ packet_list_recent_write_all(FILE *rf) { gbl_cur_packet_list->writeRecent(rf); } -gboolean +bool packet_list_multi_select_active(void) { if (gbl_cur_packet_list) { return gbl_cur_packet_list->multiSelectActive(); } - return FALSE; + return false; } #define MIN_COL_WIDTH_STR "MMMMMM" PacketList::PacketList(QWidget *parent) : QTreeView(parent), - proto_tree_(NULL), - cap_file_(NULL), + proto_tree_(nullptr), + cap_file_(nullptr), ctx_column_(-1), overlay_timer_id_(0), create_near_overlay_(true), @@ -209,7 +231,8 @@ PacketList::PacketList(QWidget *parent) : frozen_selected_rows_(QModelIndexList()), cur_history_(-1), in_history_(false), - finfo_array(NULL) + finfo_array(nullptr), + profile_switcher_(nullptr) { setItemsExpandable(false); setRootIsDecorated(false); @@ -227,9 +250,7 @@ PacketList::PacketList(QWidget *parent) : connect(packet_list_header_, &PacketListHeader::columnsChanged, this, &PacketList::columnsChanged); setHeader(packet_list_header_); -#if QT_VERSION >= QT_VERSION_CHECK(5, 11, 0) header()->setFirstSectionMovable(true); -#endif setSelectionMode(QAbstractItemView::ExtendedSelection); @@ -276,10 +297,23 @@ PacketList::~PacketList() { if (finfo_array) { - g_ptr_array_free(finfo_array, TRUE); + g_ptr_array_free(finfo_array, true); } } +void PacketList::scrollTo(const QModelIndex &index, QAbstractItemView::ScrollHint hint) +{ + /* QAbstractItemView doesn't have a way to indicate "auto scroll, but + * only vertically." So just restore the horizontal scroll value whenever + * it scrolls. + */ + setUpdatesEnabled(false); + int horizVal = horizontalScrollBar()->value(); + QTreeView::scrollTo(index, hint); + horizontalScrollBar()->setValue(horizVal); + setUpdatesEnabled(true); +} + void PacketList::colorsChanged() { const QString c_active = "active"; @@ -550,7 +584,6 @@ void PacketList::selectionChanged (const QItemSelection & selected, const QItemS selection_history_.resize(cur_history_); selection_history_.append(cap_file_->current_frame->num); } - in_history_ = false; related_packet_delegate_.clear(); @@ -567,7 +600,7 @@ void PacketList::selectionChanged (const QItemSelection & selected, const QItemS if (cap_file_->edt->tree) { packet_info *pi = &cap_file_->edt->pi; related_packet_delegate_.setCurrentFrame(pi->num); - conversation_t *conv = find_conversation_pinfo(pi, 0); + conversation_t *conv = find_conversation_pinfo_ro(pi, 0); if (conv) { related_packet_delegate_.setConversation(conv); } @@ -581,9 +614,17 @@ void PacketList::selectionChanged (const QItemSelection & selected, const QItemS // The tree where the target string matched one of the labels was discarded in // match_protocol_tree() so we have to search again in the latest tree. fi = cf_find_string_protocol_tree(cap_file_, cap_file_->edt->tree); - } else if (cap_file_->search_pos != 0) { + } else if (cap_file_->search_len != 0) { // Find the finfo that corresponds to our byte. - fi = proto_find_field_from_offset(cap_file_->edt->tree, cap_file_->search_pos, + // The match can span multiple fields (and a single byte can + // match more than one field.) Our behavior is to find the last + // field in the tree (so hopefully spanning fewer bytes) that + // matches the last byte in the search match. + // (regex search can find a zero length match not at the + // start of the frame if lookbehind is used, but + // proto_find_field_from_offset doesn't match such a field + // and it's not clear which field we would want to match.) + fi = proto_find_field_from_offset(cap_file_->edt->tree, cap_file_->search_pos + cap_file_->search_len - 1, cap_file_->edt->tvb); } @@ -606,16 +647,16 @@ void PacketList::contextMenuEvent(QContextMenuEvent *event) if (finfo_array) { - g_ptr_array_free(finfo_array, TRUE); + g_ptr_array_free(finfo_array, true); finfo_array = NULL; } if (cap_file_ && cap_file_->edt && cap_file_->edt->tree) { finfo_array = proto_all_finfos(cap_file_->edt->tree); QList<QString> added_proto_prefs; - for (guint i = 0; i < finfo_array->len; i++) { + for (unsigned i = 0; i < finfo_array->len; i++) { field_info *fi = (field_info *)g_ptr_array_index (finfo_array, i); - header_field_info *hfinfo = fi->hfinfo; + const header_field_info *hfinfo = fi->hfinfo; if (prefs_is_registered_protocol(hfinfo->abbrev)) { if (hfinfo->parent == -1) { @@ -654,8 +695,8 @@ void PacketList::contextMenuEvent(QContextMenuEvent *event) ctx_menu->setAttribute(Qt::WA_DeleteOnClose); // XXX We might want to reimplement setParent() and fill in the context // menu there. - ctx_menu->addAction(window()->findChild<QAction *>("actionEditMarkPacket")); - ctx_menu->addAction(window()->findChild<QAction *>("actionEditIgnorePacket")); + ctx_menu->addAction(window()->findChild<QAction *>("actionEditMarkSelected")); + ctx_menu->addAction(window()->findChild<QAction *>("actionEditIgnoreSelected")); ctx_menu->addAction(window()->findChild<QAction *>("actionEditSetTimeReference")); ctx_menu->addAction(window()->findChild<QAction *>("actionEditTimeShift")); ctx_menu->addMenu(window()->findChild<QMenu *>("menuPacketComment")); @@ -728,6 +769,7 @@ void PacketList::contextMenuEvent(QContextMenuEvent *event) main_menu_item = window()->findChild<QMenu *>("menuEditCopy"); submenu = new QMenu(main_menu_item->title(), ctx_menu); + submenu->setToolTipsVisible(true); ctx_menu->addMenu(submenu); QAction * action = submenu->addAction(tr("Summary as Text")); @@ -749,15 +791,16 @@ void PacketList::contextMenuEvent(QContextMenuEvent *event) copyEntries->setParent(submenu); frameData->setParent(submenu); - ctx_menu->addSeparator(); - ctx_menu->addMenu(&proto_prefs_menus_); - action = ctx_menu->addAction(tr("Decode As…")); - action->setProperty("create_new", QVariant(true)); - connect(action, &QAction::triggered, this, &PacketList::ctxDecodeAsDialog); - // "Print" not ported intentionally - action = window()->findChild<QAction *>("actionViewShowPacketInNewWindow"); - ctx_menu->addAction(action); - + if (is_packet_configuration_namespace()) { + ctx_menu->addSeparator(); + ctx_menu->addMenu(&proto_prefs_menus_); + action = ctx_menu->addAction(tr("Decode As…")); + action->setProperty("create_new", QVariant(true)); + connect(action, &QAction::triggered, this, &PacketList::ctxDecodeAsDialog); + // "Print" not ported intentionally + action = window()->findChild<QAction *>("actionViewShowPacketInNewWindow"); + ctx_menu->addAction(action); + } // Set menu sensitivity for the current column and set action data. if (frameData) @@ -805,9 +848,7 @@ void PacketList::paintEvent(QPaintEvent *event) void PacketList::mousePressEvent (QMouseEvent *event) { - setAutoScroll(false); QTreeView::mousePressEvent(event); - setAutoScroll(true); QModelIndex curIndex = indexAt(event->pos()); mouse_pressed_at_ = curIndex; @@ -918,23 +959,7 @@ void PacketList::mouseMoveEvent (QMouseEvent *event) void PacketList::keyPressEvent(QKeyEvent *event) { - bool handled = false; - // If scrolling up/down, want to preserve horizontal scroll extent. - if (event->key() == Qt::Key_Down || event->key() == Qt::Key_Up || - event->key() == Qt::Key_PageDown || event->key() == Qt::Key_PageUp || - event->key() == Qt::Key_End || event->key() == Qt::Key_Home ) - { - // XXX: Why allow jumping to the left if the first column is current? - if (currentIndex().isValid() && currentIndex().column() > 0) { - int pos = horizontalScrollBar()->value(); - QTreeView::keyPressEvent(event); - horizontalScrollBar()->setValue(pos); - handled = true; - } - } - - if (!handled) - QTreeView::keyPressEvent(event); + QTreeView::keyPressEvent(event); if (event->matches(QKeySequence::Copy)) { @@ -1008,19 +1033,11 @@ void PacketList::setRecentColumnWidth(int col) const char *long_str = get_column_width_string(fmt, col); QFontMetrics fm = QFontMetrics(mainApp->monospaceFont()); -#if (QT_VERSION >= QT_VERSION_CHECK(5, 11, 0)) if (long_str) { col_width = fm.horizontalAdvance(long_str); } else { col_width = fm.horizontalAdvance(MIN_COL_WIDTH_STR); } -#else - if (long_str) { - col_width = fm.width(long_str); - } else { - col_width = fm.width(MIN_COL_WIDTH_STR); - } -#endif // Custom delegate padding if (itemDelegateForColumn(col)) { QStyleOptionViewItem option; @@ -1102,6 +1119,14 @@ bool PacketList::havePreviousHistory(bool update_cur) return false; } +void PacketList::setProfileSwitcher(ProfileSwitcher *profile_switcher) +{ + profile_switcher_ = profile_switcher; + if (profile_switcher) { + connect(packet_list_model_, &PacketListModel::packetAppended, profile_switcher_, &ProfileSwitcher::checkPacket); + } +} + frame_data *PacketList::getFDataForRow(int row) const { return packet_list_model_->getRowFdata(row); @@ -1120,7 +1145,7 @@ void PacketList::columnsChanged() prefs.num_cols = g_list_length(prefs.col_list); col_cleanup(&cap_file_->cinfo); - build_column_format_array(&cap_file_->cinfo, prefs.num_cols, FALSE); + build_column_format_array(&cap_file_->cinfo, prefs.num_cols, false); create_far_overlay_ = true; resetColumns(); applyRecentColumnWidths(); @@ -1133,7 +1158,7 @@ void PacketList::fieldsChanged(capture_file *cf) { prefs.num_cols = g_list_length(prefs.col_list); col_cleanup(&cf->cinfo); - build_column_format_array(&cf->cinfo, prefs.num_cols, FALSE); + build_column_format_array(&cf->cinfo, prefs.num_cols, false); resetColumns(); } @@ -1163,9 +1188,6 @@ void PacketList::applyRecentColumnWidths() void PacketList::preferencesChanged() { - // Update color style changes - colorsChanged(); - // Related packet delegate if (prefs.gui_packet_list_show_related) { setItemDelegateForColumn(0, &related_packet_delegate_); @@ -1329,8 +1351,8 @@ void PacketList::clear() { } void PacketList::writeRecent(FILE *rf) { - gint col, width, col_fmt; - gchar xalign; + int col, width, col_fmt; + char xalign; fprintf (rf, "%s:\n", RECENT_KEY_COL_WIDTH); for (col = 0; col < prefs.num_cols; col++) { @@ -1387,7 +1409,7 @@ QString PacketList::getFilterFromRowAndColumn(QModelIndex idx) return filter; /* error reading the record */ } /* proto tree, visible. We need a proto tree if there's custom columns */ - epan_dissect_init(&edt, cap_file_->epan, have_custom_cols(&cap_file_->cinfo), FALSE); + epan_dissect_init(&edt, cap_file_->epan, have_custom_cols(&cap_file_->cinfo), false); col_custom_prime_edt(&edt, &cap_file_->cinfo); epan_dissect_run(&edt, cap_file_->cd_t, &rec, @@ -1400,14 +1422,14 @@ QString PacketList::getFilterFromRowAndColumn(QModelIndex idx) /* We don't need to fill in the custom columns, as we get their * filters above. */ - col_fill_in(&edt.pi, TRUE, TRUE); + col_fill_in(&edt.pi, true, true); if (strlen(cap_file_->cinfo.col_expr.col_expr[column]) != 0 && strlen(cap_file_->cinfo.col_expr.col_expr_val[column]) != 0) { - gboolean is_string_value = FALSE; + bool is_string_value = false; header_field_info *hfi = proto_registrar_get_byname(cap_file_->cinfo.col_expr.col_expr[column]); - if (hfi && hfi->type == FT_STRING) { + if (hfi && FT_IS_STRING(hfi->type)) { /* Could be an address type such as usb.src which must be quoted. */ - is_string_value = TRUE; + is_string_value = true; } if (filter.isEmpty()) { @@ -1438,7 +1460,7 @@ void PacketList::resetColorized() update(); } -QString PacketList::getPacketComment(guint c_number) +QString PacketList::getPacketComment(unsigned c_number) { int row = currentIndex().row(); const frame_data *fdata; @@ -1487,7 +1509,7 @@ void PacketList::addPacketComment(QString new_comment) } } -void PacketList::setPacketComment(guint c_number, QString new_comment) +void PacketList::setPacketComment(unsigned c_number, QString new_comment) { QModelIndex curIndex = currentIndex(); @@ -1513,7 +1535,7 @@ void PacketList::setPacketComment(guint c_number, QString new_comment) QString PacketList::allPacketComments() { - guint32 framenum; + uint32_t framenum; frame_data *fdata; QString buf_str; @@ -1525,8 +1547,8 @@ QString PacketList::allPacketComments() wtap_block_t pkt_block = cf_get_packet_block(cap_file_, fdata); if (pkt_block) { - guint n_comments = wtap_block_count_option(pkt_block, OPT_COMMENT); - for (guint i = 0; i < n_comments; i++) { + unsigned n_comments = wtap_block_count_option(pkt_block, OPT_COMMENT); + for (unsigned i = 0; i < n_comments; i++) { char *comment_text; if (WTAP_OPTTYPE_SUCCESS == wtap_block_get_nth_string_option_value(pkt_block, OPT_COMMENT, i, &comment_text)) { buf_str.append(QString(tr("Frame %1: %2\n\n")).arg(framenum).arg(comment_text)); @@ -1584,7 +1606,12 @@ void PacketList::setCaptureFile(capture_file *cf) void PacketList::setMonospaceFont(const QFont &mono_font) { setFont(mono_font); - header()->setFont(mainApp->font()); +} + +void PacketList::setRegularFont(const QFont ®ular_font) +{ + header()->setFont(regular_font); + header()->viewport()->setFont(regular_font); } void PacketList::goNextPacket(void) @@ -1644,16 +1671,14 @@ void PacketList::goLastPacket(void) { scrollViewChanged(false); } -// XXX We can jump to the wrong packet if a display filter is applied void PacketList::goToPacket(int packet, int hf_id) { - if (!cf_goto_frame(cap_file_, packet)) + if (!cf_goto_frame(cap_file_, packet, false)) return; - int row = packet_list_model_->packetNumberToRow(packet); - if (row >= 0) { - selectionModel()->setCurrentIndex(packet_list_model_->index(row, 0), QItemSelectionModel::ClearAndSelect | QItemSelectionModel::Rows); - scrollTo(currentIndex(), PositionAtCenter); + // cf_goto_frame only returns true if packet_list_select_row_from_data + // succeeds, the latter has already selected and scrolled to the frame. + if (hf_id > 0) { proto_tree_->goToHfid(hf_id); } @@ -1810,7 +1835,7 @@ void PacketList::sectionResized(int col, int, int new_width) // visible. // // Don't set column width when columns changed or setting column - // visibility because we may get a sectionReized() from QTreeView + // visibility because we may get a sectionResized() from QTreeView // with values from a old columns layout. // // Don't set column width when hiding a column. @@ -1825,6 +1850,7 @@ void PacketList::sectionResized(int col, int, int new_width) void PacketList::sectionMoved(int logicalIndex, int oldVisualIndex, int newVisualIndex) { GList *new_col_list = NULL; + GList *new_recent_col_list = NULL; QList<int> saved_sizes; int sort_idx; @@ -1849,9 +1875,14 @@ void PacketList::sectionMoved(int logicalIndex, int oldVisualIndex, int newVisua saved_sizes << header()->sectionSize(log_idx); void *pref_data = g_list_nth_data(prefs.col_list, log_idx); - if (!pref_data) continue; + if (pref_data) { + new_col_list = g_list_append(new_col_list, pref_data); + } - new_col_list = g_list_append(new_col_list, pref_data); + pref_data = g_list_nth_data(recent.col_width_list, log_idx); + if (pref_data) { + new_recent_col_list = g_list_append(new_recent_col_list, pref_data); + } } // Undo move to ensure that the logical indices map to the visual indices, @@ -1869,6 +1900,8 @@ void PacketList::sectionMoved(int logicalIndex, int oldVisualIndex, int newVisua g_list_free(prefs.col_list); prefs.col_list = new_col_list; + g_list_free(recent.col_width_list); + recent.col_width_list = new_recent_col_list; thaw(true); @@ -1988,7 +2021,7 @@ void PacketList::scrollViewChanged(bool at_end) // out colors. // Try 3: One packet per vertical scroll bar pixel. This seems to work best // but has the smallest window. -// Try 4: Use a multiple of the scroll bar heigh and scale the image down +// Try 4: Use a multiple of the scroll bar height and scale the image down // using Qt::SmoothTransformation. This gives us more packets per raster // line. |