<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

Reply via email to