tUse GtkTreeView in options dialog - vaccinewars - be a doctor and try to vaccinate the world (HTM) git clone git://src.adamsgaard.dk/vaccinewars (DIR) Log (DIR) Files (DIR) Refs (DIR) README (DIR) LICENSE --- (DIR) commit d01de5ab48d16a145dd0e34df1148b0230a51489 (DIR) parent a2e4409e98b7c8c00b06fe2a29fc655bbef614f6 (HTM) Author: Ben Webb <ben@salilab.org> Date: Sat, 21 Nov 2020 01:25:41 -0800 Use GtkTreeView in options dialog Replace all use of the obsolete GtkCList class in the options dialog with GtkTreeView and associated classes. Diffstat: M src/gui_client/optdialog.c | 446 ++++++++++++++++++------------- 1 file changed, 257 insertions(+), 189 deletions(-) --- (DIR) diff --git a/src/gui_client/optdialog.c b/src/gui_client/optdialog.c t@@ -66,15 +66,11 @@ static void UpdateAllLists(void) GSList *listpt; for (listpt = clists; listpt; listpt = g_slist_next(listpt)) { - GtkCList *clist = GTK_CLIST(listpt->data); - - if (clist->selection) { - int row = GPOINTER_TO_INT(clist->selection->data); - - if (row >= 0) { - gtk_clist_unselect_row(clist, row, 0); - } - } + GtkTreeView *tv = GTK_TREE_VIEW(listpt->data); + GtkTreeSelection *treesel = gtk_tree_view_get_selection(tv); + /* Force unselection, which should trigger *_sel_changed function to + copy widget data into configuration */ + gtk_tree_selection_unselect_all(treesel); } } t@@ -309,12 +305,19 @@ static void AddStructConfig(GtkWidget *table, int row, gchar *structname, } } -static void swap_rows(GtkCList *clist, gint selrow, gint swaprow, +static void swap_rows(GtkTreeView *tv, gint selrow, gint swaprow, gchar *structname) { GSList *listpt; + GtkTreeIter seliter, swapiter; + GtkTreeModel *model = gtk_tree_view_get_model(tv); + GtkTreeSelection *treesel = gtk_tree_view_get_selection(tv); + + g_assert(gtk_tree_model_iter_nth_child(model, &seliter, NULL, selrow)); + g_assert(gtk_tree_model_iter_nth_child(model, &swapiter, NULL, swaprow)); - gtk_clist_unselect_row(clist, selrow, 0); + gtk_tree_selection_unselect_iter(treesel, &seliter); + gtk_list_store_swap(GTK_LIST_STORE(model), &seliter, &swapiter); for (listpt = configlist; listpt; listpt = g_slist_next(listpt)) { struct ConfigWidget *cwid = (struct ConfigWidget *)listpt->data; t@@ -327,31 +330,57 @@ static void swap_rows(GtkCList *clist, gint selrow, gint swaprow, cwid->data[selrow] = cwid->data[swaprow]; cwid->data[swaprow] = tmp; - if (strcmp(gvar->Name, "Name") == 0) { - gtk_clist_set_text(clist, selrow, 0, cwid->data[selrow]); - gtk_clist_set_text(clist, swaprow, 0, cwid->data[swaprow]); - } } } - gtk_clist_select_row(clist, swaprow, 0); + gtk_tree_selection_select_iter(treesel, &seliter); +} + +/* Return the index of the currently selected row, or -1 if none is selected. + This works only for lists (not trees) with GTK_SELECTION_SINGLE mode */ +static int get_tree_selection_row_index(GtkTreeSelection *treesel, + GtkTreeModel **model) +{ + int row = -1; + GList *selrows = gtk_tree_selection_get_selected_rows(treesel, model); + if (selrows) { + GtkTreePath *path = selrows->data; + gint depth; + gint *inds = gtk_tree_path_get_indices_with_depth(path, &depth); + g_assert(selrows->next == NULL); + g_assert(depth == 1); + row = inds[0]; + } + g_list_free_full(selrows, (GDestroyNotify)gtk_tree_path_free); + return row; } static void list_delete(GtkWidget *widget, gchar *structname) { - GtkCList *clist; - int minlistlength; + GtkTreeView *tv; + GtkTreeSelection *treesel; + GtkTreeModel *model; + int minlistlength, nrows, row; + + tv = GTK_TREE_VIEW(g_object_get_data(G_OBJECT(widget), "treeview")); + g_assert(tv); + treesel = gtk_tree_view_get_selection(tv); + row = get_tree_selection_row_index(treesel, &model); - clist = GTK_CLIST(g_object_get_data(G_OBJECT(widget), "clist")); - g_assert(clist); - minlistlength = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(clist), + minlistlength = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(model), "minlistlength")); + nrows = gtk_tree_model_iter_n_children(model, NULL); - if (clist->rows > minlistlength && clist->selection) { + if (nrows > minlistlength && row >= 0) { + GtkTreeIter iter; GSList *listpt; - int row = GPOINTER_TO_INT(clist->selection->data); + gboolean valid; + /* Prevent selection changed from reading deleted entry */ + g_object_set_data(G_OBJECT(model), "oldsel", GINT_TO_POINTER(-1)); + g_assert(gtk_tree_model_iter_nth_child(model, &iter, NULL, row)); + gtk_tree_selection_unselect_iter(treesel, &iter); + valid = gtk_list_store_remove(GTK_LIST_STORE(model), &iter); - gtk_clist_remove(clist, row); for (listpt = configlist; listpt; listpt = g_slist_next(listpt)) { struct ConfigWidget *cwid = (struct ConfigWidget *)listpt->data; struct GLOBALS *gvar; t@@ -368,21 +397,31 @@ static void list_delete(GtkWidget *widget, gchar *structname) cwid->data = g_realloc(cwid->data, sizeof(gchar *) * cwid->maxindex); } } + if (valid) { + gtk_tree_selection_select_iter(treesel, &iter); + } } } static void list_new(GtkWidget *widget, gchar *structname) { - GtkCList *clist; + GtkTreeView *tv; + GtkListStore *store; + GtkTreeSelection *treesel; + GtkTreeIter iter; int row; GSList *listpt; - gchar *text[3]; + gchar *newname; - clist = GTK_CLIST(g_object_get_data(G_OBJECT(widget), "clist")); - g_assert(clist); + tv = GTK_TREE_VIEW(g_object_get_data(G_OBJECT(widget), "treeview")); + g_assert(tv); + treesel = gtk_tree_view_get_selection(tv); + store = GTK_LIST_STORE(gtk_tree_view_get_model(tv)); - text[0] = g_strdup_printf(_("New %s"), structname); - row = gtk_clist_append(clist, text); + newname = g_strdup_printf(_("New %s"), structname); + gtk_list_store_append(store, &iter); + gtk_list_store_set(store, &iter, 0, newname, -1); + row = gtk_tree_model_iter_n_children(GTK_TREE_MODEL(store), NULL) - 1; for (listpt = configlist; listpt; listpt = g_slist_next(listpt)) { struct ConfigWidget *cwid = (struct ConfigWidget *)listpt->data; t@@ -394,160 +433,165 @@ static void list_new(GtkWidget *widget, gchar *structname) g_assert(cwid->maxindex == row + 1); cwid->data = g_realloc(cwid->data, sizeof(gchar *) * cwid->maxindex); if (strcmp(gvar->Name, "Name") == 0) { - cwid->data[row] = g_strdup(text[0]); + cwid->data[row] = g_strdup(newname); } else { cwid->data[row] = g_strdup(""); } } } - g_free(text[0]); + g_free(newname); - gtk_clist_select_row(clist, row, 0); + gtk_tree_selection_select_iter(treesel, &iter); } static void list_up(GtkWidget *widget, gchar *structname) { - GtkCList *clist; - - clist = GTK_CLIST(g_object_get_data(G_OBJECT(widget), "clist")); - g_assert(clist); + GtkTreeView *tv; + GtkTreeSelection *treesel; + int row; - if (clist->selection) { - int row = GPOINTER_TO_INT(clist->selection->data); + tv = GTK_TREE_VIEW(g_object_get_data(G_OBJECT(widget), "treeview")); + g_assert(tv); + treesel = gtk_tree_view_get_selection(tv); + row = get_tree_selection_row_index(treesel, NULL); - if (row > 0) { - swap_rows(clist, row, row - 1, structname); - } + if (row > 0) { + swap_rows(tv, row, row - 1, structname); } } static void list_down(GtkWidget *widget, gchar *structname) { - GtkCList *clist; - - clist = GTK_CLIST(g_object_get_data(G_OBJECT(widget), "clist")); - g_assert(clist); - - if (clist->selection) { - int row = GPOINTER_TO_INT(clist->selection->data); - int numrows = clist->rows; - - if (row < numrows - 1 && row >= 0) { - swap_rows(clist, row, row + 1, structname); - } + GtkTreeView *tv; + GtkTreeSelection *treesel; + GtkTreeModel *model; + int row, nrows; + + tv = GTK_TREE_VIEW(g_object_get_data(G_OBJECT(widget), "treeview")); + g_assert(tv); + treesel = gtk_tree_view_get_selection(tv); + row = get_tree_selection_row_index(treesel, &model); + nrows = gtk_tree_model_iter_n_children(model, NULL); + + if (row < nrows - 1 && row >= 0) { + swap_rows(tv, row, row + 1, structname); } } -static void list_row_select(GtkCList *clist, gint row, gint column, - GdkEvent *event, gchar *structname) +static void list_sel_changed(GtkTreeSelection *treesel, gpointer data) { - GSList *listpt; + GtkTreeModel *model; GtkWidget *delbut, *upbut, *downbut; - int minlistlength; - - minlistlength = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(clist), - "minlistlength")); - delbut = GTK_WIDGET(g_object_get_data(G_OBJECT(clist), "delete")); - upbut = GTK_WIDGET(g_object_get_data(G_OBJECT(clist), "up")); - downbut = GTK_WIDGET(g_object_get_data(G_OBJECT(clist), "down")); - g_assert(delbut && upbut && downbut); - gtk_widget_set_sensitive(delbut, clist->rows > minlistlength); - gtk_widget_set_sensitive(upbut, row > 0); - gtk_widget_set_sensitive(downbut, row < clist->rows - 1); - - for (listpt = configlist; listpt; listpt = g_slist_next(listpt)) { - struct ConfigWidget *conf = (struct ConfigWidget *)listpt->data; - struct GLOBALS *gvar; - - gvar = &Globals[conf->globind]; - - if (gvar->NameStruct && strcmp(structname, gvar->NameStruct) == 0) { - if (gvar->BoolVal) { - gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(conf->widget), - conf->data[row] != NULL); - } else { - gtk_entry_set_text(GTK_ENTRY(conf->widget), conf->data[row]); - } - } - } -} - -static void list_row_unselect(GtkCList *clist, gint row, gint column, - GdkEvent *event, gchar *structname) -{ + int minlistlength, nrows, row, oldsel; GSList *listpt; - GtkWidget *delbut, *upbut, *downbut; + gchar *structname = data; - delbut = GTK_WIDGET(g_object_get_data(G_OBJECT(clist), "delete")); - upbut = GTK_WIDGET(g_object_get_data(G_OBJECT(clist), "up")); - downbut = GTK_WIDGET(g_object_get_data(G_OBJECT(clist), "down")); + row = get_tree_selection_row_index(treesel, &model); + nrows = gtk_tree_model_iter_n_children(model, NULL); + + delbut = GTK_WIDGET(g_object_get_data(G_OBJECT(model), "delete")); + upbut = GTK_WIDGET(g_object_get_data(G_OBJECT(model), "up")); + downbut = GTK_WIDGET(g_object_get_data(G_OBJECT(model), "down")); + oldsel = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(model), "oldsel")); g_assert(delbut && upbut && downbut); - gtk_widget_set_sensitive(delbut, FALSE); - gtk_widget_set_sensitive(upbut, FALSE); - gtk_widget_set_sensitive(downbut, FALSE); + minlistlength = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(model), + "minlistlength")); + gtk_widget_set_sensitive(delbut, nrows > minlistlength); + gtk_widget_set_sensitive(upbut, row > 0); + gtk_widget_set_sensitive(downbut, row < nrows - 1); - for (listpt = configlist; listpt; listpt = g_slist_next(listpt)) { - struct ConfigWidget *conf = (struct ConfigWidget *)listpt->data; - struct GLOBALS *gvar; + /* Store any edited data from old-selected row */ + if (oldsel >= 0) { + for (listpt = configlist; listpt; listpt = g_slist_next(listpt)) { + struct ConfigWidget *conf = (struct ConfigWidget *)listpt->data; + struct GLOBALS *gvar; - gvar = &Globals[conf->globind]; + gvar = &Globals[conf->globind]; - if (gvar->NameStruct && strcmp(structname, gvar->NameStruct) == 0) { - g_free(conf->data[row]); - conf->data[row] = NULL; + if (gvar->NameStruct && strcmp(structname, gvar->NameStruct) == 0) { + g_free(conf->data[oldsel]); + conf->data[oldsel] = NULL; - if (gvar->BoolVal) { - if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(conf->widget))) { - conf->data[row] = g_strdup("1"); + if (gvar->BoolVal) { + if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(conf->widget))) { + conf->data[oldsel] = g_strdup("1"); + } + } else { + conf->data[oldsel] = gtk_editable_get_chars( + GTK_EDITABLE(conf->widget), 0, -1); + gtk_entry_set_text(GTK_ENTRY(conf->widget), ""); + } + if (strcmp(gvar->Name, "Name") == 0) { + GtkTreeIter ositer; + g_assert(gtk_tree_model_iter_nth_child(model, &ositer, NULL, oldsel)); + gtk_list_store_set(GTK_LIST_STORE(model), &ositer, 0, + conf->data[oldsel], -1); } - } else { - conf->data[row] = gtk_editable_get_chars(GTK_EDITABLE(conf->widget), - 0, -1); - gtk_entry_set_text(GTK_ENTRY(conf->widget), ""); - } - if (strcmp(gvar->Name, "Name") == 0) { - gtk_clist_set_text(clist, row, 0, conf->data[row]); } } } -} + g_object_set_data(G_OBJECT(model), "oldsel", GINT_TO_POINTER(row)); -static void sound_row_select(GtkCList *clist, gint row, gint column, - GdkEvent *event, gpointer data) -{ - GtkWidget *entry; - int globind; - gchar **text; + /* Update widgets with selected row */ + if (row >= 0) { + for (listpt = configlist; listpt; listpt = g_slist_next(listpt)) { + struct ConfigWidget *conf = (struct ConfigWidget *)listpt->data; + struct GLOBALS *gvar; - entry = GTK_WIDGET(g_object_get_data(G_OBJECT(clist), "entry")); - globind = GPOINTER_TO_INT(gtk_clist_get_row_data(clist, row)); - g_assert(globind >=0 && globind < NUMGLOB); + gvar = &Globals[conf->globind]; - text = GetGlobalString(globind, 0); - gtk_entry_set_text(GTK_ENTRY(entry), *text); + if (gvar->NameStruct && strcmp(structname, gvar->NameStruct) == 0) { + if (gvar->BoolVal) { + gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(conf->widget), + conf->data[row] != NULL); + } else { + gtk_entry_set_text(GTK_ENTRY(conf->widget), conf->data[row]); + } + } + } + } } -static void sound_row_unselect(GtkCList *clist, gint row, gint column, - GdkEvent *event, gpointer data) +static void sound_sel_changed(GtkTreeSelection *treesel, gpointer data) { + GtkTreeModel *model; + GtkTreeIter iter; GtkWidget *entry; - int globind; - gchar *text, **oldtext; - - entry = GTK_WIDGET(g_object_get_data(G_OBJECT(clist), "entry")); - globind = GPOINTER_TO_INT(gtk_clist_get_row_data(clist, row)); - g_assert(globind >=0 && globind < NUMGLOB); + int row, oldsel, globind; + + row = get_tree_selection_row_index(treesel, &model); + oldsel = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(model), "oldsel")); + entry = GTK_WIDGET(g_object_get_data(G_OBJECT(model), "entry")); + + /* Store any edited data from old-selected row */ + if (oldsel >= 0) { + gchar *text, **oldtext; + g_assert(gtk_tree_model_iter_nth_child(model, &iter, NULL, oldsel)); + gtk_tree_model_get(model, &iter, 2, &globind, -1); + g_assert(globind >=0 && globind < NUMGLOB); + + text = gtk_editable_get_chars(GTK_EDITABLE(entry), 0, -1); + oldtext = GetGlobalString(globind, 0); + g_assert(text && oldtext); + if (strcmp(text, *oldtext) != 0) { + AssignName(GetGlobalString(globind, 0), text); + Globals[globind].Modified = TRUE; + } + gtk_entry_set_text(GTK_ENTRY(entry), ""); + g_free(text); + } - text = gtk_editable_get_chars(GTK_EDITABLE(entry), 0, -1); - oldtext = GetGlobalString(globind, 0); - g_assert(text && oldtext); - if (strcmp(text, *oldtext) != 0) { - AssignName(GetGlobalString(globind, 0), text); - Globals[globind].Modified = TRUE; + g_object_set_data(G_OBJECT(model), "oldsel", GINT_TO_POINTER(row)); + /* Update new selection */ + if (row >= 0) { + gchar **text; + g_assert(gtk_tree_model_iter_nth_child(model, &iter, NULL, row)); + gtk_tree_model_get(model, &iter, 2, &globind, -1); + g_assert(globind >=0 && globind < NUMGLOB); + text = GetGlobalString(globind, 0); + gtk_entry_set_text(GTK_ENTRY(entry), *text); } - gtk_entry_set_text(GTK_ENTRY(entry), ""); - g_free(text); } static void BrowseSound(GtkWidget *entry) t@@ -622,8 +666,12 @@ static void FinishOptDialog(GtkWidget *widget, gpointer data) static GtkWidget *CreateList(gchar *structname, struct ConfigMembers *members) { - GtkWidget *hbox, *vbox, *hbbox, *clist, *scrollwin, *button, *table; - gchar *titles[3]; + GtkWidget *hbox, *vbox, *hbbox, *tv, *scrollwin, *button, *table; + GtkTreeSelection *treesel; + GtkListStore *store; + GtkCellRenderer *renderer; + GtkTreeIter iter; + int ind, minlistlength = 0; gint i, nummembers; struct GLOBALS *gvar; t@@ -650,38 +698,44 @@ static GtkWidget *CreateList(gchar *structname, struct ConfigMembers *members) vbox = gtk_vbox_new(FALSE, 5); - titles[0] = structname; - clist = gtk_scrolled_clist_new_with_titles(1, titles, &scrollwin); + tv = gtk_scrolled_tree_view_new(&scrollwin); + store = gtk_list_store_new(1, G_TYPE_STRING); + gtk_tree_view_set_model(GTK_TREE_VIEW(tv), GTK_TREE_MODEL(store)); + renderer = gtk_cell_renderer_text_new(); + gtk_tree_view_insert_column_with_attributes( + GTK_TREE_VIEW(tv), -1, structname, renderer, "text", 0, NULL); + g_object_unref(store); + gtk_tree_view_set_headers_clickable(GTK_TREE_VIEW(tv), FALSE); - g_signal_connect(G_OBJECT(clist), "select_row", - G_CALLBACK(list_row_select), structname); - g_signal_connect(G_OBJECT(clist), "unselect_row", - G_CALLBACK(list_row_unselect), structname); - gtk_clist_column_titles_passive(GTK_CLIST(clist)); - gtk_clist_set_selection_mode(GTK_CLIST(clist), GTK_SELECTION_SINGLE); - gtk_clist_set_auto_sort(GTK_CLIST(clist), FALSE); + treesel = gtk_tree_view_get_selection(GTK_TREE_VIEW(tv)); + g_signal_connect(G_OBJECT(treesel), "changed", G_CALLBACK(list_sel_changed), + structname); + gtk_tree_selection_set_mode(treesel, GTK_SELECTION_SINGLE); + gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(store), + GTK_TREE_SORTABLE_UNSORTED_SORT_COLUMN_ID, GTK_SORT_ASCENDING); - clists = g_slist_append(clists, clist); + clists = g_slist_append(clists, tv); for (i = 1; i <= *gvar->MaxIndex; i++) { - titles[0] = *GetGlobalString(ind, i); - gtk_clist_append(GTK_CLIST(clist), titles); + gtk_list_store_append(store, &iter); + gtk_list_store_set(store, &iter, 0, *GetGlobalString(ind, i), -1); } gtk_box_pack_start(GTK_BOX(vbox), scrollwin, TRUE, TRUE, 0); hbbox = gtk_hbox_new(TRUE, 5); + g_object_set_data(G_OBJECT(store), "oldsel", GINT_TO_POINTER(-1)); button = gtk_button_new_with_label(_("New")); - g_object_set_data(G_OBJECT(button), "clist", clist); + g_object_set_data(G_OBJECT(button), "treeview", tv); g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(list_new), structname); gtk_box_pack_start(GTK_BOX(hbbox), button, TRUE, TRUE, 0); button = gtk_button_new_with_label(_("Delete")); gtk_widget_set_sensitive(button, FALSE); - g_object_set_data(G_OBJECT(button), "clist", clist); - g_object_set_data(G_OBJECT(clist), "delete", button); - g_object_set_data(G_OBJECT(clist), "minlistlength", + g_object_set_data(G_OBJECT(button), "treeview", tv); + g_object_set_data(G_OBJECT(store), "delete", button); + g_object_set_data(G_OBJECT(store), "minlistlength", GINT_TO_POINTER(minlistlength)); g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(list_delete), structname); t@@ -689,16 +743,16 @@ static GtkWidget *CreateList(gchar *structname, struct ConfigMembers *members) button = gtk_button_new_with_label(_("Up")); gtk_widget_set_sensitive(button, FALSE); - g_object_set_data(G_OBJECT(button), "clist", clist); - g_object_set_data(G_OBJECT(clist), "up", button); + g_object_set_data(G_OBJECT(button), "treeview", tv); + g_object_set_data(G_OBJECT(store), "up", button); g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(list_up), structname); gtk_box_pack_start(GTK_BOX(hbbox), button, TRUE, TRUE, 0); button = gtk_button_new_with_label(_("Down")); gtk_widget_set_sensitive(button, FALSE); - g_object_set_data(G_OBJECT(button), "clist", clist); - g_object_set_data(G_OBJECT(clist), "down", button); + g_object_set_data(G_OBJECT(button), "treeview", tv); + g_object_set_data(G_OBJECT(store), "down", button); g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(list_down), structname); gtk_box_pack_start(GTK_BOX(hbbox), button, TRUE, TRUE, 0); t@@ -720,34 +774,40 @@ static GtkWidget *CreateList(gchar *structname, struct ConfigMembers *members) return hbox; } -static void FillSoundsList(GtkCList *clist) +static void FillSoundsList(GtkTreeView *tv) { - gchar *rowtext[2]; - gint i, row; + GtkListStore *store; + GtkTreeIter iter; + gint i; + + /* Don't update the widget until we're done */ + store = GTK_LIST_STORE(gtk_tree_view_get_model(tv)); + g_object_ref(store); + gtk_tree_view_set_model(tv, NULL); - gtk_clist_freeze(clist); - gtk_clist_clear(clist); + gtk_list_store_clear(store); for (i = 0; i < NUMGLOB; i++) { if (strlen(Globals[i].Name) > 7 && strncmp(Globals[i].Name, "Sounds.", 7) == 0) { - rowtext[0] = &Globals[i].Name[7]; - rowtext[1] = _(Globals[i].Help); - row = gtk_clist_append(clist, rowtext); - gtk_clist_set_row_data(clist, row, GINT_TO_POINTER(i)); + gtk_list_store_append(store, &iter); + gtk_list_store_set(store, &iter, 0, &Globals[i].Name[7], + 1, _(Globals[i].Help), 2, i, -1); } } - gtk_clist_thaw(clist); + gtk_tree_view_set_model(tv, GTK_TREE_MODEL(store)); } void OptDialog(GtkWidget *widget, gpointer data) { GtkWidget *dialog, *notebook, *table, *label, *check, *entry; - GtkWidget *hbox, *vbox, *vbox2, *hsep, *button, *hbbox, *clist; + GtkWidget *hbox, *vbox, *vbox2, *hsep, *button, *hbbox, *tv; GtkWidget *scrollwin; GtkAccelGroup *accel_group; gchar *sound_titles[2]; - int width; + GtkCellRenderer *renderer; + GtkListStore *store; + GtkTreeSelection *treesel; struct ConfigMembers locmembers[] = { { N_("Police presence"), "PolicePresence" }, t@@ -943,16 +1003,27 @@ void OptDialog(GtkWidget *widget, gpointer data) sound_titles[0] = _("Sound name"); sound_titles[1] = _("Description"); - clist = gtk_scrolled_clist_new_with_titles(2, sound_titles, &scrollwin); - gtk_clist_column_titles_passive(GTK_CLIST(clist)); - gtk_clist_set_selection_mode(GTK_CLIST(clist), GTK_SELECTION_SINGLE); - FillSoundsList(GTK_CLIST(clist)); - g_signal_connect(G_OBJECT(clist), "select_row", - G_CALLBACK(sound_row_select), NULL); - g_signal_connect(G_OBJECT(clist), "unselect_row", - G_CALLBACK(sound_row_unselect), NULL); - - clists = g_slist_append(clists, clist); + tv = gtk_scrolled_tree_view_new(&scrollwin); + store = gtk_list_store_new(3, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INT); + g_object_set_data(G_OBJECT(store), "oldsel", GINT_TO_POINTER(-1)); + gtk_tree_view_set_model(GTK_TREE_VIEW(tv), GTK_TREE_MODEL(store)); + renderer = gtk_cell_renderer_text_new(); + gtk_tree_view_insert_column_with_attributes( + GTK_TREE_VIEW(tv), -1, sound_titles[0], renderer, + "text", 0, NULL); + gtk_tree_view_insert_column_with_attributes( + GTK_TREE_VIEW(tv), -1, sound_titles[1], renderer, + "text", 1, NULL); + g_object_unref(store); + gtk_tree_view_set_headers_clickable(GTK_TREE_VIEW(tv), FALSE); + treesel = gtk_tree_view_get_selection(GTK_TREE_VIEW(tv)); + gtk_tree_selection_set_mode(treesel, GTK_SELECTION_SINGLE); + + FillSoundsList(GTK_TREE_VIEW(tv)); + g_signal_connect(G_OBJECT(treesel), "changed", + G_CALLBACK(sound_sel_changed), NULL); + + clists = g_slist_append(clists, tv); gtk_box_pack_start(GTK_BOX(vbox2), scrollwin, TRUE, TRUE, 0); t@@ -961,7 +1032,7 @@ void OptDialog(GtkWidget *widget, gpointer data) gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); entry = gtk_entry_new(); - g_object_set_data(G_OBJECT(clist), "entry", entry); + g_object_set_data(G_OBJECT(store), "entry", entry); gtk_box_pack_start(GTK_BOX(hbox), entry, TRUE, TRUE, 0); button = gtk_button_new_with_label(_("Browse...")); t@@ -1011,7 +1082,4 @@ void OptDialog(GtkWidget *widget, gpointer data) gtk_container_add(GTK_CONTAINER(dialog), vbox); gtk_widget_show_all(dialog); - - width = gtk_clist_optimal_column_width(GTK_CLIST(clist), 0); - gtk_clist_set_column_width(GTK_CLIST(clist), 0, width); }