Crash in GtkTreeView (win64 gtk2.12)
- From: Christoph Schmeding <cschmeding altair com>
- To: gtk-app-devel-list gnome org
- Cc: Romain ALDEGUER <romain altair com>, Olivier Chertier <ochertier altair com>, Paolo Sansalvadore <paolo altair com>
- Subject: Crash in GtkTreeView (win64 gtk2.12)
- Date: Tue, 21 Jul 2009 17:42:23 +0200
Hi
For our application, we are managing some GtkTreeView(s). Our
application works on several plateforms, including
win32 and win64. For win32 we are using GTK 2.4 and for win64 we are
using GTK2.12
We are encontering a pb that occurs on 64 bits only.
Below, is a sample file that simulate what is done in our application.
The crash scenario is
- Populate the tree
- Sort with "TYPE" column
- click on "Rebuild"
The crash does not always occur but it crashes approximatively once
every 3 attempts.
The crash does not occur if we link with GTK 2.16, however for internal
reason, we have to use GTK2.12
Does anyone know if a specific patch was introduced between GTK2.12 and
GTK2.16?
Or at least can anyone give us a hint (files, or functions to diff
between version, ....)
Any help wil be appreciated because we are really stuck!
Thanks
PS:
This is the code:
------------------------------------------
#include <gtk/gtk.h>
#include <stdlib.h>
#include <string.h>
typedef struct _TreeItem TreeItem;
GtkTreeModel *model;
GtkTreeSelection *selection;
GtkTreeViewColumn *id_column;
static GtkTreeModel *create_and_fill_model(void);
void *create_view_model(GtkTreeView *view,GtkTreeModel *model);
struct _TreeItem
{
const gchar *name;
const gchar *id;
const gchar *type;
const gchar *subtype;
const gchar *entry;
TreeItem *children;
};
enum
{
Name=0,
ID,
Type,
SubType,
Color,
Pixbuf,
N_COLUMNS
};
static GdkColor color;
static TreeItem mats[]=
{
{"Shell","1","MAT","P_SHELL","",NULL},
{"Solid","2","MAT","P_SOLID","",NULL},
{NULL}
};
static TreeItem props[]=
{
{"P_SHELL","4","PROP","shell","",NULL},
{"P_SOLID","21","PROP","solid","",NULL},
{NULL}
};
static TreeItem comps[]=
{
{"PART_1","1","PART","SH3N","",NULL},
{"PART_2","12","PART","SHELL","",NULL},
{"PART_3","11","PART","SH3N","",NULL},
{"PART_4","9","PART","SHELL","",NULL},
{NULL}
};
static TreeItem rwalls[]=
{
{"RWALL_1","1","RWALL","PARAL","",NULL},
{"RWALL_2","5","RWALL","CYL","",NULL},
{"RWALL_3","9","RWALL","PARAL","",NULL},
{"RWALL_4","4","RWALL","CYL","",NULL},
{NULL}
};
static TreeItem toplevel[]=
{
{"PART","","","","",comps},
{"RWALL","","","","",rwalls},
{"MAT","","","","",mats},
{"PROPS","","","","",props},
{NULL}
};
static TreeItem modelexample[]=
{
{"Model","","","","",toplevel},
{NULL}
};
gint name_compare_func (GtkTreeModel *model, GtkTreeIter *a, GtkTreeIter
*b, gpointer user_data)
{/* sorting names*/
char *first =NULL;
char *sec = NULL;
GtkTreeIter parent;
gtk_tree_model_get(model, a,Name, &first, -1);
gtk_tree_model_get(model, b,Name, &sec, -1);
if (gtk_tree_model_iter_has_child(model, a) ||
gtk_tree_model_iter_has_child(model, b))
return 0;
if( first == NULL || sec == NULL )
{
if( first==NULL && sec==NULL)
{
return 0;
}
return (first == NULL) ? -1 : 1;
}
return g_utf8_collate(first,sec);
}
gint id_compare_func (GtkTreeModel *model,
GtkTreeIter *a,
GtkTreeIter *b,
gpointer user_data)
{
char *first, *sec = NULL;
GtkTreeIter parent;
gtk_tree_model_get(model, a,ID, &first, -1);
gtk_tree_model_get(model, b,ID, &sec, -1);
/* no sort for root folder */
if (!gtk_tree_model_iter_parent(GTK_TREE_MODEL(model), &parent, a))
return 0;
int first_t, sec_t;
first_t = atoi(first);
sec_t = atoi(sec);
if (GTK_SORT_ASCENDING == gtk_tree_view_column_get_sort_order (id_column))
{
if (first_t < sec_t)
return -1;
else
return 1;
} else
{
if (first_t > sec_t)
return 1;
else
return -1;
}
return 0;
}
void dialog_popup(GtkWidget *window,GdkEvent *event,gpointer data)
{
GtkWidget *dialog;
GtkWidget *box;
GtkWidget *label;
dialog=gtk_dialog_new_with_buttons("Validate",GTK_WINDOW(window),GTK_DIALOG_MODAL,"Yes",GTK_RESPONSE_ACCEPT,"No",GTK_RESPONSE_CANCEL,NULL);
box=gtk_hbox_new(FALSE,5);
gtk_container_set_border_width(GTK_CONTAINER(box),20);
gtk_container_add(GTK_CONTAINER(GTK_DIALOG (dialog)-> vbox),box);
gtk_widget_show(box);
label=gtk_label_new("Are you sure to close?");
gtk_box_pack_start(GTK_BOX(box),label,TRUE,TRUE,0);
gtk_widget_show(label);
gint result=gtk_dialog_run(GTK_DIALOG(dialog));
switch (result)
{
case GTK_RESPONSE_ACCEPT:
gtk_widget_destroy(window);
default:
gtk_widget_hide(dialog);
}
}
void on_edit(GtkCellRendererText *cell,const gchar *path_string,const
gchar *new_text,gpointer data)
{
GtkTreeModel *model = (GtkTreeModel *)data;
GtkTreePath *path = gtk_tree_path_new_from_string (path_string);
GtkTreeIter iter;
gboolean check;
gint column = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (cell),
"column"));
gtk_tree_model_get_iter (model, &iter, path);
check=gtk_tree_model_iter_has_child(model,&iter);
if(check == FALSE)
{
gchar *old_text;
gtk_tree_model_get (model, &iter, column, &old_text, -1);
g_free(old_text);
gtk_tree_store_set (GTK_TREE_STORE(model), &iter, column,new_text, -1);
}
gtk_tree_path_free(path);
}
void on_clicked(GtkCellRenderer *cell,const gchar *path_string,guint x,
guint y,gpointer data)
{
GtkWidget *color_dialog;
GtkColorSelection *colorselection;
gint response_for_color;
color_dialog=gtk_color_selection_dialog_new("Select");
colorselection=GTK_COLOR_SELECTION(GTK_COLOR_SELECTION_DIALOG(color_dialog)->colorsel);
gtk_color_selection_set_previous_color (colorselection, &color);
gtk_color_selection_set_current_color (colorselection, &color);
gtk_color_selection_set_has_palette (colorselection, TRUE);
response_for_color = gtk_dialog_run (GTK_DIALOG (color_dialog));
if (response_for_color == GTK_RESPONSE_OK)
{
gtk_color_selection_get_current_color (colorselection,&color);
g_object_set(GTK_CELL_RENDERER(cell),"cell-background-gdk",&color,NULL);
}
gtk_widget_destroy (color_dialog);
}
void show_tree_items(GtkWidget *widget,gpointer data)
{
GtkTreeView *view=(GtkTreeView *)data;
gtk_tree_view_expand_all(view);
}
void collapse_tree_items(GtkWidget *widget,gpointer data)
{
GtkTreeView *view=(GtkTreeView *)data;
gtk_tree_view_collapse_all(view);
}
void show_reverse(GtkWidget *widget,gpointer data)
{
GtkTreeView *view=(GtkTreeView *)data;
gtk_tree_view_expand_all(view);
GtkTreePath *path=gtk_tree_path_new_from_indices(0,0,-1);
gtk_tree_view_collapse_row(view,path);
}
void rebuild_treeStore(GtkWidget *widget,gpointer data)
{
GtkTreeView *view=(GtkTreeView *)data;
GtkTreeModel *treestore = gtk_tree_view_get_model(view);
gtk_tree_store_clear(GTK_TREE_STORE(treestore));
gtk_tree_view_set_model(view,NULL);
treestore = NULL;
if(treestore != NULL)
{
printf("TreeModel not NULL\n");
}
treestore = create_and_fill_model();
gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(GTK_TREE_STORE(treestore)),Type,GtkTreeIterCompareFunc(name_compare_func),NULL,NULL);
gtk_tree_view_set_model(view,treestore);
//redo the build to test
treestore = gtk_tree_view_get_model(view);
gtk_tree_store_clear(GTK_TREE_STORE(treestore));
gtk_tree_view_set_model(view,NULL);
treestore = NULL;
if(treestore != NULL)
{
printf("TreeModel not NULL\n");
}
treestore = create_and_fill_model();
gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(GTK_TREE_STORE(treestore)),Type,GtkTreeIterCompareFunc(name_compare_func),NULL,NULL);
gtk_tree_view_set_model(view,treestore);
gtk_tree_view_expand_all(view);
}
static GtkTreeModel *create_and_fill_model(void)
{ GtkTreeStore *store;
GtkTreeIter iter;
GdkPixbuf *icon1;
GError *error = NULL;
TreeItem *model=modelexample;
icon1 = gdk_pixbuf_new_from_file("C:\\home.xpm", &error);
store=gtk_tree_store_new(N_COLUMNS,G_TYPE_STRING,G_TYPE_STRING,G_TYPE_STRING,G_TYPE_STRING,G_TYPE_STRING,GDK_TYPE_PIXBUF);
while(model->name)
{
TreeItem *model_properties=model->children;
gtk_tree_store_append(store,&iter,NULL);
gtk_tree_store_set(store,&iter,Name,model->name,ID,"",Type,"",SubType,"",-1);
while(model_properties->name)
{
TreeItem *props=model_properties->children;
GtkTreeIter child;
gtk_tree_store_append(store,&child,&iter);
gtk_tree_store_set(store,&child,Name,model_properties->name,ID,"",Type,"",SubType,"",-1);
while(props->name)
{
GtkTreeIter child_final;
gtk_tree_store_append(store,&child_final,&child);
gtk_tree_store_set(store,&child_final,Name,props->name,ID,props->id,Type,props->type,SubType,props->subtype,-1);
props++;
}
model_properties++;
}
model++;
}
return GTK_TREE_MODEL (store);
}
void *create_view_model(GtkTreeView *view,GtkTreeModel *model)
{
gint col_offset;
GtkCellRenderer *renderer;
GtkTreeViewColumn *column;
renderer=gtk_cell_renderer_text_new();
g_object_set(renderer,"editable",TRUE,NULL);
//g_signal_connect(renderer,"edited",G_CALLBACK(on_edit),model);
g_object_set_data(G_OBJECT(renderer),"column",GINT_TO_POINTER(Name));
col_offset=gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(view),-1,"Name",renderer,"text",Name,NULL);
column=gtk_tree_view_get_column(GTK_TREE_VIEW(view),col_offset - 1);
gtk_tree_view_column_set_sort_column_id(column,Name);
gtk_tree_view_column_set_sort_indicator(column,TRUE);
gtk_tree_view_column_set_resizable(column,TRUE);
gtk_tree_view_column_set_reorderable(column,TRUE);
gtk_tree_view_column_set_fixed_width (GTK_TREE_VIEW_COLUMN (column), 10);
gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(GTK_TREE_STORE(model)),Name,GtkTreeIterCompareFunc(name_compare_func),NULL,NULL);
renderer=gtk_cell_renderer_text_new();
g_object_set(renderer,"editable",TRUE,NULL);
//g_signal_connect(renderer,"edited",G_CALLBACK(on_edit),model);
g_object_set_data(G_OBJECT(renderer),"column",GINT_TO_POINTER(ID));
col_offset=gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(view),-1,"ID",renderer,"text",ID,NULL);
id_column=gtk_tree_view_get_column(GTK_TREE_VIEW(view),col_offset - 1);
gtk_tree_view_column_set_sort_column_id(id_column,ID);
gtk_tree_view_column_set_sort_indicator(id_column,TRUE);
gtk_tree_view_column_set_resizable(id_column,TRUE);
gtk_tree_view_column_set_reorderable(id_column,TRUE);
gtk_tree_view_column_set_sizing
(GTK_TREE_VIEW_COLUMN(id_column),GTK_TREE_VIEW_COLUMN_FIXED);
gtk_tree_view_column_set_fixed_width (GTK_TREE_VIEW_COLUMN (id_column),50);
gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(GTK_TREE_STORE(model)),ID,GtkTreeIterCompareFunc(id_compare_func),NULL,NULL);
renderer=gtk_cell_renderer_text_new();
g_object_set(renderer,"editable",TRUE,NULL);
//g_signal_connect(renderer,"edited",G_CALLBACK(on_edit),model);
g_object_set_data(G_OBJECT(renderer),"column",GINT_TO_POINTER(Type));
col_offset=gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(view),-1,"Type",renderer,"text",Type,NULL);
column=gtk_tree_view_get_column(GTK_TREE_VIEW(view),col_offset - 1);
gtk_tree_view_column_set_sort_column_id(column,Type);
gtk_tree_view_column_set_sort_indicator(column,TRUE);
gtk_tree_view_column_set_resizable(column,TRUE);
gtk_tree_view_column_set_reorderable(column,TRUE);
gtk_tree_view_column_set_sizing
(GTK_TREE_VIEW_COLUMN(column),GTK_TREE_VIEW_COLUMN_FIXED);
gtk_tree_view_column_set_fixed_width (GTK_TREE_VIEW_COLUMN (column),60);
gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(GTK_TREE_STORE(model)),Type,GtkTreeIterCompareFunc(name_compare_func),NULL,NULL);
renderer=gtk_cell_renderer_text_new();
g_object_set(renderer,"editable",TRUE,NULL);
//g_signal_connect(renderer,"edited",G_CALLBACK(on_edit),model);
g_object_set_data(G_OBJECT(renderer),"column",GINT_TO_POINTER(SubType));
col_offset=gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(view),-1,"SubType",renderer,"text",SubType,NULL);
column=gtk_tree_view_get_column(GTK_TREE_VIEW(view),col_offset - 1);
gtk_tree_view_column_set_sort_column_id(column,SubType);
gtk_tree_view_column_set_sort_indicator(column,TRUE);
gtk_tree_view_column_set_resizable(column,TRUE);
gtk_tree_view_column_set_reorderable(column,TRUE);
gtk_tree_view_column_set_sizing
(GTK_TREE_VIEW_COLUMN(column),GTK_TREE_VIEW_COLUMN_FIXED);
gtk_tree_view_column_set_fixed_width (GTK_TREE_VIEW_COLUMN (column), 50);
return 0;
}
static gint select_view(GtkWidget *widget,GdkEvent *event,gpointer data)
{
if (event->button.button == 3) {
GdkEventButton *bevent = (GdkEventButton *) event;
gtk_menu_popup (GTK_MENU (widget), NULL, NULL, NULL,
NULL,bevent->button, bevent->time);
return TRUE;
}
return FALSE;
}
void make_bold(GtkWidget *widget,GdkEvent *event,gpointer data)
{
GtkTreeIter iter;
gtk_tree_selection_get_selected(selection,&model,&iter);
}
GtkWidget *create_menu(GtkTreeView *view)
{
GtkWidget *select_menu,*item;
select_menu=gtk_menu_new();
item=gtk_menu_item_new_with_label("Make Bold");
gtk_menu_shell_append(GTK_MENU_SHELL(select_menu),item);
g_signal_connect_swapped(G_OBJECT(item),"activate",G_CALLBACK(make_bold),NULL);
gtk_widget_show(item);
g_signal_connect_swapped(G_OBJECT(view),"button-press-event",G_CALLBACK(select_view),select_menu);
return select_menu;
}
int main(int argc,char *argv[])
{ GtkWidget *window;
GtkWidget *vbox,*hbox;
GtkWidget *toolbar;
GtkWidget *first;
GtkWidget *icon1,*icon2,*icon3;
GtkWidget *view;
GtkWidget *menu;
color.red= 0;
color.blue= 65535;
color.green= 0;
gtk_init(&argc,&argv);
window=gtk_window_new(GTK_WINDOW_TOPLEVEL);
g_signal_connect(G_OBJECT(window),"delete_event",G_CALLBACK(dialog_popup),NULL);
gtk_window_set_default_size(GTK_WINDOW(window),600,350);
vbox=gtk_vbox_new(FALSE,0);
gtk_container_add(GTK_CONTAINER(window),vbox);
hbox=gtk_hbox_new(FALSE,0);
gtk_box_pack_start(GTK_BOX(vbox),hbox,FALSE,FALSE,0);
model=create_and_fill_model();
view=gtk_tree_view_new_with_model(model);
gtk_tree_view_set_hover_selection(GTK_TREE_VIEW(view),TRUE);
selection=gtk_tree_view_get_selection(GTK_TREE_VIEW(view));
gtk_tree_selection_set_mode(selection,GTK_SELECTION_EXTENDED);
menu=create_menu(GTK_TREE_VIEW(view));
create_view_model(GTK_TREE_VIEW(view),model);
gtk_container_add(GTK_CONTAINER(vbox),view);
icon1=gtk_image_new_from_stock(GTK_STOCK_APPLY,GTK_ICON_SIZE_SMALL_TOOLBAR);
icon2=gtk_image_new_from_stock(GTK_STOCK_MISSING_IMAGE,GTK_ICON_SIZE_SMALL_TOOLBAR);
icon3=gtk_image_new_from_stock(GTK_STOCK_REDO,GTK_ICON_SIZE_SMALL_TOOLBAR);
GtkWidget *icon4 =
gtk_image_new_from_stock(GTK_STOCK_REFRESH,GTK_ICON_SIZE_SMALL_TOOLBAR);
toolbar=gtk_toolbar_new();
gtk_box_pack_start(GTK_BOX(hbox),toolbar,FALSE,FALSE,0);
gtk_widget_show(toolbar);
gtk_toolbar_append_item(GTK_TOOLBAR(toolbar),"Show","Show the
contents","show",icon1,GTK_SIGNAL_FUNC(show_tree_items),view);
gtk_toolbar_append_item(GTK_TOOLBAR(toolbar),"No Show","Hide the
contents","hide",icon2,GTK_SIGNAL_FUNC(collapse_tree_items),view);
gtk_toolbar_append_item(GTK_TOOLBAR(toolbar),"Reverse","Show the
reverse","reverse",icon3,GTK_SIGNAL_FUNC(show_reverse),view);
gtk_toolbar_append_item(GTK_TOOLBAR(toolbar),"Rebuild","Destroy &
Rebuild Tree
Store","rebuild",icon4,GTK_SIGNAL_FUNC(rebuild_treeStore),view);
gtk_toolbar_set_style(GTK_TOOLBAR(toolbar),GTK_TOOLBAR_BOTH_HORIZ);
gtk_window_set_title(GTK_WINDOW(window),"Tree");
gtk_widget_show_all(window);
gtk_main();
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]