<URL: http://bugs.freeciv.org/Ticket/Display.html?id=40548 >
The attached patch fixes the update_conn_list_dialog() function so that it works without assuming that player numbers are contiguous. Also, the code is greatly cleaned up and the style improved: - Global variables are removed except for the view and the store, which are renamed for clarity and to avoid conflicts. - Hard-coded column numbers are replaced by enums. - The access level of a player is the access level of the controlling connection. - The call to gtk_tree_view_expand_all() is moved to a place where it actually has an effect. - Removed some #if 0 stuff in playerlist_event(). - Added helper function add_tree_col() to add a tree view column more easily. ----------------------------------------------------------------------- 何て知力と思った時がある?私も。
diff --git a/client/gui-gtk-2.0/gui_main.c b/client/gui-gtk-2.0/gui_main.c index ca5cb1e..7866e30 100644 --- a/client/gui-gtk-2.0/gui_main.c +++ b/client/gui-gtk-2.0/gui_main.c @@ -122,9 +122,11 @@ GtkWidget *main_frame_civ_name; GtkWidget *main_label_info; GtkWidget *avbox, *ahbox, *vbox, *conn_box; -GtkTreeStore *conn_model; GtkWidget* scroll_panel; +GtkTreeStore *connection_list_store; +GtkTreeView *connection_list_view; + GtkWidget *econ_label[10]; GtkWidget *bulb_label; GtkWidget *sun_label; @@ -1606,8 +1608,6 @@ void ui_exit() **************************************************************************/ void update_conn_list_dialog(void) { - GtkTreeIter it[player_count()]; - if (client_has_player()) { char *text; @@ -1658,45 +1658,79 @@ void update_conn_list_dialog(void) gtk_stockbutton_set_label(take_button, _("Do not _observe")); } - gtk_tree_view_column_set_visible(record_col, (with_ggz || in_ggz)); - gtk_tree_view_column_set_visible(rating_col, (with_ggz || in_ggz)); + if (connection_list_view != NULL) { + GObject *view; + GtkTreeViewColumn *col; + bool visible; + + view = G_OBJECT(connection_list_view); + visible = (with_ggz || in_ggz); - if (C_S_RUNNING != client_state()) { + col = g_object_get_data(view, "record_col"); + if (col != NULL) { + gtk_tree_view_column_set_visible(col, visible); + } + col = g_object_get_data(view, "rating_col"); + if (col != NULL) { + gtk_tree_view_column_set_visible(col, visible); + } + } + + if (client_state() == C_S_PREPARING + && get_client_page() == PAGE_START + && connection_list_store != NULL) { + GtkTreeStore *store; + GtkTreeIter iter, parent; bool is_ready; - const char *nation, *leader, *team; - char name[MAX_LEN_NAME + 4], rating_text[128], record_text[128]; + const char *nation, *plr_name, *team; + char user_name[MAX_LEN_NAME + 8], rating_text[128], record_text[128]; int rating, wins, losses, ties, forfeits; + enum cmdlevel_id access_level; + int conn_id; + + /* Clear the old list. */ + store = connection_list_store; + gtk_tree_store_clear(store); - gtk_tree_store_clear(conn_model); + /* Insert players into the connection list. */ players_iterate(pplayer) { - enum cmdlevel_id access_level = ALLOW_NONE; - int conn_id = -1; + conn_id = -1; + access_level = ALLOW_NONE; conn_list_iterate(pplayer->connections, pconn) { - access_level = MAX(pconn->access_level, access_level); + if (pconn->playing == pplayer && !pconn->observer) { + conn_id = pconn->id; + access_level = pconn->access_level; + break; + } } conn_list_iterate_end; - if (pplayer->ai.control) { + if (pplayer->ai.control && !pplayer->was_created + && !pplayer->is_connected) { /* TRANS: "<Novice AI>" */ - my_snprintf(name, sizeof(name), _("<%s AI>"), + my_snprintf(user_name, sizeof(user_name), _("<%s AI>"), ai_level_name(pplayer->ai.skill_level)); - } else if (access_level <= ALLOW_INFO) { - sz_strlcpy(name, pplayer->username); } else { - my_snprintf(name, sizeof(name), "%s*", pplayer->username); + sz_strlcpy(user_name, pplayer->username); + if (access_level > ALLOW_INFO) { + sz_strlcat(user_name, "*"); + } } - is_ready = pplayer->ai.control ? TRUE: pplayer->is_ready; + + is_ready = pplayer->ai.control ? TRUE : pplayer->is_ready; + if (pplayer->nation == NO_NATION_SELECTED) { nation = _("Random"); if (pplayer->was_created) { - leader = player_name(pplayer); + plr_name = player_name(pplayer); } else { - leader = ""; + plr_name = ""; } } else { nation = nation_adjective_for_player(pplayer); - leader = player_name(pplayer); + plr_name = player_name(pplayer); } + team = pplayer->team ? team_name_translation(pplayer->team) : ""; rating_text[0] = '\0'; @@ -1723,52 +1757,52 @@ void update_conn_list_dialog(void) } } - conn_list_iterate(game.est_connections, pconn) { - if (pconn->playing == pplayer && !pconn->observer) { - assert(conn_id == -1); - conn_id = pconn->id; - } + gtk_tree_store_append(store, &iter, NULL); + gtk_tree_store_set(store, &iter, + CL_COL_PLAYER_NUMBER, player_number(pplayer), + CL_COL_USER_NAME, user_name, + CL_COL_READY_STATE, is_ready, + CL_COL_PLAYER_NAME, plr_name, + CL_COL_NATION, nation, + CL_COL_TEAM, team, + CL_COL_GGZ_RECORD, record_text, + CL_COL_GGZ_RATING, rating_text, + CL_COL_CONN_ID, conn_id, -1); + parent = iter; + + /* Insert observers of this player as child nodes. */ + conn_list_iterate(pplayer->connections, pconn) { + if (pconn->id == conn_id) { + continue; + } + gtk_tree_store_append(store, &iter, &parent); + gtk_tree_store_set(store, &iter, + CL_COL_PLAYER_NUMBER, -1, + CL_COL_USER_NAME, pconn->username, + CL_COL_TEAM, _("Observer"), + CL_COL_CONN_ID, pconn->id, -1); } conn_list_iterate_end; - - gtk_tree_store_append(conn_model, &it[player_index(pplayer)], NULL); - gtk_tree_store_set(conn_model, &it[player_index(pplayer)], - 0, player_number(pplayer), - 1, name, - 2, is_ready, - 3, leader, - 4, nation, - 5, team, - 6, record_text, - 7, rating_text, - 8, conn_id, - -1); + } players_iterate_end; - conn_list_iterate(game.est_connections, pconn) { - GtkTreeIter conn_it, *parent; - if (NULL != pconn->playing && !pconn->observer) { + /* Finally, insert global observers and detached connections. */ + conn_list_iterate(game.est_connections, pconn) { + if (pconn->playing != NULL) { continue; /* Already listed above. */ } - sz_strlcpy(name, pconn->username); - is_ready = TRUE; - nation = ""; - leader = ""; team = pconn->observer ? _("Observer") : _("Detached"); - parent = (NULL != pconn->playing) - ? &it[player_index(pconn->playing)] - : NULL; - - gtk_tree_store_append(conn_model, &conn_it, parent); - gtk_tree_store_set(conn_model, &conn_it, - 0, -1, - 1, name, - 2, is_ready, - 3, leader, - 4, nation, - 5, team, - 8, pconn->id, - -1); + gtk_tree_store_append(store, &iter, NULL); + gtk_tree_store_set(store, &iter, + CL_COL_PLAYER_NUMBER, -1, + CL_COL_USER_NAME, pconn->username, + CL_COL_TEAM, team, + CL_COL_CONN_ID, pconn->id, -1); } conn_list_iterate_end; + + if (connection_list_view != NULL) { + GtkTreeView *view = connection_list_view; + gtk_tree_view_expand_all(view); + } } } diff --git a/client/gui-gtk-2.0/gui_main.h b/client/gui-gtk-2.0/gui_main.h index 67aec27..f5ed3fa 100644 --- a/client/gui-gtk-2.0/gui_main.h +++ b/client/gui-gtk-2.0/gui_main.h @@ -73,7 +73,24 @@ extern GtkWidget * top_notebook; extern GtkWidget * map_widget; extern GtkWidget * bottom_notebook; extern GtkTextBuffer * message_buffer; -extern GtkTreeStore *conn_model; + +/* NB: Must match creation arugments in + * create_start_page() in pages.c */ +enum connection_list_columns { + CL_COL_PLAYER_NUMBER = 0, + CL_COL_USER_NAME, + CL_COL_READY_STATE, + CL_COL_PLAYER_NAME, + CL_COL_NATION, + CL_COL_TEAM, + CL_COL_GGZ_RECORD, + CL_COL_GGZ_RATING, + CL_COL_CONN_ID, + + CL_NUM_COLUMNS +}; +extern GtkTreeStore *connection_list_store; +extern GtkTreeView *connection_list_view; void enable_menus(bool enable); diff --git a/client/gui-gtk-2.0/pages.c b/client/gui-gtk-2.0/pages.c index f251ac7..6ff8361 100644 --- a/client/gui-gtk-2.0/pages.c +++ b/client/gui-gtk-2.0/pages.c @@ -54,8 +54,6 @@ GtkWidget *start_message_area; -GtkTreeViewColumn *rating_col, *record_col; - static GtkWidget *start_options_table; GtkWidget *take_button, *ready_button, *nation_button; @@ -1355,6 +1353,7 @@ static gboolean playerlist_event(GtkWidget *widget, GdkEventButton *event, GtkTreeIter iter; GtkTreePath *path = NULL; GtkTreeViewColumn *column = NULL; + GtkWidget *menu; int player_no, conn_id; struct player *pplayer; struct connection *pconn; @@ -1368,19 +1367,52 @@ static gboolean playerlist_event(GtkWidget *widget, GdkEventButton *event, } gtk_tree_model_get_iter(model, &iter, path); - gtk_tree_path_free(path); - gtk_tree_model_get(model, &iter, 0, &player_no, -1); - pplayer = player_by_number(player_no); - gtk_tree_model_get(model, &iter, 8, &conn_id, -1); + + gtk_tree_model_get(model, &iter, CL_COL_PLAYER_NUMBER, &player_no, -1); + pplayer = valid_player_by_number(player_no); + + gtk_tree_model_get(model, &iter, CL_COL_CONN_ID, &conn_id, -1); pconn = find_conn_by_id(conn_id); - gtk_menu_popup(GTK_MENU(create_conn_menu(pplayer, pconn)), - NULL, NULL, NULL, NULL, - event->button, 0); + menu = create_conn_menu(pplayer, pconn); + gtk_menu_popup(GTK_MENU(menu), NULL, NULL, + NULL, NULL, event->button, 0); + + gtk_tree_path_free(path); return TRUE; -#if 0 - return show_conn_popup(widget, event, data); -#endif +} + +/************************************************************************** + Helper function for adding columns to a tree view. If 'key' is not NULL + then the added column is added to the object data of the treeview using + g_object_set_data under 'key'. +**************************************************************************/ +static void add_tree_col(GtkWidget *treeview, GType gtype, + const char *title, int colnum, const char *key) +{ + GtkTreeViewColumn *col; + GtkCellRenderer *rend; + const char *attr; + + if (gtype == G_TYPE_BOOLEAN) { + rend = gtk_cell_renderer_toggle_new(); + attr = "active"; + } else if (gtype == GDK_TYPE_PIXBUF) { + rend = gtk_cell_renderer_pixbuf_new(); + attr = "pixbuf"; + } else { + rend = gtk_cell_renderer_text_new(); + attr = "text"; + } + + col = gtk_tree_view_column_new_with_attributes(title, rend, attr, + colnum, NULL); + gtk_tree_view_column_set_sizing(col, GTK_TREE_VIEW_COLUMN_AUTOSIZE); + gtk_tree_view_append_column(GTK_TREE_VIEW(treeview), col); + + if (key != NULL) { + g_object_set_data(G_OBJECT(treeview), key, col); + } } /************************************************************************** @@ -1389,11 +1421,9 @@ static gboolean playerlist_event(GtkWidget *widget, GdkEventButton *event, GtkWidget *create_start_page(void) { GtkWidget *box, *sbox, *bbox, *table, *align, *vbox; - GtkWidget *view, *sw, *text, *entry, *button, *spin, *option; GtkWidget *label, *menu, *item; - GtkCellRenderer *rend; - GtkTreeViewColumn *col; + GtkTreeStore *store; enum ai_level level; box = gtk_vbox_new(FALSE, 8); @@ -1486,57 +1516,33 @@ GtkWidget *create_start_page(void) gtk_container_add(GTK_CONTAINER(align), button); gtk_box_pack_start(GTK_BOX(vbox), align, FALSE, FALSE, 8); + /* NB: Must match order and type of enum + * connection_list_columns in gui_main.h. */ + store = gtk_tree_store_new(CL_NUM_COLUMNS, G_TYPE_INT, + G_TYPE_STRING, G_TYPE_BOOLEAN, + G_TYPE_STRING, G_TYPE_STRING, + G_TYPE_STRING, G_TYPE_STRING, + G_TYPE_STRING, G_TYPE_INT); + connection_list_store = store; - conn_model = gtk_tree_store_new(9, G_TYPE_INT, - G_TYPE_STRING, G_TYPE_BOOLEAN, - G_TYPE_STRING, G_TYPE_STRING, - G_TYPE_STRING, G_TYPE_STRING, - G_TYPE_STRING, - G_TYPE_INT); - - view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(conn_model)); - g_object_unref(conn_model); + view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store)); gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(view), TRUE); - gtk_tree_view_expand_all(GTK_TREE_VIEW(view)); - - rend = gtk_cell_renderer_text_new(); - gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(view), - -1, _("Name"), rend, - "text", 1, NULL); - - rend = gtk_cell_renderer_text_new(); - record_col = gtk_tree_view_column_new_with_attributes(_("Record"), rend, - "text", 6, NULL); - gtk_tree_view_insert_column(GTK_TREE_VIEW(view), record_col, -1); - - rend = gtk_cell_renderer_text_new(); - rating_col = gtk_tree_view_column_new_with_attributes(_("Rating"), rend, - "text", 7, NULL); - gtk_tree_view_insert_column(GTK_TREE_VIEW(view), rating_col, -1); - - /* FIXME: should change to always be minimum-width. */ - rend = gtk_cell_renderer_toggle_new(); - col = gtk_tree_view_column_new_with_attributes(_("Ready"), - rend, - "active", 2, NULL); - gtk_tree_view_insert_column(GTK_TREE_VIEW(view), col, -1); - - rend = gtk_cell_renderer_text_new(); - gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(view), - -1, _("Leader"), rend, - "text", 3, NULL); - - rend = gtk_cell_renderer_text_new(); - col = gtk_tree_view_column_new_with_attributes(_("Nation"), - rend, - "text", 4, NULL); - gtk_tree_view_insert_column(GTK_TREE_VIEW(view), col, -1); - - rend = gtk_cell_renderer_text_new(); - col = gtk_tree_view_column_new_with_attributes(_("Team"), - rend, - "text", 5, NULL); - gtk_tree_view_insert_column(GTK_TREE_VIEW(view), col, -1); + connection_list_view = GTK_TREE_VIEW(view); + + add_tree_col(view, G_TYPE_STRING, _("Name"), + CL_COL_USER_NAME, NULL); + add_tree_col(view, G_TYPE_STRING, _("Record"), + CL_COL_GGZ_RECORD, "record_col"); + add_tree_col(view, G_TYPE_STRING, _("Rating"), + CL_COL_GGZ_RATING, "rating_col"); + add_tree_col(view, G_TYPE_BOOLEAN, _("Ready"), + CL_COL_READY_STATE, NULL); + add_tree_col(view, G_TYPE_STRING, _("Leader"), + CL_COL_PLAYER_NAME, NULL); + add_tree_col(view, G_TYPE_STRING, _("Nation"), + CL_COL_NATION, NULL); + add_tree_col(view, G_TYPE_STRING, _("Team"), + CL_COL_TEAM, NULL); g_signal_connect(view, "button-press-event", G_CALLBACK(playerlist_event), NULL); diff --git a/client/gui-gtk-2.0/pages.h b/client/gui-gtk-2.0/pages.h index 6b5242f..1c0c014 100644 --- a/client/gui-gtk-2.0/pages.h +++ b/client/gui-gtk-2.0/pages.h @@ -21,7 +21,6 @@ extern GtkWidget *start_message_area; extern GtkWidget *take_button, *ready_button, *nation_button; -extern GtkTreeViewColumn *rating_col, *record_col; GtkWidget *create_main_page(void); GtkWidget *create_start_page(void);
_______________________________________________ Freeciv-dev mailing list Freeciv-dev@gna.org https://mail.gna.org/listinfo/freeciv-dev