3 * Wireshark - Network traffic analyzer
4 * By Gerald Combs <gerald@wireshark.org>
5 * Copyright 1998 Gerald Combs
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
26 #include <epan/epan.h>
27 #include <epan/epan_dissect.h>
29 #include <epan/column-info.h>
30 #include <epan/column.h>
31 #include <epan/packet.h>
33 #include "packet_list.h"
34 #include "proto_tree.h"
35 #include "wireshark_application.h"
36 #include "epan/ipproto.h"
38 #include "qt_ui_utils.h"
40 #include "ui/main_statusbar.h"
41 #include "ui/recent.h"
42 #include "ui/recent_utils.h"
43 #include "ui/ui_util.h"
45 #include "wsutil/str_util.h"
47 #include "frame_tvbuff.h"
49 #include <QTreeWidget>
53 #include <QContextMenuEvent>
54 #include <QMessageBox>
56 // If we ever add the ability to open multiple capture files we might be
57 // able to use something like QMap<capture_file *, PacketList *> to match
58 // capture files against packet lists and models.
59 static PacketList *gbl_cur_packet_list = NULL;
61 const int max_comments_to_fetch_ = 20000000; // Arbitrary
64 packet_list_append(column_info *cinfo, frame_data *fdata)
68 if (!gbl_cur_packet_list)
71 /* fdata should be filled with the stuff we need
72 * strings are built at display time.
76 visible_pos = gbl_cur_packet_list->packetListModel()->appendPacket(fdata);
80 // Copied from ui/gtk/packet_list.c
81 void packet_list_resize_column(gint col)
85 // const gchar *long_str;
87 g_log(NULL, G_LOG_LEVEL_DEBUG, "FIX: packet_list_resize_column %d", col);
88 // long_str = packet_list_get_widest_column_string(packetlist, col);
89 // if(!long_str || strcmp("",long_str)==0)
90 // /* If we get an empty string leave the width unchanged */
92 // column = gtk_tree_view_get_column (GTK_TREE_VIEW(packetlist->view), col);
93 // col_width = get_default_col_size (packetlist->view, long_str);
94 // gtk_tree_view_column_set_fixed_width(column, col_width);
98 packet_list_select_first_row(void)
100 if (!gbl_cur_packet_list)
102 gbl_cur_packet_list->goFirstPacket();
103 gbl_cur_packet_list->setFocus();
107 packet_list_select_last_row(void)
109 if (!gbl_cur_packet_list)
111 gbl_cur_packet_list->goLastPacket();
112 gbl_cur_packet_list->setFocus();
116 * Given a frame_data structure, scroll to and select the row in the
117 * packet list corresponding to that frame. If there is no such
118 * row, return FALSE, otherwise return TRUE.
121 packet_list_select_row_from_data(frame_data *fdata_needle)
123 int row = gbl_cur_packet_list->packetListModel()->visibleIndexOf(fdata_needle);
125 gbl_cur_packet_list->setCurrentIndex(gbl_cur_packet_list->packetListModel()->index(row,0));
133 packet_list_check_end(void)
135 if (gbl_cur_packet_list) {
136 QScrollBar *sb = gbl_cur_packet_list->verticalScrollBar();
137 if (sb && sb->isVisible() && sb->value() == sb->maximum()) {
145 packet_list_clear(void)
147 if (gbl_cur_packet_list) {
148 gbl_cur_packet_list->clear();
153 packet_list_enable_color(gboolean enable)
155 if (gbl_cur_packet_list && gbl_cur_packet_list->packetListModel()) {
156 gbl_cur_packet_list->packetListModel()->setColorEnabled(enable);
157 gbl_cur_packet_list->update();
162 packet_list_freeze(void)
164 if (gbl_cur_packet_list) {
165 gbl_cur_packet_list->freeze();
170 packet_list_thaw(void)
172 if (gbl_cur_packet_list) {
173 gbl_cur_packet_list->thaw();
176 packets_bar_update();
180 packet_list_recreate_visible_rows(void)
182 if (gbl_cur_packet_list && gbl_cur_packet_list->packetListModel()) {
183 gbl_cur_packet_list->packetListModel()->recreateVisibleRows();
188 packet_list_get_row_data(gint row)
190 if (gbl_cur_packet_list && gbl_cur_packet_list->packetListModel()) {
191 return gbl_cur_packet_list->packetListModel()->getRowFdata(row);
197 packet_list_moveto_end(void)
199 if (gbl_cur_packet_list)
200 gbl_cur_packet_list->goLastPacket();
203 /* Redraw the packet list *and* currently-selected detail */
205 packet_list_queue_draw(void)
207 if (gbl_cur_packet_list)
208 gbl_cur_packet_list->updateAll();
212 packet_list_recent_write_all(FILE *rf) {
213 if (!gbl_cur_packet_list)
216 gbl_cur_packet_list->writeRecent(rf);
219 #define MIN_COL_WIDTH_STR "...."
221 PacketList::PacketList(QWidget *parent) :
224 byte_view_tab_(NULL),
229 QMenu *submenu, *subsubmenu;
231 setItemsExpandable(FALSE);
232 setRootIsDecorated(FALSE);
233 setSortingEnabled(TRUE);
234 setUniformRowHeights(TRUE);
235 setAccessibleName("Packet list");
236 setItemDelegateForColumn(0, &related_packet_delegate_);
238 packet_list_model_ = new PacketListModel(this, cap_file_);
239 setModel(packet_list_model_);
240 packet_list_model_->setColorEnabled(recent.packet_list_colorize);
242 // XXX We might want to reimplement setParent() and fill in the context
244 ctx_menu_.addAction(window()->findChild<QAction *>("actionEditMarkPacket"));
245 ctx_menu_.addAction(window()->findChild<QAction *>("actionEditIgnorePacket"));
246 ctx_menu_.addAction(window()->findChild<QAction *>("actionEditSetTimeReference"));
247 ctx_menu_.addAction(window()->findChild<QAction *>("actionEditTimeShift"));
248 ctx_menu_.addAction(window()->findChild<QAction *>("actionEditPacketComment"));
250 ctx_menu_.addSeparator();
251 submenu = new QMenu(tr("Follow..."));
252 ctx_menu_.addMenu(submenu);
253 submenu->addAction(window()->findChild<QAction *>("actionAnalyzeFollowTCPStream"));
254 submenu->addAction(window()->findChild<QAction *>("actionAnalyzeFollowUDPStream"));
255 submenu->addAction(window()->findChild<QAction *>("actionAnalyzeFollowSSLStream"));
256 filter_actions_ << submenu->actions();
257 // " <menuitem name='FollowTCPStream' action='/Follow TCP Stream'/>\n"
258 // " <menuitem name='FollowUDPStream' action='/Follow UDP Stream'/>\n"
259 // " <menuitem name='FollowSSLStream' action='/Follow SSL Stream'/>\n"
260 submenu = new QMenu(tr("SCTP"));
261 ctx_menu_.addMenu(submenu);
262 submenu->addAction(window()->findChild<QAction *>("actionSCTPAnalyseThisAssociation"));
263 submenu->addAction(window()->findChild<QAction *>("actionSCTPShowAllAssociations"));
264 submenu->addAction(window()->findChild<QAction *>("actionSCTPFilterThisAssociation"));
265 filter_actions_ << submenu->actions();
266 ctx_menu_.addSeparator();
267 // " <menuitem name='ManuallyResolveAddress' action='/ManuallyResolveAddress'/>\n"
268 ctx_menu_.addSeparator();
269 submenu = new QMenu(tr("Apply as Filter"));
270 ctx_menu_.addMenu(submenu);
271 submenu->addAction(window()->findChild<QAction *>("actionAnalyzeAAFSelected"));
272 submenu->addAction(window()->findChild<QAction *>("actionAnalyzeAAFNotSelected"));
273 submenu->addAction(window()->findChild<QAction *>("actionAnalyzeAAFAndSelected"));
274 submenu->addAction(window()->findChild<QAction *>("actionAnalyzeAAFOrSelected"));
275 submenu->addAction(window()->findChild<QAction *>("actionAnalyzeAAFAndNotSelected"));
276 submenu->addAction(window()->findChild<QAction *>("actionAnalyzeAAFOrNotSelected"));
277 filter_actions_ << submenu->actions();
278 submenu = new QMenu(tr("Prepare a Filter"));
279 ctx_menu_.addMenu(submenu);
280 submenu->addAction(window()->findChild<QAction *>("actionAnalyzePAFSelected"));
281 submenu->addAction(window()->findChild<QAction *>("actionAnalyzePAFNotSelected"));
282 submenu->addAction(window()->findChild<QAction *>("actionAnalyzePAFAndSelected"));
283 submenu->addAction(window()->findChild<QAction *>("actionAnalyzePAFOrSelected"));
284 submenu->addAction(window()->findChild<QAction *>("actionAnalyzePAFAndNotSelected"));
285 submenu->addAction(window()->findChild<QAction *>("actionAnalyzePAFOrNotSelected"));
286 filter_actions_ << submenu->actions();
287 submenu = new QMenu(tr("Colorize with Filter"));
288 // " <menu name= 'ConversationFilter' action='/Conversation Filter'>\n"
289 // " <menuitem name='Ethernet' action='/Conversation Filter/Ethernet'/>\n"
290 // " <menuitem name='IP' action='/Conversation Filter/IP'/>\n"
291 // " <menuitem name='TCP' action='/Conversation Filter/TCP'/>\n"
292 // " <menuitem name='UDP' action='/Conversation Filter/UDP'/>\n"
293 // " <menuitem name='PN-CBA' action='/Conversation Filter/PN-CBA'/>\n"
294 // " <menu name= 'ColorizeConversation' action='/Colorize Conversation'>\n"
295 // " <menu name= 'Ethernet' action='/Colorize Conversation/Ethernet'>\n"
296 // " <menuitem name='Color1' action='/Colorize Conversation/Ethernet/Color 1'/>\n"
297 // " <menuitem name='Color2' action='/Colorize Conversation/Ethernet/Color 2'/>\n"
298 // " <menuitem name='Color3' action='/Colorize Conversation/Ethernet/Color 3'/>\n"
299 // " <menuitem name='Color4' action='/Colorize Conversation/Ethernet/Color 4'/>\n"
300 // " <menuitem name='Color5' action='/Colorize Conversation/Ethernet/Color 5'/>\n"
301 // " <menuitem name='Color6' action='/Colorize Conversation/Ethernet/Color 6'/>\n"
302 // " <menuitem name='Color7' action='/Colorize Conversation/Ethernet/Color 7'/>\n"
303 // " <menuitem name='Color8' action='/Colorize Conversation/Ethernet/Color 8'/>\n"
304 // " <menuitem name='Color9' action='/Colorize Conversation/Ethernet/Color 9'/>\n"
305 // " <menuitem name='Color10' action='/Colorize Conversation/Ethernet/Color 10'/>\n"
306 // " <menuitem name='NewColoringRule' action='/Colorize Conversation/Ethernet/New Coloring Rule'/>\n"
307 // " <menu name= 'IP' action='/Colorize Conversation/IP'>\n"
308 // " <menuitem name='Color1' action='/Colorize Conversation/IP/Color 1'/>\n"
309 // " <menuitem name='Color2' action='/Colorize Conversation/IP/Color 2'/>\n"
310 // " <menuitem name='Color3' action='/Colorize Conversation/IP/Color 3'/>\n"
311 // " <menuitem name='Color4' action='/Colorize Conversation/IP/Color 4'/>\n"
312 // " <menuitem name='Color5' action='/Colorize Conversation/IP/Color 5'/>\n"
313 // " <menuitem name='Color6' action='/Colorize Conversation/IP/Color 6'/>\n"
314 // " <menuitem name='Color7' action='/Colorize Conversation/IP/Color 7'/>\n"
315 // " <menuitem name='Color8' action='/Colorize Conversation/IP/Color 8'/>\n"
316 // " <menuitem name='Color9' action='/Colorize Conversation/IP/Color 9'/>\n"
317 // " <menuitem name='Color10' action='/Colorize Conversation/IP/Color 10'/>\n"
318 // " <menuitem name='NewColoringRule' action='/Colorize Conversation/IP/New Coloring Rule'/>\n"
319 // " <menu name= 'TCP' action='/Colorize Conversation/TCP'>\n"
320 // " <menuitem name='Color1' action='/Colorize Conversation/TCP/Color 1'/>\n"
321 // " <menuitem name='Color2' action='/Colorize Conversation/TCP/Color 2'/>\n"
322 // " <menuitem name='Color3' action='/Colorize Conversation/TCP/Color 3'/>\n"
323 // " <menuitem name='Color4' action='/Colorize Conversation/TCP/Color 4'/>\n"
324 // " <menuitem name='Color5' action='/Colorize Conversation/TCP/Color 5'/>\n"
325 // " <menuitem name='Color6' action='/Colorize Conversation/TCP/Color 6'/>\n"
326 // " <menuitem name='Color7' action='/Colorize Conversation/TCP/Color 7'/>\n"
327 // " <menuitem name='Color8' action='/Colorize Conversation/TCP/Color 8'/>\n"
328 // " <menuitem name='Color9' action='/Colorize Conversation/TCP/Color 9'/>\n"
329 // " <menuitem name='Color10' action='/Colorize Conversation/TCP/Color 10'/>\n"
330 // " <menuitem name='NewColoringRule' action='/Colorize Conversation/TCP/New Coloring Rule'/>\n"
331 // " <menu name= 'UDP' action='/Colorize Conversation/UDP'>\n"
332 // " <menuitem name='Color1' action='/Colorize Conversation/UDP/Color 1'/>\n"
333 // " <menuitem name='Color2' action='/Colorize Conversation/UDP/Color 2'/>\n"
334 // " <menuitem name='Color3' action='/Colorize Conversation/UDP/Color 3'/>\n"
335 // " <menuitem name='Color4' action='/Colorize Conversation/UDP/Color 4'/>\n"
336 // " <menuitem name='Color5' action='/Colorize Conversation/UDP/Color 5'/>\n"
337 // " <menuitem name='Color6' action='/Colorize Conversation/UDP/Color 6'/>\n"
338 // " <menuitem name='Color7' action='/Colorize Conversation/UDP/Color 7'/>\n"
339 // " <menuitem name='Color8' action='/Colorize Conversation/UDP/Color 8'/>\n"
340 // " <menuitem name='Color9' action='/Colorize Conversation/UDP/Color 9'/>\n"
341 // " <menuitem name='Color10' action='/Colorize Conversation/UDP/Color 10'/>\n"
342 // " <menuitem name='NewColoringRule' action='/Colorize Conversation/UDP/New Coloring Rule'/>\n"
343 // " <menu name= 'PN-CBA' action='/Colorize Conversation/PN-CBA'>\n"
344 // " <menuitem name='Color1' action='/Colorize Conversation/PN-CBA/Color 1'/>\n"
345 // " <menuitem name='Color2' action='/Colorize Conversation/PN-CBA/Color 2'/>\n"
346 // " <menuitem name='Color3' action='/Colorize Conversation/PN-CBA/Color 3'/>\n"
347 // " <menuitem name='Color4' action='/Colorize Conversation/PN-CBA/Color 4'/>\n"
348 // " <menuitem name='Color5' action='/Colorize Conversation/PN-CBA/Color 5'/>\n"
349 // " <menuitem name='Color6' action='/Colorize Conversation/PN-CBA/Color 6'/>\n"
350 // " <menuitem name='Color7' action='/Colorize Conversation/PN-CBA/Color 7'/>\n"
351 // " <menuitem name='Color8' action='/Colorize Conversation/PN-CBA/Color 8'/>\n"
352 // " <menuitem name='Color9' action='/Colorize Conversation/PN-CBA/Color 9'/>\n"
353 // " <menuitem name='Color10' action='/Colorize Conversation/PN-CBA/Color 10'/>\n"
354 // " <menuitem name='NewColoringRule' action='/Colorize Conversation/PN-CBA/New Coloring Rule'/>\n"
355 // " <menu name= 'SCTP' action='/SCTP'>\n"
356 // " <menuitem name='AnalysethisAssociation' action='/SCTP/Analyse this Association'/>\n"
357 // " <menuitem name='PrepareFilterforthisAssociation' action='/SCTP/Prepare Filter for this Association'/>\n"
358 // " <menuitem name='FollowTCPStream' action='/Follow TCP Stream'/>\n"
359 // " <menuitem name='FollowUDPStream' action='/Follow UDP Stream'/>\n"
360 // " <menuitem name='FollowSSLStream' action='/Follow SSL Stream'/>\n"
361 ctx_menu_.addSeparator();
362 // " <menu name= 'Copy' action='/Copy'>\n"
363 submenu = new QMenu(tr("Copy"));
364 ctx_menu_.addMenu(submenu);
365 // " <menuitem name='SummaryTxt' action='/Copy/SummaryTxt'/>\n"
366 // " <menuitem name='SummaryCSV' action='/Copy/SummaryCSV'/>\n"
367 submenu->addAction(window()->findChild<QAction *>("actionEditCopyAsFilter"));
368 filter_actions_ << window()->findChild<QAction *>("actionEditCopyAsFilter");
369 submenu->addSeparator();
370 subsubmenu = new QMenu(tr("Bytes"));
371 submenu->addMenu(subsubmenu);
372 // " <menuitem name='OffsetHexText' action='/Copy/Bytes/OffsetHexText'/>\n"
373 // " <menuitem name='OffsetHex' action='/Copy/Bytes/OffsetHex'/>\n"
374 // " <menuitem name='PrintableTextOnly' action='/Copy/Bytes/PrintableTextOnly'/>\n"
375 ctx_menu_.addSeparator();
376 // " <menuitem name='HexStream' action='/Copy/Bytes/HexStream'/>\n"
377 // " <menuitem name='BinaryStream' action='/Copy/Bytes/BinaryStream'/>\n"
378 ctx_menu_.addSeparator();
379 // " <menuitem name='ProtocolPreferences' action='/ProtocolPreferences'/>\n"
380 decode_as_ = window()->findChild<QAction *>("actionAnalyzeDecodeAs");
381 ctx_menu_.addAction(decode_as_);
382 // " <menuitem name='Print' action='/Print'/>\n"
383 // " <menuitem name='ShowPacketinNewWindow' action='/ShowPacketinNewWindow'/>\n"
385 g_assert(gbl_cur_packet_list == NULL);
386 gbl_cur_packet_list = this;
389 void PacketList::setProtoTree (ProtoTree *proto_tree) {
390 proto_tree_ = proto_tree;
392 connect(proto_tree_, SIGNAL(goToFrame(int)), this, SLOT(goToPacket(int)));
393 connect(proto_tree_, SIGNAL(relatedFrame(int)), this, SLOT(addRelatedFrame(int)));
396 void PacketList::setByteViewTab (ByteViewTab *byte_view_tab) {
397 byte_view_tab_ = byte_view_tab;
399 connect(proto_tree_, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)),
400 byte_view_tab_, SLOT(protoTreeItemChanged(QTreeWidgetItem*)));
403 PacketListModel *PacketList::packetListModel() const {
404 return packet_list_model_;
407 void PacketList::showEvent (QShowEvent *event) {
410 if (!cap_file_) return;
412 for (int i = 0; i < cap_file_->cinfo.num_cols; i++) {
414 const char *long_str;
416 fmt = get_column_format(i);
417 long_str = get_column_width_string(fmt, i);
419 col_width = wsApp->monospaceTextSize(long_str);
421 col_width = wsApp->monospaceTextSize(MIN_COL_WIDTH_STR);
423 setColumnWidth(i, col_width);
427 void PacketList::selectionChanged (const QItemSelection & selected, const QItemSelection & deselected) {
428 QTreeView::selectionChanged(selected, deselected);
430 if (!cap_file_) return;
432 int row = selected.first().top();
433 cf_select_packet(cap_file_, row);
434 related_packet_delegate_.clear();
435 emit packetSelectionChanged();
437 if (!cap_file_->edt) return;
439 if (proto_tree_ && cap_file_->edt->tree) {
440 proto_tree_->fillProtocolTree(cap_file_->edt->tree);
441 packet_info *pi = &cap_file_->edt->pi;
442 conversation_t *conv = find_conversation(pi->fd->num, &pi->src, &pi->dst, pi->ptype,
443 pi->srcport, pi->destport, 0);
445 related_packet_delegate_.setConversationSpan(conv->setup_frame, conv->last_frame);
447 viewport()->update();
450 if (byte_view_tab_) {
452 struct data_source *source;
454 byte_view_tab_->clear();
456 for (src_le = cap_file_->edt->pi.data_src; src_le != NULL; src_le = src_le->next) {
457 source = (struct data_source *)src_le->data;
458 byte_view_tab_->addTab(get_data_source_name(source), get_data_source_tvb(source), cap_file_->edt->tree, proto_tree_, (packet_char_enc)cap_file_->current_frame->flags.encoding);
460 byte_view_tab_->setCurrentIndex(0);
464 void PacketList::contextMenuEvent(QContextMenuEvent *event)
466 bool fa_enabled = filter_actions_[0]->isEnabled();
468 gboolean is_tcp = FALSE, is_udp = FALSE;
470 /* walk the list of a available protocols in the packet to see what we have */
471 if ((cap_file_ != NULL) && (cap_file_->edt != NULL))
473 proto_get_frame_protocols(cap_file_->edt->pi.layers, NULL, &is_tcp, &is_udp, NULL, NULL);
476 foreach (act, filter_actions_)
478 act->setEnabled(true);
481 if (act->objectName().contains("SCTP"))
483 if ((cap_file_ != NULL) && (cap_file_->edt != NULL) && (cap_file_->edt->pi.ipproto == IP_PROTO_SCTP))
485 act->setEnabled(true);
489 act->setEnabled(false);
493 // check follow stream
494 if (act->text().contains("TCP"))
496 act->setEnabled(is_tcp);
500 if (act->text().contains("UDP"))
502 act->setEnabled(is_udp);
506 if ((cap_file_ != NULL) && act->text().contains("SSL"))
508 if (epan_dissect_packet_contains_field(cap_file_->edt, "ssl"))
510 act->setEnabled(true);
514 act->setEnabled(false);
518 decode_as_->setData(qVariantFromValue(true));
519 ctx_column_ = columnAt(event->x());
520 ctx_menu_.exec(event->globalPos());
522 decode_as_->setData(QVariant());
523 foreach (act, filter_actions_) {
524 act->setEnabled(fa_enabled);
528 void PacketList::markFramesReady()
530 packets_bar_update();
534 void PacketList::setFrameMark(gboolean set, frame_data *fdata)
537 cf_mark_frame(cap_file_, fdata);
539 cf_unmark_frame(cap_file_, fdata);
542 void PacketList::setFrameIgnore(gboolean set, frame_data *fdata)
545 cf_ignore_frame(cap_file_, fdata);
547 cf_unignore_frame(cap_file_, fdata);
550 void PacketList::setFrameReftime(gboolean set, frame_data *fdata)
552 if (!fdata || !cap_file_) return;
554 fdata->flags.ref_time=1;
555 cap_file_->ref_time_count++;
557 fdata->flags.ref_time=0;
558 cap_file_->ref_time_count--;
560 cf_reftime_packets(cap_file_);
561 if (!fdata->flags.ref_time && !fdata->flags.passed_dfilter) {
562 cap_file_->displayed_count--;
563 packet_list_model_->recreateVisibleRows();
568 // Redraw the packet list and detail
569 void PacketList::updateAll() {
572 if (!cap_file_) return;
574 if (selectedIndexes().length() > 0) {
575 cf_select_packet(cap_file_, selectedIndexes()[0].row());
578 if (cap_file_->edt && cap_file_->edt->tree) {
579 proto_tree_->fillProtocolTree(cap_file_->edt->tree);
582 packet_list_model_->resetColumns();
585 void PacketList::freeze()
587 setUpdatesEnabled(false);
591 void PacketList::thaw()
593 setModel(packet_list_model_);
594 setUpdatesEnabled(true);
597 void PacketList::clear() {
598 // packet_history_clear();
599 related_packet_delegate_.clear();
600 packet_list_model_->clear();
601 proto_tree_->clear();
602 byte_view_tab_->clear();
604 /* XXX is this correct in all cases?
605 * Reset the sort column, use packetlist as model in case the list is frozen.
607 sortByColumn(0, Qt::AscendingOrder);
610 void PacketList::writeRecent(FILE *rf) {
611 gint col, width, col_fmt;
614 fprintf (rf, "%s:", RECENT_KEY_COL_WIDTH);
615 for (col = 0; col < packet_list_model_->columnCount(); col++) {
619 col_fmt = get_column_format(col);
620 if (col_fmt == COL_CUSTOM) {
621 fprintf (rf, " %%Cus:%s,", get_column_custom_field(col));
623 fprintf (rf, " %s,", col_format_to_string(col_fmt));
625 width = columnWidth(col);
626 xalign = recent_get_column_xalign (col);
628 /* We have not initialized the packet list yet, use old values */
629 width = recent_get_column_width (col);
631 fprintf (rf, " %d", width);
632 if (xalign != COLUMN_XALIGN_DEFAULT) {
633 fprintf (rf, ":%c", xalign);
640 bool PacketList::contextMenuActive()
642 return ctx_column_ >= 0 ? true : false;
645 QString &PacketList::getFilterFromRowAndColumn()
648 QString &filter = *new QString();
649 int row = currentIndex().row();
651 if (!cap_file_ || !packet_list_model_ || ctx_column_ < 0 || ctx_column_ >= cap_file_->cinfo.num_cols) return filter;
653 fdata = packet_list_model_->getRowFdata(row);
658 if (cf_read_frame(cap_file_, fdata) == -1)
659 return filter; /* error reading the frame */
660 /* proto tree, visible. We need a proto tree if there's custom columns */
661 epan_dissect_init(&edt, cap_file_->epan, have_custom_cols(&cap_file_->cinfo), FALSE);
662 col_custom_prime_edt(&edt, &cap_file_->cinfo);
664 epan_dissect_run(&edt, &cap_file_->phdr, frame_tvbuff_new_buffer(fdata, &cap_file_->buf), fdata, &cap_file_->cinfo);
665 epan_dissect_fill_in_columns(&edt, TRUE, TRUE);
667 if ((cap_file_->cinfo.col_custom_occurrence[ctx_column_]) ||
668 (strchr (cap_file_->cinfo.col_expr.col_expr_val[ctx_column_], ',') == NULL))
670 /* Only construct the filter when a single occurrence is displayed
671 * otherwise we might end up with a filter like "ip.proto==1,6".
673 * Or do we want to be able to filter on multiple occurrences so that
674 * the filter might be calculated as "ip.proto==1 && ip.proto==6"
677 if (strlen(cap_file_->cinfo.col_expr.col_expr[ctx_column_]) != 0 &&
678 strlen(cap_file_->cinfo.col_expr.col_expr_val[ctx_column_]) != 0) {
679 /* leak a little but safer than ep_ here */
680 if (cap_file_->cinfo.col_fmt[ctx_column_] == COL_CUSTOM) {
681 header_field_info *hfi = proto_registrar_get_byname(cap_file_->cinfo.col_custom_field[ctx_column_]);
682 if (hfi->parent == -1) {
684 filter.append(cap_file_->cinfo.col_expr.col_expr[ctx_column_]);
685 } else if (hfi->type == FT_STRING) {
686 /* Custom string, add quotes */
687 filter.append(QString("%1 == \"%2\"")
688 .arg(cap_file_->cinfo.col_expr.col_expr[ctx_column_])
689 .arg(cap_file_->cinfo.col_expr.col_expr_val[ctx_column_]));
692 if (filter.isEmpty()) {
693 filter.append(QString("%1 == %2")
694 .arg(cap_file_->cinfo.col_expr.col_expr[ctx_column_])
695 .arg(cap_file_->cinfo.col_expr.col_expr_val[ctx_column_]));
700 epan_dissect_cleanup(&edt);
706 QString PacketList::packetComment()
708 int row = currentIndex().row();
712 if (!cap_file_ || !packet_list_model_) return NULL;
714 fdata = packet_list_model_->getRowFdata(row);
716 if (!fdata) return NULL;
718 pkt_comment = cf_get_comment(cap_file_, fdata);
720 return QString(pkt_comment);
722 /* XXX, g_free(pkt_comment) */
725 void PacketList::setPacketComment(QString new_comment)
727 int row = currentIndex().row();
729 gchar *new_packet_comment = new_comment.toUtf8().data();
731 if (!cap_file_ || !packet_list_model_) return;
733 fdata = packet_list_model_->getRowFdata(row);
737 /* Check if we are clearing the comment */
738 if(new_comment.isEmpty()) {
739 new_packet_comment = NULL;
742 cf_set_user_packet_comment(cap_file_, fdata, new_packet_comment);
747 QString PacketList::allPacketComments()
753 if (!cap_file_) return buf_str;
755 for (framenum = 1; framenum <= cap_file_->count ; framenum++) {
756 fdata = frame_data_sequence_find(cap_file_->frames, framenum);
758 char *pkt_comment = cf_get_comment(cap_file_, fdata);
761 buf_str.append(QString(tr("Frame %1: %2 \n\n")).arg(framenum).arg(pkt_comment));
764 if (buf_str.length() > max_comments_to_fetch_) {
765 buf_str.append(QString(tr("[ Comment text exceeds %1. Stopping. ]"))
766 .arg(format_size(max_comments_to_fetch_, format_size_unit_bytes|format_size_prefix_si)));
775 void PacketList::setCaptureFile(capture_file *cf)
778 packet_list_model_->setCaptureFile(cf);
781 void PacketList::goNextPacket(void) {
782 setCurrentIndex(moveCursor(MoveDown, Qt::NoModifier));
785 void PacketList::goPreviousPacket(void) {
786 setCurrentIndex(moveCursor(MoveUp, Qt::NoModifier));
789 void PacketList::goFirstPacket(void) {
790 setCurrentIndex(moveCursor(MoveHome, Qt::NoModifier));
793 void PacketList::goLastPacket(void) {
794 setCurrentIndex(moveCursor(MoveEnd, Qt::NoModifier));
797 // XXX We can jump to the wrong packet if a display filter is applied
798 void PacketList::goToPacket(int packet) {
799 int row = packet_list_model_->packetNumberToRow(packet);
801 setCurrentIndex(packet_list_model_->index(row, 0));
805 void PacketList::markFrame()
807 int row = currentIndex().row();
810 if (!cap_file_ || !packet_list_model_) return;
812 fdata = packet_list_model_->getRowFdata(row);
814 setFrameMark(!fdata->flags.marked, fdata);
818 void PacketList::markAllDisplayedFrames(bool set)
823 if (!cap_file_ || !packet_list_model_) return;
825 for (framenum = 1; framenum <= cap_file_->count; framenum++) {
826 fdata = frame_data_sequence_find(cap_file_->frames, framenum);
827 if (fdata->flags.passed_dfilter)
828 setFrameMark(set, fdata);
833 void PacketList::ignoreFrame()
835 int row = currentIndex().row();
838 if (!cap_file_ || !packet_list_model_) return;
840 fdata = packet_list_model_->getRowFdata(row);
842 setFrameIgnore(!fdata->flags.ignored, fdata);
843 emit packetDissectionChanged();
846 void PacketList::ignoreAllDisplayedFrames(bool set)
851 if (!cap_file_ || !packet_list_model_) return;
853 for (framenum = 1; framenum <= cap_file_->count; framenum++) {
854 fdata = frame_data_sequence_find(cap_file_->frames, framenum);
855 if (!set || fdata->flags.passed_dfilter)
856 setFrameIgnore(set, fdata);
858 emit packetDissectionChanged();
861 void PacketList::setTimeReference()
863 if (!cap_file_) return;
865 if (cap_file_->current_frame) {
866 if(recent.gui_time_format != TS_RELATIVE && cap_file_->current_frame->flags.ref_time==0) {
867 int ret = QMessageBox::question(
869 tr("Change Time Display Format?"),
870 tr("Time References don't work well with the currently selected Time Display Format.\n"
871 "Do you want to switch to \"Seconds Since Beginning of Capture\" now?"),
872 QMessageBox::Yes | QMessageBox::No
874 if (ret == QMessageBox::Yes) {
875 timestamp_set_type(TS_RELATIVE);
876 recent.gui_time_format = TS_RELATIVE;
877 cf_timestamp_auto_precision(cap_file_);
880 setFrameReftime(!cap_file_->current_frame->flags.ref_time,
881 cap_file_->current_frame);
887 void PacketList::unsetAllTimeReferences()
889 if (!cap_file_) return;
891 /* XXX: we might need a progressbar here */
894 for (framenum = 1; framenum <= cap_file_->count && cap_file_->ref_time_count > 0; framenum++) {
895 fdata = frame_data_sequence_find(cap_file_->frames, framenum);
896 if (fdata->flags.ref_time == 1) {
897 setFrameReftime(FALSE, fdata);
903 void PacketList::addRelatedFrame(int related_frame)
905 related_packet_delegate_.addRelatedFrame(related_frame);
914 * indent-tabs-mode: nil
917 * ex: set shiftwidth=4 tabstop=8 expandtab:
918 * :indentSize=4:tabSize=8:noTabs=true: