diff --git a/file.c b/file.c index 03e4d64487..eccf1a3c84 100644 --- a/file.c +++ b/file.c @@ -1898,6 +1898,8 @@ rescan_packets(capture_file *cf, const char *action, const char *action_item, /* Unfreeze the packet list. */ #ifdef NEW_PACKET_LIST + if (!add_to_packet_list) + new_packet_list_recreate_visible_rows(); new_packet_list_thaw(); #else packet_list_thaw(); diff --git a/gtk/new_packet_list.c b/gtk/new_packet_list.c index 524e492626..16dc7031b2 100644 --- a/gtk/new_packet_list.c +++ b/gtk/new_packet_list.c @@ -74,9 +74,6 @@ static void show_cell_data_func(GtkTreeViewColumn *col, GtkTreeModel *model, GtkTreeIter *iter, gpointer data); -static void filter_function (GtkTreeView *treeview); -static gboolean filter_visible_func (GtkTreeModel *model, GtkTreeIter *iter, gpointer data _U_); - GtkWidget * new_packet_list_create(void) @@ -114,10 +111,8 @@ new_packet_list_append(column_info *cinfo _U_, frame_data *fdata, packet_info *p row_data.fdata = fdata; - packet_list_append_record(packetlist, &row_data); - - /* XXX - Check that this is the right # */ - return PACKET_LIST_RECORD_COUNT(packetlist->rows); + /* Return the _visible_ position */ + return packet_list_append_record(packetlist, &row_data); } static gboolean @@ -262,7 +257,8 @@ new_packet_list_freeze(void) void new_packet_list_thaw(void) { - filter_function(GTK_TREE_VIEW(packetlist->view)); + /* Apply model */ + gtk_tree_view_set_model( GTK_TREE_VIEW(packetlist->view), GTK_TREE_MODEL(packetlist)); /* Remove extra reference added by new_packet_list_freeze() */ g_object_unref(packetlist); @@ -270,6 +266,12 @@ new_packet_list_thaw(void) packets_bar_update(); } +void +new_packet_list_recreate_visible_rows(void) +{ + packet_list_recreate_visible_rows(packetlist); +} + void new_packet_list_resize_columns_cb(GtkWidget *widget _U_, gpointer data _U_) { @@ -568,7 +570,7 @@ new_packet_list_get_row_data(gint row) { PacketListRecord *record; - record = PACKET_LIST_RECORD_GET(packetlist->rows, row-1); + record = PACKET_LIST_RECORD_GET(packetlist->physical_rows, row-1); return record->fdata; } @@ -650,7 +652,7 @@ show_cell_data_func(GtkTreeViewColumn *col _U_, GtkCellRenderer *renderer, record = new_packet_list_get_record(model, iter); fdata = record->fdata; - row = record->pos; + row = record->physical_pos; if (record->dissected) color_filter = fdata->color_filter; @@ -772,28 +774,6 @@ void new_packet_list_mark_frame_cb(GtkWidget *w _U_, gpointer data _U_) mark_frames_ready(); } -static void filter_function (GtkTreeView *treeview) -{ - GtkTreeModel *filter_model; - - filter_model = gtk_tree_model_filter_new(GTK_TREE_MODEL(packetlist), NULL ); - - gtk_tree_model_filter_set_visible_func (GTK_TREE_MODEL_FILTER ( filter_model ),(GtkTreeModelFilterVisibleFunc) filter_visible_func, NULL , NULL); - - /* Apply model */ - gtk_tree_view_set_model( GTK_TREE_VIEW( treeview ),filter_model); - - g_object_unref( filter_model ); -} - -/* This function is called on every model row. We check whether the packet - * should be visible or not. - */ -static gboolean -filter_visible_func (GtkTreeModel *model _U_, GtkTreeIter *iter, gpointer data _U_) -{ - return packet_list_visible_record(packetlist, iter); -} static gboolean get_col_text_from_record( PacketListRecord *record, gint col_num, gchar** cell_text){ diff --git a/gtk/packet_list_store.c b/gtk/packet_list_store.c index a0a49ca383..3a29f3ebfa 100644 --- a/gtk/packet_list_store.c +++ b/gtk/packet_list_store.c @@ -98,9 +98,6 @@ static gboolean packet_list_sortable_has_default_sort_func(GtkTreeSortable static void packet_list_sortable_init(GtkTreeSortableIface *iface); static gint packet_list_compare_records(gint sort_id _U_, PacketListRecord *a, PacketListRecord *b); -static gint packet_list_qsort_compare_func(PacketListRecord **a, - PacketListRecord **b, - PacketList *packet_list); static void packet_list_resort(PacketList *packet_list); static GObjectClass *parent_class = NULL; @@ -221,16 +218,17 @@ packet_list_init(PacketList *packet_list) packet_list->column_types[i] = G_TYPE_STRING; } + /* To check whether an iter belongs to our model. */ + packet_list->stamp = g_random_int(); + /* Note: We need one extra column to store the entire PacketListRecord */ packet_list->column_types[i] = G_TYPE_POINTER; packet_list->n_columns = (guint)cfile.cinfo.num_cols+1; - packet_list->rows = g_ptr_array_new(); + packet_list->physical_rows = g_ptr_array_new(); + packet_list->visible_rows = g_ptr_array_new(); packet_list->sort_id = 0; /* defaults to first column for now */ packet_list->sort_order = GTK_SORT_ASCENDING; - - packet_list->stamp = g_random_int(); /* To check whether an iter belongs - * to our model. */ } /* This function is called just before a packet list is destroyed. Free @@ -297,13 +295,15 @@ packet_list_get_iter(GtkTreeModel *tree_model, GtkTreeIter *iter, n = indices[0]; /* the n-th top level row */ packet_list = PACKET_LIST(tree_model); - if(n >= PACKET_LIST_RECORD_COUNT(packet_list->rows)) + if(PACKET_LIST_RECORD_COUNT(packet_list->visible_rows) == 0) return FALSE; - record = PACKET_LIST_RECORD_GET(packet_list->rows, n); + if(!PACKET_LIST_RECORD_INDEX_VALID(packet_list->visible_rows, n)) + return FALSE; - g_assert(record != NULL); - g_assert(record->pos == n); + record = PACKET_LIST_RECORD_GET(packet_list->visible_rows, n); + + g_assert(record->visible_pos == n); /* We simply store a pointer to our custom record in the iter */ iter->stamp = packet_list->stamp; @@ -330,7 +330,7 @@ packet_list_get_path(GtkTreeModel *tree_model, GtkTreeIter *iter) record = (PacketListRecord*) iter->user_data; path = gtk_tree_path_new(); - gtk_tree_path_append_index(path, record->pos); + gtk_tree_path_append_index(path, record->visible_pos); return path; } @@ -345,16 +345,18 @@ packet_list_get_value(GtkTreeModel *tree_model, GtkTreeIter *iter, gint column, g_return_if_fail(PACKETLIST_IS_LIST(tree_model)); g_return_if_fail(iter != NULL); + packet_list = PACKET_LIST(tree_model); /* Note: We use one extra column to store the entire PacketListRecord */ g_return_if_fail(column < packet_list->n_columns); - type = packet_list->column_types[column]; - g_value_init(value, type); - record = (PacketListRecord*) iter->user_data; - g_return_if_fail(record->pos < PACKET_LIST_RECORD_COUNT(packet_list->rows)); + g_return_if_fail(PACKET_LIST_RECORD_INDEX_VALID(packet_list->physical_rows, record->physical_pos)); + g_return_if_fail(PACKET_LIST_RECORD_INDEX_VALID(packet_list->visible_rows, record->visible_pos)); + + type = packet_list->column_types[column]; + g_value_init(value, type); /* XXX Probably the switch should be on column or * should we allways return the pointer and read the data as required?? @@ -374,6 +376,27 @@ packet_list_get_value(GtkTreeModel *tree_model, GtkTreeIter *iter, gint column, } } +static PacketListRecord * +packet_list_iter_next_visible(PacketList *packet_list, PacketListRecord *record) +{ + PacketListRecord *nextrecord; + gint next_visible_pos; + + g_assert(record->visible_pos >= 0); + next_visible_pos = record->visible_pos + 1; + + /* Is this the last record in the list? */ + if(!PACKET_LIST_RECORD_INDEX_VALID(packet_list->visible_rows, next_visible_pos)) + return NULL; + + nextrecord = PACKET_LIST_RECORD_GET(packet_list->visible_rows, next_visible_pos); + + g_assert(nextrecord->visible_pos == (record->visible_pos + 1)); + g_assert(nextrecord->physical_pos >= (record->physical_pos + 1)); + + return nextrecord; +} + /* Takes an iter structure and sets it to point to the next row. */ static gboolean packet_list_iter_next(GtkTreeModel *tree_model, GtkTreeIter *iter) @@ -383,22 +406,19 @@ packet_list_iter_next(GtkTreeModel *tree_model, GtkTreeIter *iter) g_return_val_if_fail(PACKETLIST_IS_LIST(tree_model), FALSE); - if(iter == NULL || iter->user_data == NULL) + if(iter == NULL) return FALSE; + g_return_val_if_fail(iter->user_data, FALSE); + packet_list = PACKET_LIST(tree_model); record = (PacketListRecord*) iter->user_data; + nextrecord = packet_list_iter_next_visible(packet_list, record); - /* Is this the last record in the list? */ - if((record->pos + 1) >= PACKET_LIST_RECORD_COUNT(packet_list->rows)) + if (!nextrecord) return FALSE; - nextrecord = PACKET_LIST_RECORD_GET(packet_list->rows, (record->pos + 1)); - - g_assert(nextrecord != NULL); - g_assert(nextrecord->pos == (record->pos + 1)); - iter->stamp = packet_list->stamp; iter->user_data = nextrecord; @@ -411,27 +431,23 @@ packet_list_iter_children(GtkTreeModel *tree_model, GtkTreeIter *iter, { PacketList *packet_list; - g_return_val_if_fail(parent == NULL || parent->user_data != NULL, - FALSE); + g_return_val_if_fail(parent == NULL || parent->user_data != NULL, FALSE); /* This is a list, nodes have no children. */ if(parent) return FALSE; - /* parent == NULL is a special case; we need to return the first top- - * level row */ - g_return_val_if_fail(PACKETLIST_IS_LIST(tree_model), FALSE); packet_list = PACKET_LIST(tree_model); /* No rows => no first row */ - if(PACKET_LIST_RECORD_COUNT(packet_list->rows) == 0) + if(PACKET_LIST_RECORD_COUNT(packet_list->visible_rows) == 0) return FALSE; /* Set iter to first item in list */ iter->stamp = packet_list->stamp; - iter->user_data = PACKET_LIST_RECORD_GET(packet_list->rows, 0); + iter->user_data = PACKET_LIST_RECORD_GET(packet_list->visible_rows, 0); return TRUE; } @@ -447,16 +463,20 @@ packet_list_iter_n_children(GtkTreeModel *tree_model, GtkTreeIter *iter) { PacketList *packet_list; - g_return_val_if_fail(PACKETLIST_IS_LIST(tree_model), -1); - g_return_val_if_fail(iter == NULL || iter->user_data != NULL, FALSE); + g_return_val_if_fail(PACKETLIST_IS_LIST(tree_model), 0); + g_return_val_if_fail(iter, 0); + g_return_val_if_fail(iter->user_data, 0); packet_list = PACKET_LIST(tree_model); - /* special case: if iter == NULL, return number of top-level rows */ - if(!iter) - return PACKET_LIST_RECORD_COUNT(packet_list->rows); - - return 0; /* Lists have zero children */ + if(!iter) { + /* special case: if iter == NULL, return number of top-level rows */ + return PACKET_LIST_RECORD_COUNT(packet_list->visible_rows); + } + else { + /* Lists have zero children */ + return 0; + } } static gboolean @@ -474,15 +494,13 @@ packet_list_iter_nth_child(GtkTreeModel *tree_model, GtkTreeIter *iter, if(parent) return FALSE; - /* Special case: if parent == NULL, set iter to n-th - * top-level row. */ - if((guint)n >= PACKET_LIST_RECORD_COUNT(packet_list->rows)) - return FALSE; + /* Special case: if parent == NULL, set iter to n-th top-level row. */ + if(!PACKET_LIST_RECORD_INDEX_VALID(packet_list->visible_rows, n)) + return NULL; - record = PACKET_LIST_RECORD_GET(packet_list->rows, n); + record = PACKET_LIST_RECORD_GET(packet_list->visible_rows, n); - g_assert(record != NULL); - g_assert(record->pos == (guint)n); + g_assert(record->visible_pos == n); iter->stamp = packet_list->stamp; iter->user_data = record; @@ -532,9 +550,6 @@ new_packet_list_store_clear(PacketList *packet_list) g_return_if_fail(packet_list != NULL); g_return_if_fail(PACKETLIST_IS_LIST(packet_list)); - if(PACKET_LIST_RECORD_COUNT(packet_list->rows) == 0) - return; - /* Don't issue a row_deleted signal. We rely on our caller to have disconnected * the model from the view. for( ; packet_list->num_rows > 0; --packet_list->num_rows) @@ -542,8 +557,12 @@ new_packet_list_store_clear(PacketList *packet_list) */ /* XXX - hold on to these rows and reuse them instead */ - g_ptr_array_free(packet_list->rows, TRUE); - packet_list->rows = g_ptr_array_new(); + if(packet_list->physical_rows) + g_ptr_array_free(packet_list->physical_rows, TRUE); + if(packet_list->visible_rows) + g_ptr_array_free(packet_list->visible_rows, TRUE); + packet_list->physical_rows = g_ptr_array_new(); + packet_list->visible_rows = g_ptr_array_new(); } #if 0 @@ -585,22 +604,26 @@ packet_list_visible_record(PacketList *packet_list, GtkTreeIter *iter) return record->fdata->flags.passed_dfilter; } -void +gint packet_list_append_record(PacketList *packet_list, row_data_t *row_data) { PacketListRecord *newrecord; - guint pos; - g_return_if_fail(PACKETLIST_IS_LIST(packet_list)); - - pos = PACKET_LIST_RECORD_COUNT(packet_list->rows); + g_return_val_if_fail(PACKETLIST_IS_LIST(packet_list), -1); newrecord = se_alloc(sizeof(PacketListRecord)); newrecord->dissected = FALSE; newrecord->fdata = row_data->fdata; - newrecord->pos = pos; + newrecord->physical_pos = PACKET_LIST_RECORD_COUNT(packet_list->physical_rows); - PACKET_LIST_RECORD_APPEND(packet_list->rows, newrecord); + if (newrecord->fdata->flags.passed_dfilter) { + newrecord->visible_pos = PACKET_LIST_RECORD_COUNT(packet_list->visible_rows); + PACKET_LIST_RECORD_APPEND(packet_list->visible_rows, newrecord); + } + else + newrecord->visible_pos = -1; + + PACKET_LIST_RECORD_APPEND(packet_list->physical_rows, newrecord); /* Don't issue a row_inserted signal. We rely on our caller to have disconnected * the model from the view. @@ -610,6 +633,8 @@ packet_list_append_record(PacketList *packet_list, row_data_t *row_data) /* Don't resort the list for every row, the list will be in packet order any way. * packet_list_resort(packet_list); */ + + return newrecord->visible_pos; } void @@ -619,10 +644,13 @@ packet_list_change_record(PacketList *packet_list, guint row, gint col, column_i g_return_if_fail(PACKETLIST_IS_LIST(packet_list)); - g_assert(row < PACKET_LIST_RECORD_COUNT(packet_list->rows)); - record = PACKET_LIST_RECORD_GET(packet_list->rows, row); - g_assert(record->pos == row); + g_assert(row < PACKET_LIST_RECORD_COUNT(packet_list->physical_rows)); + + record = PACKET_LIST_RECORD_GET(packet_list->physical_rows, row); + + g_assert(record->physical_pos == row); g_assert(!record->fdata->col_text || (record->fdata->col_text[col] == NULL)); + if (!record->fdata->col_text) record->fdata->col_text = se_alloc0(sizeof(record->fdata->col_text) * (packet_list->n_columns-1)); @@ -728,8 +756,9 @@ packet_list_compare_records(gint sort_id, PacketListRecord *a, g_return_val_if_reached(0); } + static gint -packet_list_qsort_compare_func(PacketListRecord **a, PacketListRecord **b, +packet_list_qsort_physical_compare_func(PacketListRecord **a, PacketListRecord **b, PacketList *packet_list) { gint ret; @@ -745,34 +774,64 @@ packet_list_qsort_compare_func(PacketListRecord **a, PacketListRecord **b, return ret; } +static gint +packet_list_qsort_visible_compare_func(PacketListRecord **a, PacketListRecord **b, + PacketList *packet_list) +{ + gint ret; + + g_assert((a) && (b) && (packet_list)); + + ret = ((*a)->visible_pos) < ((*b)->visible_pos) ? -1 : + ((*a)->visible_pos) > ((*b)->visible_pos) ? 1 : 0; + + return ret; +} + static void packet_list_resort(PacketList *packet_list) { + PacketListRecord *record; GtkTreePath *path; gint *neworder; - guint i; + guint phy_idx; + guint vis_idx; g_return_if_fail(packet_list != NULL); g_return_if_fail(PACKETLIST_IS_LIST(packet_list)); - if(PACKET_LIST_RECORD_COUNT(packet_list->rows) == 0) + if(PACKET_LIST_RECORD_COUNT(packet_list->visible_rows) == 0) return; - /* resort */ - g_qsort_with_data(packet_list->rows->pdata, - PACKET_LIST_RECORD_COUNT(packet_list->rows), + /* resort physical rows according to sorting column */ + g_qsort_with_data(packet_list->physical_rows->pdata, + PACKET_LIST_RECORD_COUNT(packet_list->physical_rows), sizeof(PacketListRecord*), - (GCompareDataFunc) packet_list_qsort_compare_func, + (GCompareDataFunc) packet_list_qsort_physical_compare_func, packet_list); /* let other objects know about the new order */ - neworder = g_new0(gint, PACKET_LIST_RECORD_COUNT(packet_list->rows)); + neworder = g_new0(gint, PACKET_LIST_RECORD_COUNT(packet_list->visible_rows)); - for(i = 0; i < PACKET_LIST_RECORD_COUNT(packet_list->rows); ++i) { - neworder[i] = PACKET_LIST_RECORD_GET(packet_list->rows, i)->pos; - PACKET_LIST_RECORD_GET(packet_list->rows, i)->pos = i; + for(phy_idx = 0, vis_idx = 0; phy_idx < PACKET_LIST_RECORD_COUNT(packet_list->physical_rows); ++phy_idx) { + record = PACKET_LIST_RECORD_GET(packet_list->physical_rows, phy_idx); + record->physical_pos = phy_idx; + if (record->visible_pos >= 0) { + neworder[vis_idx] = record->visible_pos; + record->visible_pos = vis_idx; + ++vis_idx; + } } + g_assert(vis_idx == PACKET_LIST_RECORD_COUNT(packet_list->visible_rows)); + + /* resort visible rows according to new physical order */ + g_qsort_with_data(packet_list->visible_rows->pdata, + PACKET_LIST_RECORD_COUNT(packet_list->visible_rows), + sizeof(PacketListRecord*), + (GCompareDataFunc) packet_list_qsort_visible_compare_func, + packet_list); + path = gtk_tree_path_new(); gtk_tree_model_rows_reordered(GTK_TREE_MODEL(packet_list), path, NULL, @@ -782,14 +841,41 @@ packet_list_resort(PacketList *packet_list) g_free(neworder); } +void +packet_list_recreate_visible_rows(PacketList *packet_list) +{ + guint phy_idx; + guint vis_idx; + PacketListRecord *record; + + g_return_if_fail(packet_list != NULL); + g_return_if_fail(PACKETLIST_IS_LIST(packet_list)); + + if(PACKET_LIST_RECORD_COUNT(packet_list->physical_rows) == 0) + return; + + if(packet_list->visible_rows) + g_ptr_array_free(packet_list->visible_rows, TRUE); + + packet_list->visible_rows = g_ptr_array_new(); + + for(phy_idx = 0, vis_idx = 0; phy_idx < PACKET_LIST_RECORD_COUNT(packet_list->physical_rows); ++phy_idx) { + record = PACKET_LIST_RECORD_GET(packet_list->physical_rows, phy_idx); + if (record->fdata->flags.passed_dfilter) { + record->visible_pos = vis_idx++; + PACKET_LIST_RECORD_APPEND(packet_list->visible_rows, record); + } + } +} + void packet_list_reset_dissected(PacketList *packet_list) { PacketListRecord *record; guint i; - for(i = 0; i < PACKET_LIST_RECORD_COUNT(packet_list->rows); ++i) { - record = PACKET_LIST_RECORD_GET(packet_list->rows, i); + for(i = 0; i < PACKET_LIST_RECORD_COUNT(packet_list->physical_rows); ++i) { + record = PACKET_LIST_RECORD_GET(packet_list->physical_rows, i); record->dissected = FALSE; } } diff --git a/gtk/packet_list_store.h b/gtk/packet_list_store.h index 8954bffc62..8fe2df3c56 100644 --- a/gtk/packet_list_store.h +++ b/gtk/packet_list_store.h @@ -45,10 +45,11 @@ typedef struct _PacketListRecord PacketListRecord; typedef struct _PacketList PacketList; typedef struct _PacketListClass PacketListClass; -#define PACKET_LIST_RECORD_GET(rows, pos) ((PacketListRecord*) g_ptr_array_index((rows), (pos))) +#define PACKET_LIST_RECORD_GET(rows, pos) ((PacketListRecord*) g_ptr_array_index((rows), (pos))) #define PACKET_LIST_RECORD_SET(rows, pos, item) PACKET_LIST_RECORD_GET((rows), (pos)) = (item) #define PACKET_LIST_RECORD_APPEND(rows, item) g_ptr_array_add((rows), (item)) -#define PACKET_LIST_RECORD_COUNT(rows) ((rows)->len) +#define PACKET_LIST_RECORD_COUNT(rows) ((rows) ? (rows)->len : 0) +#define PACKET_LIST_RECORD_INDEX_VALID(rows, idx) ((rows) ? (((guint) (idx)) < (rows)->len) : FALSE) /* PacketListRecord: represents a row */ struct _PacketListRecord @@ -57,7 +58,10 @@ struct _PacketListRecord frame_data *fdata; /* admin stuff used by the custom list model */ - guint pos; /* position within the array */ + /* position within the physical array */ + guint physical_pos; + /* position within the visible array */ + gint visible_pos; }; /* PacketListRecord: Everything for our model implementation. */ @@ -65,9 +69,9 @@ struct _PacketList { GObject parent; /* MUST be first */ - GPtrArray *rows; /* Dynamically allocated array of pointers to - * the PacketListRecord structure for each - * row. */ + GPtrArray *visible_rows; + /* Array of pointers to the PacketListRecord structure for each row. */ + GPtrArray *physical_rows; gint n_columns; /* Note: We need one extra column to store the entire PacketListRecord */ @@ -77,8 +81,8 @@ struct _PacketList gint sort_id; GtkSortType sort_order; - gint stamp; /* Random integer to check whether an iter belongs to our - * model. */ + /* Random integer to check whether an iter belongs to our model. */ + gint stamp; }; /* PacketListClass: more boilerplate GObject stuff */ @@ -90,8 +94,9 @@ struct _PacketListClass GType packet_list_list_get_type(void); PacketList *new_packet_list_new(void); void new_packet_list_store_clear(PacketList *packet_list); +void packet_list_recreate_visible_rows(PacketList *packet_list); gboolean packet_list_visible_record(PacketList *packet_list, GtkTreeIter *iter); -void packet_list_append_record(PacketList *packet_list, row_data_t *row_data); +gint packet_list_append_record(PacketList *packet_list, row_data_t *row_data); void packet_list_change_record(PacketList *packet_list, guint row, gint col, column_info *cinfo); void packet_list_reset_dissected(PacketList *packet_list); #endif /* NEW_PACKET_LIST */ diff --git a/ui_util.h b/ui_util.h index b2f4955cb2..8a4dc37c5b 100644 --- a/ui_util.h +++ b/ui_util.h @@ -63,6 +63,7 @@ extern void pipe_input_set_handler(gint source, gpointer user_data, int *child_p #ifdef NEW_PACKET_LIST void new_packet_list_clear(void); void new_packet_list_freeze(void); +void new_packet_list_recreate_visible_rows(void); void new_packet_list_thaw(void); void new_packet_list_next(void); void new_packet_list_prev(void);