Qt client - remove right click menu from end turn sidebar
[freeciv.git] / client / gui-gtk-2.0 / citizensinfo.c
blobdb48d66a4dc20bf13686c196b11920912e897605
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
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <string.h>
23 #include <gtk/gtk.h>
24 #include <gdk/gdkkeysyms.h>
26 /* common */
27 #include "citizens.h"
28 #include "city.h"
29 #include "player.h"
31 /* client/gui-gtk-2.0 */
32 #include "gui_stuff.h"
33 #include "plrdlg.h"
35 #include "citizensinfo.h"
38 static struct citizens_dialog *citizens_dialog_get(const struct city *pcity);
39 static struct citizens_dialog
40 *citizens_dialog_create(const struct city *pcity);
41 static GtkTreeStore *citizens_dialog_store_new(void);
42 static int citizens_dialog_default_sort_column(void);
43 static void citizens_dialog_row(GtkTreeStore *store, GtkTreeIter *it,
44 const struct city *pcity,
45 const struct player_slot *pslot);
47 static const char *col_nation(const struct city *pcity,
48 const struct player_slot *pslot);
49 static const char *col_citizens(const struct city *pcity,
50 const struct player_slot *pslot);
52 /*****************************************************************************
53 The layout of the citizens display.
54 *****************************************************************************/
55 static struct citizens_column {
56 bool show;
57 enum player_dlg_column_type type;
58 const char *title;
59 const char *(*func)(const struct city *, const struct player_slot *);
60 /* if type = COL_*TEXT */
61 const char *tagname; /* for save_options */
62 } citizens_cols[] = {
63 {TRUE, COL_RIGHT_TEXT, N_("#"), col_citizens, "citizens"},
64 {TRUE, COL_FLAG, N_("Flag"), NULL, "flag"},
65 {TRUE, COL_TEXT, N_("Nation"), col_nation, "nation"}
67 static const int num_citizens_cols = ARRAY_SIZE(citizens_cols);
68 #define CITIZENS_DLG_COL_STYLE (0 + num_citizens_cols)
69 #define CITIZENS_DLG_COL_WEIGHT (1 + num_citizens_cols)
70 #define CITIZENS_DLG_COL_ID (2 + num_citizens_cols)
72 /*****************************************************************************
73 The citizens dialog.
74 *****************************************************************************/
75 struct citizens_dialog {
76 const struct city *pcity;
77 GtkWidget *shell;
78 GtkTreeStore *store;
79 GtkWidget *list;
80 GtkTreeModel *sort;
83 #define SPECLIST_TAG dialog
84 #define SPECLIST_TYPE struct citizens_dialog
85 #include "speclist.h"
87 #define dialog_list_iterate(dialoglist, pdialog) \
88 TYPED_LIST_ITERATE(struct citizens_dialog, dialoglist, pdialog)
89 #define dialog_list_iterate_end LIST_ITERATE_END
91 static struct dialog_list *dialog_list;
93 /*****************************************************************************
94 The name of the player's nation for the plrdlg.
95 *****************************************************************************/
96 static const char *col_nation(const struct city *pcity,
97 const struct player_slot *pslot)
99 return nation_adjective_for_player(player_slot_get_player(pslot));
102 /*****************************************************************************
103 The number of citizens for the player in the city.
104 *****************************************************************************/
105 static const char *col_citizens(const struct city *pcity,
106 const struct player_slot *pslot)
108 citizens nationality = citizens_nation_get(pcity, pslot);
110 if (nationality == 0) {
111 return "-";
112 } else {
113 static char buf[8];
115 fc_snprintf(buf, sizeof(buf), "%d", nationality);
117 return buf;
121 /****************************************************************************
122 Create a citizens dialog store.
124 FIXME: copy of players_dialog_store_new();
125 ****************************************************************************/
126 static GtkTreeStore *citizens_dialog_store_new(void)
128 GtkTreeStore *store;
129 GType model_types[num_citizens_cols + 3];
130 int i;
132 for (i = 0; i < num_citizens_cols; i++) {
133 switch (citizens_cols[i].type) {
134 case COL_FLAG:
135 model_types[i] = GDK_TYPE_PIXBUF;
136 break;
137 case COL_COLOR:
138 model_types[i] = GDK_TYPE_PIXBUF;
139 break;
140 case COL_BOOLEAN:
141 model_types[i] = G_TYPE_BOOLEAN;
142 break;
143 case COL_TEXT:
144 case COL_RIGHT_TEXT:
145 model_types[i] = G_TYPE_STRING;
146 break;
149 /* special (invisible rows) - Text style, weight and player id */
150 model_types[i++] = G_TYPE_INT; /* CITIZENS_DLG_COL_STYLE. */
151 model_types[i++] = G_TYPE_INT; /* CITIZENS_DLG_COL_WEIGHT. */
152 model_types[i++] = G_TYPE_INT; /* CITIZENS_DLG_COL_ID. */
154 store = gtk_tree_store_newv(i, model_types);
156 return store;
159 /*****************************************************************************
160 Returns column to sort by by default
161 *****************************************************************************/
162 static int citizens_dialog_default_sort_column(void) {
163 return 0;
166 /*****************************************************************************
167 Create citizens dialog
168 *****************************************************************************/
169 static struct citizens_dialog
170 *citizens_dialog_create(const struct city *pcity)
172 GtkWidget *frame, *align, *sw;
173 struct citizens_dialog *pdialog = fc_malloc(sizeof(struct citizens_dialog));
174 int i;
176 pdialog->pcity = pcity;
177 pdialog->store = citizens_dialog_store_new();
178 pdialog->sort
179 = gtk_tree_model_sort_new_with_model(GTK_TREE_MODEL(pdialog->store));
180 g_object_unref(pdialog->store);
182 gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(pdialog->sort),
183 citizens_dialog_default_sort_column(),
184 GTK_SORT_DESCENDING);
186 pdialog->list
187 = gtk_tree_view_new_with_model(GTK_TREE_MODEL(pdialog->sort));
188 g_object_unref(pdialog->sort);
190 for (i = 0; i < num_citizens_cols; i++) {
191 struct citizens_column *pcol;
192 GtkCellRenderer *renderer;
193 GtkTreeViewColumn *col;
195 pcol = &citizens_cols[i];
196 col = NULL;
198 switch (pcol->type) {
199 case COL_FLAG:
200 renderer = gtk_cell_renderer_pixbuf_new();
201 col = gtk_tree_view_column_new_with_attributes(_(pcol->title), renderer,
202 "pixbuf", i, NULL);
203 break;
204 case COL_TEXT:
205 renderer = gtk_cell_renderer_text_new();
206 g_object_set(renderer, "style-set", TRUE, "weight-set", TRUE, NULL);
208 col = gtk_tree_view_column_new_with_attributes(_(pcol->title), renderer,
209 "text", i,
210 "style", CITIZENS_DLG_COL_STYLE,
211 "weight", CITIZENS_DLG_COL_WEIGHT,
212 NULL);
213 gtk_tree_view_column_set_sort_column_id(col, i);
214 break;
215 case COL_RIGHT_TEXT:
216 renderer = gtk_cell_renderer_text_new();
217 g_object_set(renderer, "style-set", TRUE, "weight-set", TRUE, NULL);
219 col = gtk_tree_view_column_new_with_attributes(_(pcol->title), renderer,
220 "text", i,
221 "style", CITIZENS_DLG_COL_STYLE,
222 "weight", CITIZENS_DLG_COL_WEIGHT,
223 NULL);
224 gtk_tree_view_column_set_sort_column_id(col, i);
225 g_object_set(renderer, "xalign", 1.0, NULL);
226 gtk_tree_view_column_set_alignment(col, 1.0);
227 break;
228 case COL_COLOR:
229 case COL_BOOLEAN:
230 /* These are not used. */
231 fc_assert(pcol->type != COL_COLOR && pcol->type != COL_BOOLEAN);
232 continue;
235 if (col) {
236 gtk_tree_view_append_column(GTK_TREE_VIEW(pdialog->list), col);
240 align = gtk_alignment_new(0.5, 0.0, 0.0, 0.0);
241 gtk_container_add(GTK_CONTAINER(align), pdialog->list);
243 sw = gtk_scrolled_window_new(NULL, NULL);
244 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw),
245 GTK_POLICY_AUTOMATIC,
246 GTK_POLICY_AUTOMATIC);
247 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(sw),
248 GTK_SHADOW_NONE);
249 gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(sw), align);
251 frame = gtk_frame_new(_("Citizens"));
252 gtk_container_add(GTK_CONTAINER(frame), sw);
254 pdialog->shell = frame;
256 dialog_list_prepend(dialog_list, pdialog);
258 citizens_dialog_refresh(pcity);
260 return pdialog;
263 /*****************************************************************************
264 Initialize citizens dialog
265 *****************************************************************************/
266 void citizens_dialog_init()
268 dialog_list = dialog_list_new();
271 /*****************************************************************************
272 Free resources allocated for citizens dialog
273 *****************************************************************************/
274 void citizens_dialog_done()
276 dialog_list_destroy(dialog_list);
279 /*****************************************************************************
280 Get citizen dialog of the given city
281 *****************************************************************************/
282 static struct citizens_dialog *citizens_dialog_get(const struct city *pcity)
284 dialog_list_iterate(dialog_list, pdialog) {
285 if (pdialog->pcity == pcity) {
286 return pdialog;
288 } dialog_list_iterate_end;
290 return NULL;
293 /*****************************************************************************
294 Refresh citizen dialog of the given city
295 *****************************************************************************/
296 void citizens_dialog_refresh(const struct city *pcity)
298 struct citizens_dialog *pdialog = citizens_dialog_get(pcity);
300 if (pdialog == NULL) {
301 return;
304 gtk_tree_store_clear(pdialog->store);
305 citizens_iterate(pcity, pslot, nationality) {
306 GtkTreeIter iter;
308 gtk_tree_store_append(pdialog->store, &iter, NULL);
309 citizens_dialog_row(pdialog->store, &iter, pcity, pslot);
310 } citizens_iterate_end;
313 /*****************************************************************************
314 Fills the citizens list with the data for 'pslot' at the row given by 'it'.
315 *****************************************************************************/
316 static void citizens_dialog_row(GtkTreeStore *store, GtkTreeIter *it,
317 const struct city *pcity,
318 const struct player_slot *pslot)
320 GdkPixbuf *pixbuf;
321 int style = PANGO_STYLE_NORMAL, weight = PANGO_WEIGHT_NORMAL;
322 int k;
324 for (k = 0; k < num_citizens_cols; k++) {
325 struct citizens_column *pcol = &citizens_cols[k];
326 switch (pcol->type) {
327 case COL_TEXT:
328 case COL_RIGHT_TEXT:
329 gtk_tree_store_set(store, it, k, pcol->func(pcity, pslot), -1);
330 break;
331 case COL_FLAG:
332 pixbuf = get_flag(nation_of_player(player_slot_get_player(pslot)));
333 if (pixbuf != NULL) {
334 gtk_tree_store_set(store, it, k, pixbuf, -1);
335 g_object_unref(pixbuf);
337 break;
338 case COL_COLOR:
339 case COL_BOOLEAN:
340 /* These are not used. */
341 fc_assert(pcol->type != COL_COLOR && pcol->type != COL_BOOLEAN);
342 continue;
343 break;
347 if (city_owner(pcity)->slot == pslot) {
348 weight = PANGO_WEIGHT_BOLD;
349 style = PANGO_STYLE_NORMAL;
352 gtk_tree_store_set(store, it,
353 CITIZENS_DLG_COL_STYLE, style,
354 CITIZENS_DLG_COL_WEIGHT, weight,
355 CITIZENS_DLG_COL_ID, player_slot_index(pslot),
356 -1);
359 /*****************************************************************************
360 Close citizens dialog of one city
361 *****************************************************************************/
362 void citizens_dialog_close(const struct city *pcity)
364 struct citizens_dialog *pdialog = citizens_dialog_get(pcity);
365 if (pdialog == NULL) {
366 return;
369 gtk_widget_hide(pdialog->shell);
371 dialog_list_remove(dialog_list, pdialog);
373 gtk_widget_destroy(pdialog->shell);
374 free(pdialog);
377 /*****************************************************************************
378 Make citizen dialog of the city visible.
379 *****************************************************************************/
380 GtkWidget *citizens_dialog_display(const struct city *pcity)
382 struct citizens_dialog *pdialog = citizens_dialog_get(pcity);
384 if (!pdialog) {
385 pdialog = citizens_dialog_create(pcity);
388 gtk_widget_show_all(pdialog->shell);
389 citizens_dialog_refresh(pcity);
391 return pdialog->shell;