Revealer 在激活时隐藏另一个 revealer (gtk_tree_store) - GTK3,C

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

背景

这是练习的一部分,我在练习中创建了一个“作为 Wireshark”的小型网络数据包分析器。

瞄准

我正在尝试将数据包的数据存储在 gtk_tree_store 中,可以显示:

代码

使用的结构:

数据包的数据存储在一个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;

带按钮的 trames 链表(上部 window,arbre(下部 window 的显示符)

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

此函数创建一个新的gtk_store_tree,其中包含数据包中收集的所有数据

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;
}

此函数调用 remplir_arbre() 并创建新的揭示器,它将堆叠在下方 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);
}

问题

我在想是不是因为我用了 gtk_box 来堆叠揭密器,但似乎不是这样。

编辑

我首先移除了显示器以查看是否可以,尝试查看树的所有 child,然后找到隐藏它们的解决方案。

我注意到了一些事情:

已解决

最后我找到了GTK提供的另一种结构,它符合我的需要。 我没有使用 gtk_trees ,而是使用一些 gtk_expanders 结合 gtk_box 将小部件堆叠到其中。

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

外观如下:

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;
    }

我仍然不知道为什么 gtk_tree 没有工作。