/* packet_list.cpp * * $Id$ * * Wireshark - Network traffic analyzer * By Gerald Combs * Copyright 1998 Gerald Combs * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version 2 * of the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #ifdef HAVE_CONFIG_H # include "config.h" #endif #include #include #include #include #include #include #include "packet_list.h" #include "monospace_font.h" #include "proto_tree.h" #include "globals.h" #include "qt_ui_utils.h" #include "ui/main_statusbar.h" #include "ui/recent.h" #include "ui/recent_utils.h" #include "ui/ui_util.h" #include #include #include #include // If we ever add the ability to open multiple capture files we might be // able to use something like QMap to match // capture files against packet lists and models. static PacketList *gbl_cur_packet_list = NULL; guint packet_list_append(column_info *cinfo, frame_data *fdata, packet_info *pinfo) { Q_UNUSED(cinfo); Q_UNUSED(pinfo); if (!gbl_cur_packet_list) return 0; /* fdata should be filled with the stuff we need * strings are built at display time. */ guint visible_pos; visible_pos = gbl_cur_packet_list->packetListModel()->appendPacket(fdata); return visible_pos; } // Copied from ui/gtk/packet_list.c void packet_list_resize_column(gint col) { // xxx qtshark // gint col_width; // const gchar *long_str; g_log(NULL, G_LOG_LEVEL_DEBUG, "FIX: packet_list_resize_column %d", col); // long_str = packet_list_get_widest_column_string(packetlist, col); // if(!long_str || strcmp("",long_str)==0) // /* If we get an empty string leave the width unchanged */ // return; // column = gtk_tree_view_get_column (GTK_TREE_VIEW(packetlist->view), col); // col_width = get_default_col_size (packetlist->view, long_str); // gtk_tree_view_column_set_fixed_width(column, col_width); } void packet_list_select_first_row(void) { if (!gbl_cur_packet_list) return; gbl_cur_packet_list->goFirstPacket(); gbl_cur_packet_list->setFocus(); } void packet_list_select_last_row(void) { if (!gbl_cur_packet_list) return; gbl_cur_packet_list->goLastPacket(); gbl_cur_packet_list->setFocus(); } /* * 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. */ gboolean packet_list_select_row_from_data(frame_data *fdata_needle) { int row = gbl_cur_packet_list->packetListModel()->visibleIndexOf(fdata_needle); if (row >= 0) { gbl_cur_packet_list->setCurrentIndex(gbl_cur_packet_list->packetListModel()->index(row,0)); return TRUE; } return FALSE; } gboolean packet_list_check_end(void) { if (gbl_cur_packet_list) { QScrollBar *sb = gbl_cur_packet_list->verticalScrollBar(); if (sb && sb->isVisible() && sb->value() == sb->maximum()) { return TRUE; } } return FALSE; } void packet_list_clear(void) { if (gbl_cur_packet_list) { gbl_cur_packet_list->clear(); } } void packet_list_enable_color(gboolean enable) { if (gbl_cur_packet_list && gbl_cur_packet_list->packetListModel()) { gbl_cur_packet_list->packetListModel()->setColorEnabled(enable); gbl_cur_packet_list->update(); } } void packet_list_freeze(void) { if (gbl_cur_packet_list) { gbl_cur_packet_list->setUpdatesEnabled(false); } } void packet_list_thaw(void) { if (gbl_cur_packet_list) { gbl_cur_packet_list->setUpdatesEnabled(true); } packets_bar_update(); } void packet_list_recreate_visible_rows(void) { if (gbl_cur_packet_list && gbl_cur_packet_list->packetListModel()) { gbl_cur_packet_list->packetListModel()->recreateVisibleRows(); } } frame_data * packet_list_get_row_data(gint row) { if (gbl_cur_packet_list && gbl_cur_packet_list->packetListModel()) { return gbl_cur_packet_list->packetListModel()->getRowFdata(row); } return NULL; } void packet_list_moveto_end(void) { if (gbl_cur_packet_list) gbl_cur_packet_list->goLastPacket(); } /* Redraw the packet list *and* currently-selected detail */ void packet_list_queue_draw(void) { if (gbl_cur_packet_list) gbl_cur_packet_list->updateAll(); } void packet_list_recent_write_all(FILE *rf) { if (!gbl_cur_packet_list) return; gbl_cur_packet_list->writeRecent(rf); } #define MIN_COL_WIDTH_STR "...." PacketList::PacketList(QWidget *parent) : QTreeView(parent) { setItemsExpandable(FALSE); setRootIsDecorated(FALSE); setSortingEnabled(TRUE); setUniformRowHeights(TRUE); setAccessibleName("Packet list"); packet_list_model_ = new PacketListModel(this, &cfile); setModel(packet_list_model_); packet_list_model_->setColorEnabled(true); // We don't yet fetch color settings. // packet_list_model_->setColorEnabled(recent.packet_list_colorize); g_assert(gbl_cur_packet_list == NULL); gbl_cur_packet_list = this; proto_tree_ = NULL; byte_view_tab_ = NULL; } void PacketList::setProtoTree (ProtoTree *proto_tree) { proto_tree_ = proto_tree; connect(proto_tree_, SIGNAL(goToFrame(int)), this, SLOT(goToPacket(int))); } void PacketList::setByteViewTab (ByteViewTab *byte_view_tab) { byte_view_tab_ = byte_view_tab; } PacketListModel *PacketList::packetListModel() const { return packet_list_model_; } void PacketList::showEvent (QShowEvent *event) { Q_UNUSED(event); // g_log(NULL, G_LOG_LEVEL_DEBUG, "cols: %d", cfile.cinfo.num_cols); for (int i = 0; i < cfile.cinfo.num_cols; i++) { int fmt, col_width; const char *long_str; fmt = get_column_format(i); long_str = get_column_width_string(fmt, i); if (long_str) { col_width = get_monospace_text_size(long_str, TRUE); } else { col_width = get_monospace_text_size(MIN_COL_WIDTH_STR, TRUE); } setColumnWidth(i, col_width); } } void PacketList::selectionChanged (const QItemSelection & selected, const QItemSelection & deselected) { QTreeView::selectionChanged(selected, deselected); if (proto_tree_) { int row = selected.first().top(); cf_select_packet(&cfile, row); if (!cfile.edt && !cfile.edt->tree) { return; } proto_tree_->fillProtocolTree(cfile.edt->tree); } if (byte_view_tab_ && cfile.edt) { GSList *src_le; data_source *source; // Clear out existing tabs while (byte_view_tab_->currentWidget()) { delete byte_view_tab_->currentWidget(); } for (src_le = cfile.edt->pi.data_src; src_le != NULL; src_le = src_le->next) { source = (data_source *)src_le->data; byte_view_tab_->addTab(get_data_source_name(source), source->tvb, cfile.edt->tree, proto_tree_, cfile.current_frame->flags.encoding); } } if (proto_tree_ && byte_view_tab_) { // Connect signals between the proto tree and byte views. connect(proto_tree_, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)), byte_view_tab_, SLOT(protoTreeItemChanged(QTreeWidgetItem*))); } } // Redraw the packet list and detail void PacketList::updateAll() { update(); if (selectedIndexes().length() > 0) { cf_select_packet(&cfile, selectedIndexes()[0].row()); } } void PacketList::clear() { // packet_history_clear(); packetListModel()->clear(); proto_tree_->clear(); // Clear out existing tabs while (byte_view_tab_->currentWidget()) { delete byte_view_tab_->currentWidget(); } /* XXX is this correct in all cases? * Reset the sort column, use packetlist as model in case the list is frozen. */ gbl_cur_packet_list->sortByColumn(0, Qt::AscendingOrder); } void PacketList::writeRecent(FILE *rf) { gint col, width, col_fmt; gchar xalign; fprintf (rf, "%s:", RECENT_KEY_COL_WIDTH); for (col = 0; col < packetListModel()->columnCount(); col++) { if (col > 0) { fprintf (rf, ","); } col_fmt = get_column_format(col); if (col_fmt == COL_CUSTOM) { fprintf (rf, " %%Cus:%s,", get_column_custom_field(col)); } else { fprintf (rf, " %s,", col_format_to_string(col_fmt)); } width = columnWidth(col); xalign = recent_get_column_xalign (col); if (width == 0) { /* We have not initialized the packet list yet, use old values */ width = recent_get_column_width (col); } fprintf (rf, " %d", width); if (xalign != COLUMN_XALIGN_DEFAULT) { fprintf (rf, ":%c", xalign); } } fprintf (rf, "\n"); } void PacketList::goNextPacket(void) { setCurrentIndex(moveCursor(MoveDown, Qt::NoModifier)); } void PacketList::goPreviousPacket(void) { setCurrentIndex(moveCursor(MoveUp, Qt::NoModifier)); } void PacketList::goFirstPacket(void) { setCurrentIndex(moveCursor(MoveHome, Qt::NoModifier)); } void PacketList::goLastPacket(void) { setCurrentIndex(moveCursor(MoveEnd, Qt::NoModifier)); } void PacketList::goToPacket(int packet) { if (packet > 0 && packet <= packet_list_model_->rowCount()) { setCurrentIndex(packet_list_model_->index(packet - 1, 0)); } } /* * Editor modelines * * Local Variables: * c-basic-offset: 4 * tab-width: 8 * indent-tabs-mode: nil * End: * * ex: set shiftwidth=4 tabstop=8 expandtab: * :indentSize=4:tabSize=8:noTabs=true: */