Search code examples
ctreeviewgtkgtk3

Revealer hiding another revealer when active (gtk_tree_store) - GTK3 , C


Background

This is part of an exercise, in which I am creating a small network packet analyzer "as Wireshark".

Aim

I'm trying to store the Data of packets in a gtk_tree_store which can be revealed: my window with revealers

Code

structures used:

packet's data is stored in a trame.

typedef struct trame_{
    unsigned int *tab;
    int id;
    int nb_ligne_erreur;
    int nb_octet_erreur;
    
    //couche ethernet
    char *mac_dest;
    char *mac_source;
    char *ip_type;
    
    //couche ip
    char *version;
    char *header_length;

    int *total_length;
    int *identification;
    int *flags_frag_offset;
    int TTL;
    int protocol;
    int *header_checksum; 
    int *ip_source;
    int *ip_dest;
    
    //couche tcp
    int source_port;
    int destination_port;
    int stream_index;
    int tcp_seg_len;
    char* sequence_number;
    int sequence_number_raw;
    char *next_sequence_number;
    char *acknowledgment_number;
    int acknowledgment_number_raw;
    char *tcp_header_length;
}trame;

chained list of trames with buttons (upper window, arbre (revealers on the lower window)

typedef struct cell_{
    trame *obj;
    GtkWidget *arbre;
    GtkWidget *bouton;
    struct cell_ *suiv;
    int status_bouton_ip;
}cell;

this function create a new gtk_store_tree with all the data collected in a packet

void remplir_arbre(GtkWidget *pWidget, gpointer pData){
    
    cell *tmp_cell=(cell *)pData;   
    
    GtkTreeStore *arbre=gtk_tree_store_new(2, G_TYPE_STRING, G_TYPE_STRING);
    GtkTreeIter header_ethernet;
    GtkTreeIter contenu_ethernet;
    GtkTreeIter header_IP;
    GtkTreeIter contenu_IP;
    
    gtk_tree_store_insert (arbre,&header_ethernet,NULL,-1);
    gtk_tree_store_set(arbre, &header_ethernet,0,"Ethernet II",1,NULL, -1);
    
    gtk_tree_store_insert (arbre,&contenu_ethernet,&header_ethernet,-1);
    gtk_tree_store_set(arbre,&contenu_ethernet, 0, "Source:",1,tmp_cell->obj->mac_source, -1);
    gtk_tree_store_insert (arbre,&contenu_ethernet,&header_ethernet,-1);
    gtk_tree_store_set(arbre,&contenu_ethernet, 0, "Destination:",1,tmp_cell->obj->mac_dest, -1);
    gtk_tree_store_insert (arbre,&contenu_ethernet,&header_ethernet,-1);
    gtk_tree_store_set(arbre,&contenu_ethernet, 0, "type:",1,tmp_cell->obj->ip_type, -1);
    
    gtk_tree_store_insert(arbre,&header_IP,NULL,-1);
    gtk_tree_store_set(arbre,&header_IP,0,"Internet Protocol",1,"", -1);
    
    gtk_tree_store_insert(arbre,&contenu_IP,&header_IP,-1);
    gtk_tree_store_set(arbre,&contenu_IP,0,"IP Version:",1,tmp_cell->obj->version, -1);
    gtk_tree_store_insert(arbre,&contenu_IP,&header_IP,-1);
    gtk_tree_store_set(arbre,&contenu_IP,0,"IP Version:",1,tmp_cell->obj->version, -1);
    gtk_tree_store_insert(arbre,&contenu_IP,&header_IP,-1);
    gtk_tree_store_set(arbre,&contenu_IP,0,"IP Version:",1,tmp_cell->obj->version, -1);
    
    tmp_cell->arbre = gtk_tree_view_new_with_model(GTK_TREE_MODEL(arbre));
    
    GtkCellRenderer *renderer_col1;
    GtkCellRenderer *renderer_col2;
    GtkTreeViewColumn *column;
    GtkTreeViewColumn *column_2;
    
    char label[20];
    sprintf(label,"trame n°%d",tmp_cell->obj->id);

    renderer_col1 = gtk_cell_renderer_text_new();
    renderer_col2 = gtk_cell_renderer_text_new();
    
    column = gtk_tree_view_column_new_with_attributes(label, renderer_col1, "text", 0, NULL);
    column_2 = gtk_tree_view_column_new_with_attributes(NULL, renderer_col2, "text",1, NULL);
    
    gtk_tree_view_append_column(GTK_TREE_VIEW(tmp_cell->arbre), column);
    gtk_tree_view_append_column(GTK_TREE_VIEW(tmp_cell->arbre), column_2);
    
    return;
}

this Function call remplir_arbre() and create and new revealer which is going to be stacked in the lower window

void ajout_liste(cell **liste,trame *elem,GtkWidget* box_haut, GtkWidget* box_bas){
    char label[80];
    sprintf(label,"%d\t%d:%d:%d:%d\t%d:%d:%d:%d",elem->id,(elem->ip_source)[0],(elem->ip_source)[1],(elem->ip_source)[2],(elem->ip_source)[3],(elem->ip_dest)[0],(elem->ip_dest)[1],(elem->ip_dest)[2],(elem->ip_dest)[3]);                 
    
    GtkWidget* tmp_bouton=gtk_toggle_button_new_with_label(label);
    if (elem->nb_ligne_erreur==-1){
        gtk_widget_set_name(tmp_bouton,"button_dark_mode");
    }else {
        gtk_widget_set_name(tmp_bouton,"button_dark_mode_erreur");
    }
    cell *new_cell=(cell *) malloc(sizeof(cell));
    GtkWidget *revealer = gtk_revealer_new();
    new_cell->obj=elem;
    new_cell->arbre=NULL;
    new_cell->bouton=tmp_bouton;
    new_cell->suiv=(*liste);
    new_cell->status_bouton_ip=0;
    *liste=new_cell;
    
    remplir_arbre(NULL, new_cell);
    gtk_widget_set_name(new_cell->arbre,"tree_dark_mode");
    gtk_container_add(GTK_CONTAINER(revealer), new_cell->arbre);
    gtk_revealer_set_reveal_child(GTK_REVEALER(revealer), FALSE);
    gtk_box_pack_start(GTK_BOX(box_haut),tmp_bouton, FALSE,TRUE, 0);
    gtk_box_pack_start(GTK_BOX(box_bas),revealer, FALSE, FALSE, 0); #box_bas is a gtk_box were all revealers are stacked ( the lower box on the screen)
    gtk_widget_show (tmp_bouton);
    gtk_widget_show_all(box_bas);
    g_signal_connect(G_OBJECT(tmp_bouton), "clicked", G_CALLBACK(action_bouton_ip),new_cell);
    g_object_bind_property(tmp_bouton, "active", revealer, "reveal-child", 1);
}

problem

  • Revealers don't show all of the rows of their child until all of the revealers are not activated: revealer bugged

    • all revealers activated all revealers activated
  • activated revealers hide non-activated other ones:

    • a revealer hiding another one revealer hiding another one -all revealers non-activated all revealers non-activated

I was wondering if it was because i was using a gtk_box to stack revealers but it does not seems to be it.

Edit

I removed the revealer to see if i could at first , try to see all of the tree's childs and then find a solution to hide them.

i noticed some things :

  • i can always see all the childs of the second child of the tree ( Internet Protocol)
  • sometimes i can see all of the first child (Ethernet II ) rows without activating the second child ( Internet Protocol )

Solution

  • Solved

    Finally i found another structure provided by GTK which fits to my needs. Instead of using gtk_trees , i'm using some gtk_expanders combined with gtk_box to stack widgets into.

    https://developer.gnome.org/gtk3/stable/GtkExpander.html

    here is how it looks: window with expanders

    void remplir_ethernet(GtkWidget *box_ethernet,cell *tmp_cell){
        char label[80];
        GtkWidget *tmp_label=NULL;
    
        sprintf(label,"\tSource\t\t:  %s\n",(tmp_cell->obj->mac_source));
        tmp_label=gtk_label_new(label);
        gtk_label_set_xalign (GTK_LABEL(tmp_label),0);
        gtk_box_pack_start(GTK_BOX(box_ethernet),tmp_label, FALSE, FALSE, 0);
    
       sprintf(label,"\tDestination\t:  %s\n",(tmp_cell->obj->mac_dest));
       tmp_label=gtk_label_new(label);
       gtk_label_set_xalign (GTK_LABEL(tmp_label),0);
       gtk_box_pack_start(GTK_BOX(box_ethernet),tmp_label, FALSE, FALSE, 0);
    
       sprintf(label,"\ttype\t\t:  %s\n",(tmp_cell->obj->ip_type));
       tmp_label=gtk_label_new(label);
       gtk_label_set_xalign (GTK_LABEL(tmp_label),0);
       gtk_box_pack_start(GTK_BOX(box_ethernet),tmp_label, FALSE, FALSE, 0);
    
    }
    
    void remplir_ip(GtkWidget *box_ip,cell *tmp_cell){
        char label[80];
        GtkWidget *tmp_label=NULL;
    
        sprintf(label,"\tVersion\t\t:  %s\n",(tmp_cell->obj->version));
        tmp_label=gtk_label_new(label);
        gtk_label_set_xalign (GTK_LABEL(tmp_label),0);
        gtk_box_pack_start(GTK_BOX(box_ip),tmp_label, FALSE, FALSE, 0);
    }
    
    
    void remplir_arbre(GtkWidget *new_box, gpointer pData){
    
        cell *tmp_cell=(cell *)pData;
    
        GtkWidget *ethernet=gtk_expander_new ("Ethernet II");
        gtk_expander_set_resize_toplevel (GTK_EXPANDER(ethernet),FALSE);
        gtk_box_pack_start (GTK_BOX(new_box),ethernet,FALSE,FALSE,0);
    
        GtkWidget *box_ethernet=gtk_box_new(FALSE,0);
        gtk_orientable_set_orientation (GTK_ORIENTABLE    (box_ethernet),GTK_ORIENTATION_VERTICAL);
        gtk_container_add(GTK_CONTAINER(ethernet),box_ethernet);
        remplir_ethernet(box_ethernet,tmp_cell);    
    
        GtkWidget *IP=gtk_expander_new ("Internet Protocol");
        gtk_expander_set_resize_toplevel (GTK_EXPANDER(IP),FALSE);
        gtk_box_pack_start (GTK_BOX(new_box),IP,FALSE,FALSE,0);
    
        GtkWidget *box_ip=gtk_box_new(FALSE,0);
        gtk_orientable_set_orientation (GTK_ORIENTABLE    (box_ip),GTK_ORIENTATION_VERTICAL);
        gtk_container_add(GTK_CONTAINER(IP),box_ip);
        remplir_ip(box_ip,tmp_cell);    
        
        return;
        }
    

    I still don't know why gtk_tree did not work.