Rulesave saves trade.type and trade.bonus correctly.
[freeciv.git] / client / gui-gtk-2.0 / plrdlg.c
blob2e29aeda8b105369125d7ff2c542a8397dbadcc9
1 /**********************************************************************
2 Freeciv - Copyright (C) 1996 - A Kjeldberg, L Gregersen, P Unold
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; either version 2, or (at your option)
6 any later version.
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12 ***********************************************************************/
14 #ifdef HAVE_CONFIG_H
15 #include <fc_config.h>
16 #endif
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <string.h>
22 #include <gtk/gtk.h>
23 #include <gdk/gdkkeysyms.h>
25 /* utility */
26 #include "astring.h"
27 #include "fcintl.h"
28 #include "support.h"
30 /* common */
31 #include "diptreaty.h"
32 #include "packets.h"
33 #include "nation.h"
34 #include "player.h"
36 /* client */
37 #include "chatline.h"
38 #include "client_main.h"
39 #include "climisc.h"
40 #include "connectdlg_common.h"
41 #include "dialogs.h"
42 #include "gui_main.h"
43 #include "gui_stuff.h"
44 #include "inteldlg.h"
45 #include "spaceshipdlg.h"
46 #include "tilespec.h"
47 #include "colors.h"
48 #include "graphics.h"
49 #include "options.h"
50 #include "text.h"
52 #include "plrdlg.h"
54 struct gui_dialog *players_dialog_shell;
55 static GtkWidget *players_list;
56 static GtkTreeSelection *players_selection;
57 static GtkWidget *players_int_command;
58 static GtkWidget *players_meet_command;
59 static GtkWidget *players_war_command;
60 static GtkWidget *players_vision_command;
61 static GtkWidget *players_sship_command;
63 static GtkListStore *players_dialog_store;
64 #define PLR_DLG_COL_STYLE (0 + num_player_dlg_columns)
65 #define PLR_DLG_COL_WEIGHT (1 + num_player_dlg_columns)
66 #define PLR_DLG_COL_ID (2 + num_player_dlg_columns)
68 static void create_players_dialog(void);
69 static void players_meet_callback(GtkMenuItem *item, gpointer data);
70 static void players_war_callback(GtkMenuItem *item, gpointer data);
71 static void players_vision_callback(GtkMenuItem *item, gpointer data);
72 static void players_intel_callback(GtkMenuItem *item, gpointer data);
73 static void players_sship_callback(GtkMenuItem *item, gpointer data);
74 static void players_ai_toggle_callback(GtkMenuItem *item, gpointer data);
75 static void players_ai_skill_callback(GtkMenuItem *item, gpointer data);
78 static void update_views(void);
80 /**************************************************************************
81 popup the dialog 10% inside the main-window, and optionally raise it.
82 **************************************************************************/
83 void popup_players_dialog(bool raise)
85 if (!players_dialog_shell){
86 create_players_dialog();
88 gui_dialog_present(players_dialog_shell);
89 if (raise) {
90 gui_dialog_raise(players_dialog_shell);
94 /****************************************************************
95 Closes the players dialog.
96 *****************************************************************/
97 void popdown_players_dialog(void)
99 if (players_dialog_shell) {
100 gui_dialog_destroy(players_dialog_shell);
104 /***************************************************************************
105 Create a small colored square representing the player color, for use
106 in player lists.
107 May return NULL if the player has no color yet.
108 ***************************************************************************/
109 GdkPixbuf *create_player_icon(const struct player *plr)
111 int width, height;
112 GdkPixbuf *tmp;
113 GdkPixmap *pixmap;
115 if (!player_has_color(tileset, plr)) {
116 return NULL;
119 gtk_icon_size_lookup(GTK_ICON_SIZE_MENU, &width, &height);
121 pixmap = gdk_pixmap_new(root_window, width, height, -1);
123 gdk_gc_set_foreground(civ_gc,
124 &get_color(tileset,
125 COLOR_PLAYER_COLOR_BACKGROUND)->color);
126 gdk_draw_rectangle(pixmap, civ_gc, TRUE, 0, 0, width, height);
128 gdk_gc_set_foreground(civ_gc, &get_player_color(tileset, plr)->color);
129 gdk_draw_rectangle(pixmap, civ_gc, TRUE, 1, 1, width - 2, height - 2);
131 tmp = gdk_pixbuf_get_from_drawable(NULL, pixmap, NULL,
132 0, 0, 0, 0, -1, -1);
134 g_object_unref(pixmap);
135 return tmp;
138 /**************************************************************************
139 Refresh player menu
140 **************************************************************************/
141 static void update_players_menu(void)
143 GtkTreeModel *model;
144 GtkTreeIter it;
146 if (gtk_tree_selection_get_selected(players_selection, &model, &it)) {
147 struct player *plr;
148 gint plrno;
150 gtk_tree_model_get(model, &it, PLR_DLG_COL_ID, &plrno, -1);
151 plr = player_by_number(plrno);
153 if (plr->spaceship.state != SSHIP_NONE) {
154 gtk_widget_set_sensitive(players_sship_command, TRUE);
155 } else {
156 gtk_widget_set_sensitive(players_sship_command, FALSE);
159 if (NULL != client.conn.playing) {
160 /* We keep button sensitive in case of DIPL_SENATE_BLOCKING, so that player
161 * can request server side to check requirements of those effects with omniscience */
162 gtk_widget_set_sensitive(players_war_command,
163 can_client_issue_orders()
164 && pplayer_can_cancel_treaty(client_player(),
165 player_by_number(plrno))
166 != DIPL_ERROR);
167 } else {
168 gtk_widget_set_sensitive(players_war_command, FALSE);
171 gtk_widget_set_sensitive(players_vision_command,
172 can_client_issue_orders()
173 && gives_shared_vision(client.conn.playing, plr)
174 && !players_on_same_team(client.conn.playing, plr));
176 gtk_widget_set_sensitive(players_meet_command, can_meet_with_player(plr));
177 gtk_widget_set_sensitive(players_int_command, can_intel_with_player(plr));
178 return;
181 gtk_widget_set_sensitive(players_meet_command, FALSE);
182 gtk_widget_set_sensitive(players_int_command, FALSE);
185 /**************************************************************************
186 Something selected from player menu
187 **************************************************************************/
188 static void selection_callback(GtkTreeSelection *selection, gpointer data)
190 update_players_menu();
193 /**************************************************************************
194 Button pressed on player list
195 **************************************************************************/
196 static gboolean button_press_callback(GtkTreeView *view, GdkEventButton *ev)
198 if (ev->type == GDK_2BUTTON_PRESS) {
199 GtkTreePath *path;
201 gtk_tree_view_get_cursor(view, &path, NULL);
202 if (path) {
203 GtkTreeModel *model = gtk_tree_view_get_model(view);
204 GtkTreeIter it;
205 gint id;
206 struct player *plr;
208 gtk_tree_model_get_iter(model, &it, path);
209 gtk_tree_path_free(path);
211 gtk_tree_model_get(model, &it, PLR_DLG_COL_ID, &id, -1);
212 plr = player_by_number(id);
214 if (ev->button == 1) {
215 if (can_intel_with_player(plr)) {
216 popup_intel_dialog(plr);
218 } else if (can_meet_with_player(plr)) {
219 dsend_packet_diplomacy_init_meeting_req(&client.conn, id);
223 return FALSE;
226 /**************************************************************************
227 Sorting function for plr dlg.
228 **************************************************************************/
229 static gint plrdlg_sort_func(GtkTreeModel *model,
230 GtkTreeIter *a, GtkTreeIter *b, gpointer data)
232 GValue value = { 0, };
233 struct player *player1;
234 struct player *player2;
235 gint n;
237 n = GPOINTER_TO_INT(data);
239 gtk_tree_model_get_value(model, a, PLR_DLG_COL_ID, &value);
240 player1 = player_by_number(g_value_get_int(&value));
241 g_value_unset(&value);
243 gtk_tree_model_get_value(model, b, PLR_DLG_COL_ID, &value);
244 player2 = player_by_number(g_value_get_int(&value));
245 g_value_unset(&value);
247 return player_dlg_columns[n].sort_func(player1, player2);
250 /****************************************************************************
251 Create a player dialog store.
252 ****************************************************************************/
253 static GtkListStore *players_dialog_store_new(void)
255 GtkListStore *store;
256 GType model_types[num_player_dlg_columns + 3];
257 int i;
259 for (i = 0; i < num_player_dlg_columns; i++) {
260 switch (player_dlg_columns[i].type) {
261 case COL_FLAG:
262 model_types[i] = GDK_TYPE_PIXBUF;
263 break;
264 case COL_COLOR:
265 model_types[i] = GDK_TYPE_PIXBUF;
266 break;
267 case COL_BOOLEAN:
268 model_types[i] = G_TYPE_BOOLEAN;
269 break;
270 case COL_TEXT:
271 case COL_RIGHT_TEXT:
272 model_types[i] = G_TYPE_STRING;
273 break;
276 /* special (invisible rows) - Text style, weight and player id */
277 model_types[i++] = G_TYPE_INT; /* PLR_DLG_COL_STYLE. */
278 model_types[i++] = G_TYPE_INT; /* PLR_DLG_COL_WEIGHT. */
279 model_types[i++] = G_TYPE_INT; /* PLR_DLG_COL_ID. */
281 store = gtk_list_store_newv(i, model_types);
283 /* Set sort order */
284 for (i = 0; i < num_player_dlg_columns; i++) {
285 if (player_dlg_columns[i].sort_func != NULL) {
286 gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(store), i,
287 plrdlg_sort_func, GINT_TO_POINTER(i),
288 NULL);
292 return store;
295 /**************************************************************************
296 Toggled column visibility
297 **************************************************************************/
298 static void toggle_view(GtkCheckMenuItem* item, gpointer data)
300 struct player_dlg_column* pcol = data;
302 pcol->show = gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(item));
303 update_views();
306 /*************************************************************************
307 Called whenever player toggles the 'Show/Dead Players' menu item
308 *************************************************************************/
309 static void toggle_dead_players(GtkCheckMenuItem* item, gpointer data)
311 gui_options.player_dlg_show_dead_players =
312 gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(item));
313 real_players_dialog_update();
316 /**************************************************************************
317 Create and return the "diplomacy" menu for the player report. This menu
318 contains diplomacy actions the current player can use on other nations.
319 **************************************************************************/
320 static GtkWidget *create_diplomacy_menu(void)
322 GtkWidget *menu, *item;
324 menu = gtk_menu_new();
326 item = gtk_menu_item_new_with_mnemonic(_("_Meet"));
327 g_signal_connect(item, "activate",
328 G_CALLBACK(players_meet_callback), NULL);
329 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
330 players_meet_command = item;
332 item = gtk_menu_item_new_with_mnemonic(_("Cancel _Treaty"));
333 g_signal_connect(item, "activate",
334 G_CALLBACK(players_war_callback), NULL);
335 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
336 players_war_command = item;
338 item = gtk_menu_item_new_with_mnemonic(_("_Withdraw Vision"));
339 g_signal_connect(item, "activate",
340 G_CALLBACK(players_vision_callback), NULL);
341 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
342 players_vision_command = item;
344 return menu;
347 /**************************************************************************
348 Create and return the "intelligence" menu. The items in this menu are
349 used by the player to see more detailed information about other nations.
350 **************************************************************************/
351 static GtkWidget *create_intelligence_menu(void)
353 GtkWidget *menu, *item;
355 menu = gtk_menu_new();
357 item = gtk_menu_item_new_with_mnemonic(_("_Report"));
358 g_signal_connect(item, "activate",
359 G_CALLBACK(players_intel_callback), NULL);
360 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
361 players_int_command = item;
363 item = gtk_menu_item_new_with_mnemonic(_("_Spaceship"));
364 g_signal_connect(item, "activate",
365 G_CALLBACK(players_sship_callback), NULL);
366 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
367 players_sship_command = item;
369 return menu;
372 /**************************************************************************
373 Create 'show' menu for player dialog
374 **************************************************************************/
375 static GtkWidget* create_show_menu(void)
377 int i;
378 GtkWidget *menu = gtk_menu_new();
379 GtkWidget *item;
381 /* index starting at one (1) here to force playername to always be shown */
382 for (i = 1; i < num_player_dlg_columns; i++) {
383 struct player_dlg_column *pcol;
385 pcol = &player_dlg_columns[i];
386 item = gtk_check_menu_item_new_with_label(pcol->title);
387 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item), pcol->show);
388 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
389 g_signal_connect(item, "toggled", G_CALLBACK(toggle_view), pcol);
392 item = gtk_separator_menu_item_new();
393 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
395 item = gtk_check_menu_item_new_with_label(Q_("?show:Dead Players"));
396 gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item),
397 gui_options.player_dlg_show_dead_players);
398 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
399 g_signal_connect(item, "toggled", G_CALLBACK(toggle_dead_players), NULL);
401 return menu;
404 /**************************************************************************
405 Create all of player dialog
406 **************************************************************************/
407 void create_players_dialog(void)
409 int i;
410 GtkWidget *sep, *sw;
411 GtkWidget *menubar, *menu, *item, *vbox;
412 enum ai_level level;
414 gui_dialog_new(&players_dialog_shell, GTK_NOTEBOOK(top_notebook), NULL,
415 TRUE);
416 /* TRANS: Nations report title */
417 gui_dialog_set_title(players_dialog_shell, _("Nations"));
419 gui_dialog_add_button(players_dialog_shell,
420 GTK_STOCK_CLOSE, GTK_RESPONSE_CLOSE);
422 gui_dialog_set_default_size(players_dialog_shell, -1, 270);
424 players_dialog_store = players_dialog_store_new();
426 players_list = gtk_tree_view_new_with_model(GTK_TREE_MODEL
427 (players_dialog_store));
428 g_object_unref(players_dialog_store);
429 gtk_widget_set_name(players_list, "small_font");
431 players_selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(players_list));
432 g_signal_connect(players_selection, "changed",
433 G_CALLBACK(selection_callback), NULL);
434 g_signal_connect(players_list, "button_press_event",
435 G_CALLBACK(button_press_callback), NULL);
437 for (i = 0; i < num_player_dlg_columns; i++) {
438 struct player_dlg_column *pcol;
439 GtkCellRenderer *renderer;
440 GtkTreeViewColumn *col;
442 pcol = &player_dlg_columns[i];
443 col = NULL;
445 switch (pcol->type) {
446 case COL_FLAG:
447 renderer = gtk_cell_renderer_pixbuf_new();
449 col = gtk_tree_view_column_new_with_attributes(pcol->title,
450 renderer, "pixbuf", i, NULL);
451 break;
452 case COL_BOOLEAN:
453 renderer = gtk_cell_renderer_toggle_new();
455 col = gtk_tree_view_column_new_with_attributes(pcol->title, renderer,
456 "active", i, NULL);
457 break;
458 case COL_COLOR:
459 renderer = gtk_cell_renderer_pixbuf_new();
461 col = gtk_tree_view_column_new_with_attributes(pcol->title, renderer,
462 "pixbuf", i, NULL);
463 break;
464 case COL_TEXT:
465 renderer = gtk_cell_renderer_text_new();
466 g_object_set(renderer, "style-set", TRUE, "weight-set", TRUE, NULL);
468 col = gtk_tree_view_column_new_with_attributes(pcol->title, renderer,
469 "text", i,
470 "style", PLR_DLG_COL_STYLE,
471 "weight", PLR_DLG_COL_WEIGHT,
472 NULL);
473 gtk_tree_view_column_set_sort_column_id(col, i);
474 break;
475 case COL_RIGHT_TEXT:
476 renderer = gtk_cell_renderer_text_new();
477 g_object_set(renderer, "style-set", TRUE, "weight-set", TRUE, NULL);
479 col = gtk_tree_view_column_new_with_attributes(pcol->title, renderer,
480 "text", i,
481 "style", PLR_DLG_COL_STYLE,
482 "weight", PLR_DLG_COL_WEIGHT,
483 NULL);
484 gtk_tree_view_column_set_sort_column_id(col, i);
485 g_object_set(renderer, "xalign", 1.0, NULL);
486 gtk_tree_view_column_set_alignment(col, 1.0);
487 break;
490 if (col) {
491 gtk_tree_view_append_column(GTK_TREE_VIEW(players_list), col);
495 gtk_tree_view_set_search_column(GTK_TREE_VIEW(players_list),
496 player_dlg_default_sort_column());
498 sw = gtk_scrolled_window_new(NULL, NULL);
499 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(sw),
500 GTK_SHADOW_ETCHED_IN);
501 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw),
502 GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
503 gtk_container_add(GTK_CONTAINER(sw), players_list);
505 gtk_box_pack_start(GTK_BOX(players_dialog_shell->vbox), sw,
506 TRUE, TRUE, 0);
508 vbox = gtk_vbox_new(FALSE, 0);
510 sep = gtk_hseparator_new();
511 gtk_box_pack_start(GTK_BOX(vbox), sep, FALSE, FALSE, 0);
513 menubar = gtk_aux_menu_bar_new();
514 gtk_box_pack_start(GTK_BOX(vbox), menubar, TRUE, TRUE, 0);
517 gui_dialog_add_widget(players_dialog_shell, vbox);
518 gtk_box_set_child_packing(GTK_BOX(players_dialog_shell->action_area),
519 vbox, FALSE, FALSE, 0, GTK_PACK_START);
521 item = gtk_menu_item_new_with_mnemonic(_("Di_plomacy"));
522 menu = create_diplomacy_menu();
523 gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), menu);
524 gtk_menu_shell_append(GTK_MENU_SHELL(menubar), item);
526 item = gtk_menu_item_new_with_mnemonic(_("_Intelligence"));
527 menu = create_intelligence_menu();
528 gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), menu);
529 gtk_menu_shell_append(GTK_MENU_SHELL(menubar), item);
531 item = gtk_menu_item_new_with_mnemonic(_("_Display"));
532 menu = create_show_menu();
533 gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), menu);
534 gtk_menu_shell_append(GTK_MENU_SHELL(menubar), item);
536 item = gtk_menu_item_new_with_mnemonic(_("_AI"));
537 gtk_menu_shell_append(GTK_MENU_SHELL(menubar), item);
539 menu = gtk_menu_new();
540 gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), menu);
542 item = gtk_menu_item_new_with_mnemonic(_("_Toggle AI Mode"));
543 g_signal_connect(item, "activate",
544 G_CALLBACK(players_ai_toggle_callback), NULL);
545 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
547 sep = gtk_separator_menu_item_new();
548 gtk_menu_shell_append(GTK_MENU_SHELL(menu), sep);
550 for (level = 0; level < AI_LEVEL_COUNT; level++) {
551 if (is_settable_ai_level(level)) {
552 const char *level_name = ai_level_translated_name(level);
554 item = gtk_menu_item_new_with_label(level_name);
555 g_signal_connect(item, "activate",
556 G_CALLBACK(players_ai_skill_callback),
557 GUINT_TO_POINTER(level));
558 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
561 gtk_widget_show_all(menu);
563 gui_dialog_show_all(players_dialog_shell);
565 real_players_dialog_update();
567 gui_dialog_set_default_response(players_dialog_shell,
568 GTK_RESPONSE_CLOSE);
570 gtk_tree_view_focus(GTK_TREE_VIEW(players_list));
574 /**************************************************************************
576 **************************************************************************/
577 #define MIN_DIMENSION 5
579 /**************************************************************************
580 Builds the flag pixmap. May return NULL if there is not enough memory.
581 You must call g_object_unref on the returned pixbuf when it is no
582 longer needed.
583 **************************************************************************/
584 GdkPixbuf *get_flag(const struct nation_type *nation)
586 int x0, y0, x1, y1, w, h;
587 GdkPixbuf *im;
588 struct sprite *flag;
590 flag = get_nation_flag_sprite(tileset, nation);
592 /* calculate the bounding box ... */
593 sprite_get_bounding_box(flag, &x0, &y0, &x1, &y1);
595 fc_assert_ret_val(x0 != -1, NULL);
596 fc_assert_ret_val(y0 != -1, NULL);
597 fc_assert_ret_val(x1 != -1, NULL);
598 fc_assert_ret_val(y1 != -1, NULL);
600 w = (x1 - x0) + 1;
601 h = (y1 - y0) + 1;
603 /* if the flag is smaller then 5 x 5, something is wrong */
604 fc_assert_ret_val(w >= MIN_DIMENSION && h >= MIN_DIMENSION, NULL);
606 /* croping */
607 im = gdk_pixbuf_new(GDK_COLORSPACE_RGB, TRUE, 8, w, h);
608 if (im != NULL) {
609 gdk_pixbuf_copy_area(sprite_get_pixbuf(flag), x0, y0, w, h,
610 im, 0, 0);
613 /* and finaly store the scaled flag pixbuf in the static flags array */
614 return im;
618 /**************************************************************************
619 Fills the player list with the information for 'pplayer' at the row
620 given by 'it'.
621 **************************************************************************/
622 static void fill_row(GtkListStore *store, GtkTreeIter *it,
623 const struct player *pplayer)
625 struct player_dlg_column* pcol;
626 GdkPixbuf *pixbuf;
627 int style = PANGO_STYLE_NORMAL, weight = PANGO_WEIGHT_NORMAL;
628 int k;
630 for (k = 0; k < num_player_dlg_columns; k++) {
631 pcol = &player_dlg_columns[k];
632 switch (pcol->type) {
633 case COL_TEXT:
634 case COL_RIGHT_TEXT:
635 gtk_list_store_set(store, it, k, pcol->func(pplayer), -1);
636 break;
637 case COL_FLAG:
638 pixbuf = get_flag(nation_of_player(pplayer));
639 if (pixbuf != NULL) {
640 gtk_list_store_set(store, it, k, pixbuf, -1);
641 g_object_unref(pixbuf);
643 break;
644 case COL_COLOR:
645 pixbuf = create_player_icon(pplayer);
646 if (pixbuf != NULL) {
647 gtk_list_store_set(store, it, k, pixbuf, -1);
648 g_object_unref(pixbuf);
650 break;
651 case COL_BOOLEAN:
652 gtk_list_store_set(store, it, k, pcol->bool_func(pplayer), -1);
653 break;
657 /* now add some eye candy ... */
658 if (client_has_player()) {
659 switch (player_diplstate_get(client_player(), pplayer)->type) {
660 case DS_WAR:
661 weight = PANGO_WEIGHT_NORMAL;
662 style = PANGO_STYLE_ITALIC;
663 break;
664 case DS_ALLIANCE:
665 case DS_TEAM:
666 weight = PANGO_WEIGHT_BOLD;
667 style = PANGO_STYLE_NORMAL;
668 break;
669 case DS_ARMISTICE:
670 case DS_CEASEFIRE:
671 case DS_PEACE:
672 case DS_NO_CONTACT:
673 weight = PANGO_WEIGHT_NORMAL;
674 style = PANGO_STYLE_NORMAL;
675 break;
676 case DS_LAST:
677 break;
681 gtk_list_store_set(store, it,
682 PLR_DLG_COL_STYLE, style,
683 PLR_DLG_COL_WEIGHT, weight,
684 PLR_DLG_COL_ID, player_number(pplayer),
685 -1);
688 /**************************************************************************
689 Return TRUE if the player should be shown in the player list.
690 **************************************************************************/
691 static bool player_should_be_shown(const struct player *pplayer)
693 return NULL != pplayer && (gui_options.player_dlg_show_dead_players
694 || pplayer->is_alive)
695 && (!is_barbarian(pplayer));
698 /**************************************************************************
699 Clear and refill the entire player list.
700 **************************************************************************/
701 void real_players_dialog_update(void)
703 GtkTreeModel *model;
704 GtkTreeIter iter;
705 int selected;
707 if (NULL == players_dialog_shell) {
708 return;
711 /* Save the selection. */
712 if (gtk_tree_selection_get_selected(players_selection, &model, &iter)) {
713 gtk_tree_model_get(model, &iter, PLR_DLG_COL_ID, &selected, -1);
714 } else {
715 selected = -1;
718 gtk_list_store_clear(players_dialog_store);
719 players_iterate(pplayer) {
720 if (!player_should_be_shown(pplayer)) {
721 continue;
723 gtk_list_store_append(players_dialog_store, &iter);
724 fill_row(players_dialog_store, &iter, pplayer);
725 if (player_number(pplayer) == selected) {
726 /* Restore the selection. */
727 gtk_tree_selection_select_iter(players_selection, &iter);
729 } players_iterate_end;
731 update_views();
734 /**************************************************************************
735 Callback for diplomatic meetings button. This button is enabled iff
736 we can meet with the other player.
737 **************************************************************************/
738 void players_meet_callback(GtkMenuItem *item, gpointer data)
740 GtkTreeModel *model;
741 GtkTreeIter it;
743 if (gtk_tree_selection_get_selected(players_selection, &model, &it)) {
744 gint plrno;
746 gtk_tree_model_get(model, &it, PLR_DLG_COL_ID, &plrno, -1);
748 dsend_packet_diplomacy_init_meeting_req(&client.conn, plrno);
752 /**************************************************************************
753 Confirm pact/treaty cancellation.
754 Frees strings passed in.
755 **************************************************************************/
756 static void confirm_cancel_pact(enum clause_type clause, int plrno,
757 char *title, char *question)
759 GtkWidget *shell;
761 shell = gtk_message_dialog_new(NULL, 0,
762 GTK_MESSAGE_QUESTION, GTK_BUTTONS_YES_NO,
763 "%s", question);
764 gtk_window_set_title(GTK_WINDOW(shell), title);
765 setup_dialog(shell, toplevel);
766 gtk_dialog_set_default_response(GTK_DIALOG(shell), GTK_RESPONSE_NO);
768 if (gtk_dialog_run(GTK_DIALOG(shell)) == GTK_RESPONSE_YES) {
769 dsend_packet_diplomacy_cancel_pact(&client.conn, plrno, clause);
771 gtk_widget_destroy(shell);
772 FC_FREE(title);
773 FC_FREE(question);
776 /**************************************************************************
777 Pact cancellation requested
778 **************************************************************************/
779 void players_war_callback(GtkMenuItem *item, gpointer data)
781 GtkTreeModel *model;
782 GtkTreeIter it;
784 if (gtk_tree_selection_get_selected(players_selection, &model, &it)) {
785 struct astring title = ASTRING_INIT, question = ASTRING_INIT;
786 gint plrno;
787 struct player *aplayer;
788 enum diplstate_type oldstate, newstate;
790 gtk_tree_model_get(model, &it, PLR_DLG_COL_ID, &plrno, -1);
791 aplayer = player_by_number(plrno);
792 fc_assert_ret(aplayer != NULL);
794 oldstate = player_diplstate_get(client_player(), aplayer)->type;
795 newstate = cancel_pact_result(oldstate);
797 /* TRANS: %s is a diplomatic state: "Cancel Cease-fire" */
798 astr_set(&title, _("Cancel %s"), diplstate_type_translated_name(oldstate));
800 if (newstate == DS_WAR) {
801 astr_set(&question, _("Really declare war on the %s?"),
802 nation_plural_for_player(aplayer));
803 } else {
804 /* TRANS: "Cancel Belgian Alliance? ... will be Armistice." */
805 astr_set(&question, _("Cancel %s %s? New diplomatic state will be %s."),
806 nation_adjective_for_player(aplayer),
807 diplstate_type_translated_name(oldstate),
808 diplstate_type_translated_name(newstate));
811 /* can be any pact clause */
812 confirm_cancel_pact(CLAUSE_CEASEFIRE, plrno,
813 astr_to_str(&title), astr_to_str(&question));
817 /**************************************************************************
818 Withdrawing shared vision
819 **************************************************************************/
820 void players_vision_callback(GtkMenuItem *item, gpointer data)
822 GtkTreeModel *model;
823 GtkTreeIter it;
825 if (gtk_tree_selection_get_selected(players_selection, &model, &it)) {
826 struct astring question = ASTRING_INIT;
827 gint plrno;
828 struct player *aplayer;
830 gtk_tree_model_get(model, &it, PLR_DLG_COL_ID, &plrno, -1);
831 aplayer = player_by_number(plrno);
832 fc_assert_ret(aplayer != NULL);
834 /* TRANS: "...from the Belgians?" */
835 astr_set(&question, _("Withdraw shared vision from the %s?"),
836 nation_plural_for_player(aplayer));
838 confirm_cancel_pact(CLAUSE_VISION, plrno,
839 fc_strdup(_("Withdraw Shared Vision")),
840 astr_to_str(&question));
844 /**************************************************************************
845 Intelligence report query
846 **************************************************************************/
847 void players_intel_callback(GtkMenuItem *item, gpointer data)
849 GtkTreeModel *model;
850 GtkTreeIter it;
852 if (gtk_tree_selection_get_selected(players_selection, &model, &it)) {
853 gint plrno;
855 gtk_tree_model_get(model, &it, PLR_DLG_COL_ID, &plrno, -1);
857 if (can_intel_with_player(player_by_number(plrno))) {
858 popup_intel_dialog(player_by_number(plrno));
863 /**************************************************************************
864 Spaceship query callback
865 **************************************************************************/
866 void players_sship_callback(GtkMenuItem *item, gpointer data)
868 GtkTreeModel *model;
869 GtkTreeIter it;
871 if (gtk_tree_selection_get_selected(players_selection, &model, &it)) {
872 gint plrno;
874 gtk_tree_model_get(model, &it, PLR_DLG_COL_ID, &plrno, -1);
875 popup_spaceship_dialog(player_by_number(plrno));
879 /**************************************************************************
880 AI toggle callback.
881 **************************************************************************/
882 static void players_ai_toggle_callback(GtkMenuItem *item, gpointer data)
884 GtkTreeModel *model;
885 GtkTreeIter it;
887 if (gtk_tree_selection_get_selected(players_selection, &model, &it)) {
888 gint plrno;
890 gtk_tree_model_get(model, &it, PLR_DLG_COL_ID, &plrno, -1);
892 send_chat_printf("/aitoggle \"%s\"", player_name(player_by_number(plrno)));
896 /**************************************************************************
897 AI skill level setting callback.
898 **************************************************************************/
899 static void players_ai_skill_callback(GtkMenuItem *item, gpointer data)
901 GtkTreeModel *model;
902 GtkTreeIter it;
904 if (gtk_tree_selection_get_selected(players_selection, &model, &it)) {
905 gint plrno;
907 gtk_tree_model_get(model, &it, PLR_DLG_COL_ID, &plrno, -1);
909 send_chat_printf("/%s %s",
910 ai_level_cmd(GPOINTER_TO_UINT(data)),
911 player_name(player_by_number(plrno)));
915 /**************************************************************************
916 Refresh players dialog views.
917 **************************************************************************/
918 static void update_views(void)
920 int i;
922 for (i = 0; i < num_player_dlg_columns; i++) {
923 GtkTreeViewColumn *col;
925 col = gtk_tree_view_get_column(GTK_TREE_VIEW(players_list), i);
926 gtk_tree_view_column_set_visible(col, player_dlg_columns[i].show);