Freeciv-3.4
Loading...
Searching...
No Matches
wldlg.c
Go to the documentation of this file.
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.
7
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***********************************************************************/
13
14#ifdef HAVE_CONFIG_H
15#include <fc_config.h>
16#endif
17
18#include <stdlib.h>
19#include <string.h>
20
21#include <gtk/gtk.h>
22#include <gdk/gdk.h>
23
24/* utility */
25#include "fcintl.h"
26#include "log.h"
27#include "mem.h"
28#include "support.h"
29
30/* common */
31#include "city.h"
32#include "packets.h"
33#include "worklist.h"
34
35/* client */
36#include "citydlg_common.h"
37#include "client_main.h"
38#include "climisc.h"
39#include "global_worklist.h"
40#include "options.h"
41#include "text.h"
42#include "tilespec.h"
43
44/* client/gui-gtk-4.0 */
45#include "canvas.h"
46#include "citydlg.h"
47#include "graphics.h"
48#include "gui_main.h"
49#include "gui_stuff.h"
50#include "helpdlg.h"
51#include "inputdlg.h"
52
53#include "wldlg.h"
54
57
58enum {
63};
64
66
67static int max_unit_height = -1, max_unit_width = -1;
68
70 struct global_worklist *pgwl);
71static void popup_worklist(struct global_worklist *pgwl);
72static void popdown_worklist(struct global_worklist *pgwl);
75
76/************************************************************************/
80{
81 max_unit_height = -1;
82 max_unit_width = -1;
83}
84
85/************************************************************************/
104
105/************************************************************************/
109{
111}
112
113/************************************************************************/
132
133/************************************************************************/
136static void worklists_response(GtkWidget *w, gint response)
137{
138 struct global_worklist *pgwl;
139 int id;
140 GtkTreeSelection *selection;
141 GtkTreeModel *model;
142 GtkTreeIter it;
143
145
146 if (gtk_tree_selection_get_selected(selection, &model, &it)) {
147 gtk_tree_model_get(model, &it, 1, &id, -1);
149 } else {
150 pgwl = NULL;
151 id = -1;
152 }
153
154 switch (response) {
155 case WORKLISTS_NEW:
156 global_worklist_new(_("new"));
158 return;
159
160 case WORKLISTS_DELETE:
161 if (!pgwl) {
162 return;
163 }
164
168 return;
169
171 if (!pgwl) {
172 return;
173 }
174
176 return;
177
178 default:
180 return;
181 }
182}
183
184/************************************************************************/
188 const gchar *spath,
189 const gchar *text, gpointer data)
190{
191 GtkTreePath *path;
192 GtkTreeIter it;
193 struct global_worklist *pgwl;
194 int id;
195
198 gtk_tree_path_free(path);
199
202
203 if (!pgwl) {
205 return;
206 }
207
209 gtk_list_store_set(worklists_store, &it, 0, text, -1);
210
212}
213
214/************************************************************************/
218{
220 GtkWidget *vbox, *label, *sw;
222
223 shell = gtk_dialog_new_with_buttons(_("Edit worklists"),
224 NULL,
225 0,
226 _("_New"),
228 _("_Delete"),
230 _("_Properties"),
232 _("_Close"),
234 NULL);
236
237 g_signal_connect(shell, "response",
239 g_signal_connect(shell, "destroy",
241
244 vbox);
245
247
251
254
256
258 g_object_set(rend, "editable", TRUE, NULL);
259 g_signal_connect(rend, "edited",
262 rend, "text", 0, NULL);
263
270
272 "use-underline", TRUE,
273 "mnemonic-widget", list,
274 "label", _("_Worklists:"),
275 "xalign", 0.0, "yalign", 0.5, NULL);
276
277 gtk_box_append(GTK_BOX(vbox), label);
278 gtk_box_append(GTK_BOX(vbox), sw);
280
281 return shell;
282}
283
284/************************************************************************/
297
298/****************************************************************
299 ...
300*****************************************************************/
301struct worklist_data {
303 struct city *pcity;
304
306
313
315
318
319 bool future;
320};
321
323
324static void commit_worklist(struct worklist_data *ptr);
325
326/************************************************************************/
343
344/************************************************************************/
348{
349 if (hash) {
351
353 return ret;
354 } else {
355 return NULL;
356 }
357}
358
359/************************************************************************/
369
370/************************************************************************/
379
380/************************************************************************/
412
413/************************************************************************/
427
428/************************************************************************/
432{
433 struct worklist_data *ptr;
434
435 ptr = data;
436
437 if (ptr->global_worklist_id != -1) {
439 }
440
441 free(ptr);
442}
443
444/************************************************************************/
448 gpointer data)
449{
450 struct global_worklist *pgwl;
451 const struct worklist *pwl;
452 struct worklist_data *ptr = (struct worklist_data *)data;
453 size_t i;
454
455 if (NULL == client.conn.playing) {
456 return;
457 }
458
461 if (pgwl == NULL) {
462 return;
463 }
464
466
467 for (i = 0; i < (size_t) worklist_length(pwl); i++) {
468 GtkTreeIter it;
469 cid id;
470 char buf[8192];
471
472 id = cid_encode(pwl->entries[i]);
473
474 gtk_list_store_append(ptr->dst, &it);
475 gtk_list_store_set(ptr->dst, &it, 0, (gint)id,
476 1, production_help(&(pwl->entries[i]),
477 buf, sizeof(buf)), -1);
478 }
479
480 commit_worklist(ptr);
481}
482
483/************************************************************************/
487{
488 GSimpleAction *act;
489 int current_size = 0;
490
491 if (ptr->menu == NULL) {
492 ptr->menu = g_menu_new();
493 ptr->menu_size = 0;
494 }
495
497 int id = global_worklist_id(pgwl);
498 char act_name[60];
499
500 fc_snprintf(act_name, sizeof(act_name), "wl%d", id);
502
503 g_object_set_data(G_OBJECT(act), "id",
506 g_signal_connect(act, "activate", G_CALLBACK(menu_item_callback), ptr);
507
508 fc_snprintf(act_name, sizeof(act_name), "win.wl%d", id);
509
510 if (ptr->menu_size > current_size) {
512 }
516
517 act = g_simple_action_new("wledit", NULL);
519 g_signal_connect(act, "activate",
521
522 if (ptr->menu_size > current_size) {
524 }
525
527 g_menu_item_new(_("Edit Global _Worklists"), "win.wledit"));
528
529 if (ptr->menu_size < current_size) {
530 ptr->menu_size = current_size;
531 } else {
532 while (ptr->menu_size > current_size) {
533 g_menu_remove(ptr->menu, --ptr->menu_size);
534 }
535 }
536
537 return ptr->menu;
538}
539
540/************************************************************************/
544{
545 gint id;
546 struct universal target;
547
548 gtk_tree_model_get(model, it, 0, &id, -1);
549 target = cid_decode(id);
550
551 if (VUT_UTYPE == target.kind) {
553 HELP_UNIT);
554 } else if (is_great_wonder(target.value.building)) {
557 } else {
560 }
561}
562
563/************************************************************************/
566static void help_callback(GtkWidget *w, gpointer data)
567{
568 struct worklist_data *ptr;
569 GtkTreeSelection *selection;
570 GtkTreeModel *model;
571 GtkTreeIter it;
572
573 ptr = data;
574 selection = ptr->src_selection;
575
576 if (gtk_tree_selection_get_selected(selection, &model, &it)) {
577 wl_help_from_iter(model, &it);
578 } else {
580 }
581}
582
583/************************************************************************/
586static void change_callback(GtkWidget *w, gpointer data)
587{
588 struct worklist_data *ptr;
589 GtkTreeSelection *selection;
590 GtkTreeModel *model;
591 GtkTreeIter it;
592
593 ptr = data;
594 selection = ptr->src_selection;
595
596 if (gtk_tree_selection_get_selected(selection, &model, &it)) {
597 gint id;
598 struct universal univ;
599
600 gtk_tree_model_get(model, &it, 0, &id, -1);
601 univ = cid_production(id);
602 city_change_production(ptr->pcity, &univ);
603 }
604}
605
606/************************************************************************/
609static void future_callback(GtkToggleButton *toggle, gpointer data)
610{
611 struct worklist_data *ptr;
612
613 ptr = data;
614 ptr->future = !ptr->future;
615
617}
618
619/************************************************************************/
622static void queue_bubble_up(struct worklist_data *ptr)
623{
624 GtkTreePath *path;
626 GtkTreeModel *model;
627
629 return;
630 }
631
632 model = GTK_TREE_MODEL(ptr->dst);
634 if (path) {
636
637 if (gtk_tree_path_prev(path)) {
638 gtk_tree_model_get_iter(model, &it_prev, path);
639 it = it_prev;
640 gtk_tree_model_iter_next(model, &it);
641
643
645 commit_worklist(ptr);
646 }
647 }
648 gtk_tree_path_free(path);
649}
650
651/************************************************************************/
654static void queue_remove(struct worklist_data *ptr)
655{
656 GtkTreePath *path;
658
660 if (path) {
661 dst_row_callback(GTK_TREE_VIEW(ptr->dst_view), path, col, ptr);
662 gtk_tree_path_free(path);
663 }
664}
665
666/************************************************************************/
669static void queue_bubble_down(struct worklist_data *ptr)
670{
671 GtkTreePath *path;
673 GtkTreeModel *model;
674
676 return;
677 }
678
679 model = GTK_TREE_MODEL(ptr->dst);
681 if (path) {
683
684 gtk_tree_model_get_iter(model, &it, path);
685 it_next = it;
686 if (gtk_tree_model_iter_next(model, &it_next)) {
688
689 gtk_tree_path_next(path);
691 commit_worklist(ptr);
692 }
693 }
694 gtk_tree_path_free(path);
695}
696
697/************************************************************************/
700static void queue_insert(struct worklist_data *ptr, bool prepend)
701{
702 GtkTreeModel *model;
703 GtkTreeIter it;
704 GtkTreePath *path;
707 gint i, ncols;
708
710 return;
711 }
712
713 if (!gtk_tree_selection_get_selected(ptr->src_selection, &model, &it)) {
714 return;
715 }
716
717 path = gtk_tree_model_get_path(model, &it);
718
721
723 if (prepend) {
725 } else {
727 }
728
730
731 for (i = 0; i < ncols; i++) {
732 GValue value = { 0, };
733
736 }
737 commit_worklist(ptr);
738
739 gtk_tree_path_free(path);
740}
741
742/************************************************************************/
745static void queue_prepend(struct worklist_data *ptr)
746{
747 queue_insert(ptr, TRUE);
748}
749
750/************************************************************************/
753static void queue_append(struct worklist_data *ptr)
754{
755 queue_insert(ptr, FALSE);
756}
757
758/************************************************************************/
763{
764 struct worklist_data *ptr;
767 gint i, ncols;
768
769 ptr = data;
770
772 return;
773 }
774
777
780
782
783 for (i = 0; i < ncols; i++) {
784 GValue value = { 0, };
785
788 }
789 commit_worklist(ptr);
790}
791
792/************************************************************************/
797{
798 struct worklist_data *ptr;
800 GtkTreeIter it;
801
802 ptr = data;
804
806
808 commit_worklist(ptr);
809}
810
811/************************************************************************/
816 GdkModifierType state, gpointer data)
817{
818 struct worklist_data *ptr;
819
820 ptr = data;
821
823 return FALSE;
824 }
825
826 if ((state & GDK_SHIFT_MASK) && keyval == GDK_KEY_Insert) {
827 queue_prepend(ptr);
828 return TRUE;
829 } else if (keyval == GDK_KEY_Insert) {
830 queue_append(ptr);
831 return TRUE;
832 } else {
833 return FALSE;
834 }
835}
836
837/************************************************************************/
842 GdkModifierType state, gpointer data)
843{
844 GtkTreeModel *model;
845 struct worklist_data *ptr;
846
847 ptr = data;
848 model = GTK_TREE_MODEL(ptr->dst);
849
850 if (keyval == GDK_KEY_Delete) {
852 bool deleted = FALSE;
853
854 if (gtk_tree_model_get_iter_first(model, &it)) {
855 bool more;
856
857 do {
858 it_next = it;
859 more = gtk_tree_model_iter_next(model, &it_next);
860
863 deleted = TRUE;
864 }
865 it = it_next;
866
867 } while (more);
868 }
869
870 if (deleted) {
871 commit_worklist(ptr);
872 }
873
874 return TRUE;
875 } else if ((state & GDK_ALT_MASK) && keyval == GDK_KEY_Up) {
876 queue_bubble_up(ptr);
877
878 return TRUE;
879 } else if ((state & GDK_ALT_MASK) && keyval == GDK_KEY_Down) {
881
882 return TRUE;
883 } else {
884 return FALSE;
885 }
886}
887
888/************************************************************************/
892{
893 struct worklist_data *ptr;
894
895 ptr = data;
896
897 /* Update widget sensitivity. */
898 if (gtk_tree_selection_get_selected(selection, NULL, NULL)) {
900 && (!ptr->pcity || city_owner(ptr->pcity) == client.conn.playing)) {
901 /* If ptr->pcity is NULL, this is a global worklist */
905 } else {
909 }
911 } else {
916 }
917}
918
919/************************************************************************/
923{
924 struct worklist_data *ptr;
925
926 ptr = data;
927
928 /* Update widget sensitivity. */
929 if (gtk_tree_selection_count_selected_rows(selection) > 0) {
930 int num_rows = 0;
931 GtkTreeIter it;
932
936 do {
937 num_rows++;
938 } while (gtk_tree_model_iter_next(GTK_TREE_MODEL(ptr->dst), &it));
939 }
940 if (num_rows > 1) {
942 } else {
944 }
945 } else {
949 }
950}
951
952/************************************************************************/
956 GtkTreeModel *model, GtkTreeIter *it,
957 gpointer data)
958{
959 gint id;
960 struct universal target;
961
962 gtk_tree_model_get(model, it, 0, &id, -1);
963 target = cid_production(id);
964
966 GdkPixbuf *pix;
967 struct sprite *sprite;
968
969 if (VUT_UTYPE == target.kind) {
974 } else {
976 }
978 g_object_set(rend, "pixbuf", pix, NULL);
979 if (pix != NULL) {
981 }
982 if (VUT_UTYPE == target.kind) {
984 }
985 } else {
986 struct city **pcity = data;
987 gint column;
988 char *row[4];
989 char buf[4][64];
990 guint i;
991 gboolean useless;
992
993 for (i = 0; i < ARRAY_SIZE(row); i++) {
994 row[i] = buf[i];
995 }
997
998 get_city_dialog_production_row(row, sizeof(buf[0]), &target, *pcity);
999 g_object_set(rend, "text", row[column], NULL);
1000
1001 if (NULL != *pcity && VUT_IMPROVEMENT == target.kind) {
1002 useless = is_improvement_redundant(*pcity, target.value.building);
1003 /* Mark building redundant if we are really certain that there is
1004 * no use for it. */
1005 g_object_set(rend, "strikethrough", useless, NULL);
1006 } else {
1007 g_object_set(rend, "strikethrough", FALSE, NULL);
1008 }
1009 }
1010}
1011
1012/************************************************************************/
1017{
1018 static const char *titles[] =
1019 { N_("Type"), N_("Name"), N_("Info"), N_("Cost"), N_("Turns") };
1020
1021 static bool titles_done;
1022 guint i;
1025
1027
1028 /* Case i == 0 taken out of the loop to workaround gcc-4.2.1 bug
1029 * https://gcc.gnu.org/PR33381
1030 * Some values would 'stick' from i == 0 round. */
1031 i = 0;
1032
1034
1038
1040 if (max_unit_width == -1 || max_unit_height == -1) {
1042 }
1043 } else {
1044 g_object_set(col, "visible", FALSE, NULL);
1045 }
1048 }
1049
1050 for (i = 1; i < ARRAY_SIZE(titles); i++) {
1051 gint pos = i - 1;
1052
1055
1057 i, titles[i], rend,
1060
1061 if (pos >= 2) {
1062 g_object_set(G_OBJECT(rend), "xalign", 1.0, NULL);
1064 }
1065
1066 if (pos == 3) {
1067 *pcol = col;
1068 }
1071 }
1072 }
1073}
1074
1075/************************************************************************/
1079 int n_press,
1080 double x, double y)
1081{
1085 GtkTreePath *path;
1086 int bx, by;
1087
1089
1092
1093 if (gtk_tree_model_get_iter(model, &iter, path)) {
1094 wl_help_from_iter(model, &iter);
1095 }
1096 }
1097
1098 return TRUE;
1099}
1100
1101/************************************************************************/
1104static gboolean drag_drop(GtkDropTarget *target, const GValue *value,
1105 double x, double y, gpointer data)
1106{
1107 struct worklist_data *ptr = (struct worklist_data *)data;
1108 GtkTreeIter it;
1109 char buf[8192];
1110 cid id = g_value_get_int(value);
1111 struct universal univ;
1112
1113 univ = cid_production(id);
1114 gtk_list_store_append(ptr->dst, &it);
1115 gtk_list_store_set(ptr->dst, &it, 0, id, 1,
1116 production_help(&univ, buf, sizeof(buf)), -1);
1117
1118 commit_worklist(ptr);
1119
1120 return TRUE;
1121}
1122
1123/************************************************************************/
1127{
1128 GtkWidget *editor, *table, *sw, *bbox;
1129 GtkWidget *src_view, *dst_view, *label, *button;
1131 GMenu *menu;
1132 GtkWidget *table2, *arrow, *check;
1135 struct worklist_data *ptr;
1136 int editor_row = 0;
1140
1141 ptr = fc_malloc(sizeof(*ptr));
1142
1145
1146 ptr->global_worklist_id = -1;
1147 ptr->pcity = NULL;
1148 ptr->src = src_store;
1149 ptr->dst = dst_store;
1150 ptr->future = FALSE;
1151
1152 /* Create shell. */
1153 editor = gtk_grid_new();
1158 g_object_set_data(G_OBJECT(editor), "data", ptr);
1159
1160 ptr->editor = editor;
1161
1162 /* Add source and target lists. */
1163 table = gtk_grid_new();
1165
1167
1172 gtk_grid_attach(GTK_GRID(table), sw, 3, 1, 2, 1);
1173
1177 gtk_widget_add_css_class(GTK_WIDGET(src_view), "large-pixbufs");
1180 gtk_widget_set_name(src_view, "small_font");
1182
1186 g_signal_connect(controller, "pressed",
1189
1192
1194 "use-underline", TRUE,
1195 "mnemonic-widget", src_view,
1196 "label", _("Source _Tasks:"),
1197 "xalign", 0.0, "yalign", 0.5, NULL);
1198 gtk_grid_attach(GTK_GRID(table), label, 3, 0, 1, 1);
1199
1200 check = gtk_check_button_new_with_mnemonic(_("Show _Future Targets"));
1201 gtk_grid_attach(GTK_GRID(table), check, 4, 0, 1, 1);
1203
1204 table2 = gtk_grid_new();
1205 gtk_grid_attach(GTK_GRID(table), table2, 2, 1, 1, 1);
1206
1207 button = gtk_button_new();
1208 gtk_widget_set_margin_top(button, 24);
1209 gtk_widget_set_margin_bottom(button, 24);
1210 ptr->prepend_cmd = button;
1212 gtk_grid_attach(GTK_GRID(table2), button, 0, 0, 1, 1);
1213
1214 arrow = gtk_image_new_from_icon_name("pan-start-symbolic");
1215 gtk_button_set_child(GTK_BUTTON(button), arrow);
1216 g_signal_connect_swapped(button, "clicked",
1219
1220 button = gtk_button_new();
1221 ptr->up_cmd = button;
1223 gtk_grid_attach(GTK_GRID(table2), button, 0, 1, 1, 1);
1224
1225 arrow = gtk_image_new_from_icon_name("pan-up-symbolic");
1226 gtk_button_set_child(GTK_BUTTON(button), arrow);
1227 g_signal_connect_swapped(button, "clicked",
1230
1231 button = gtk_button_new();
1232 ptr->down_cmd = button;
1234 gtk_grid_attach(GTK_GRID(table2), button, 0, 2, 1, 1);
1235
1236 arrow = gtk_image_new_from_icon_name("pan-down-symbolic");
1237 gtk_button_set_child(GTK_BUTTON(button), arrow);
1238 g_signal_connect_swapped(button, "clicked",
1241
1242 button = gtk_button_new();
1243 gtk_widget_set_margin_top(button, 24);
1244 gtk_widget_set_margin_bottom(button, 24);
1245 ptr->append_cmd = button;
1247 gtk_grid_attach(GTK_GRID(table2), button, 0, 3, 1, 1);
1248
1249 arrow = gtk_image_new_from_icon_name("pan-start-symbolic");
1250 gtk_button_set_child(GTK_BUTTON(button), arrow);
1251 g_signal_connect_swapped(button, "clicked",
1252 G_CALLBACK(queue_append), ptr);
1254
1255 button = gtk_button_new();
1256 gtk_widget_set_margin_top(button, 24);
1257 gtk_widget_set_margin_bottom(button, 24);
1258 ptr->remove_cmd = button;
1260 gtk_grid_attach(GTK_GRID(table2), button, 0, 4, 1, 1);
1261
1262 arrow = gtk_image_new_from_icon_name("pan-end-symbolic");
1263 gtk_button_set_child(GTK_BUTTON(button), arrow);
1264 g_signal_connect_swapped(button, "clicked",
1265 G_CALLBACK(queue_remove), ptr);
1267
1272 gtk_grid_attach(GTK_GRID(table), sw, 0, 1, 2, 1);
1273
1277 gtk_widget_add_css_class(GTK_WIDGET(dst_view), "large-pixbufs");
1280 gtk_widget_set_name(dst_view, "small_font");
1282
1286 g_signal_connect(controller, "pressed",
1289
1292
1294 "use-underline", TRUE,
1295 "mnemonic-widget", dst_view,
1296 "label", _("Target _Worklist:"),
1297 "xalign", 0.0, "yalign", 0.5, NULL);
1298 gtk_grid_attach(GTK_GRID(table), label, 0, 0, 1, 1);
1299
1300 /* Add bottom menu and buttons. */
1304
1305 ptr->menu = NULL;
1308 menu = create_wl_menu(ptr);
1310
1313
1314 button = icon_label_button_new("help-browser", _("Help"));
1315 gtk_box_append(GTK_BOX(bbox), button);
1316 g_signal_connect(button, "clicked",
1318 ptr->help_cmd = button;
1320
1321 button = gtk_button_new_with_mnemonic(_("Change Prod_uction"));
1322 gtk_box_append(GTK_BOX(bbox), button);
1323 g_signal_connect(button, "clicked",
1325 ptr->change_cmd = button;
1327
1328 ptr->src_view = src_view;
1329 ptr->dst_view = dst_view;
1333
1334 /* DND and other state changing callbacks. */
1336
1338
1341
1343 g_signal_connect(controller, "key-pressed",
1346
1348 g_signal_connect(controller, "key-pressed",
1351
1352 g_signal_connect(src_view, "row_activated",
1354
1355 g_signal_connect(dst_view, "row_activated",
1357
1358 g_signal_connect(ptr->src_selection, "changed",
1360 g_signal_connect(ptr->dst_selection, "changed",
1362
1363
1366
1367 return editor;
1368}
1369
1370/************************************************************************/
1374 double x, double y,
1375 gpointer data)
1376{
1377 GtkTreeIter it;
1378 struct worklist_data *ptr = (struct worklist_data *)data;
1379
1381 gint id;
1383
1384 gtk_tree_model_get(GTK_TREE_MODEL(ptr->src), &it, 0, &id, -1);
1385
1387
1389
1390 return provider;
1391 }
1392
1393 return NULL;
1394}
1395
1396/************************************************************************/
1400 gpointer *data)
1401{
1403 GValue val = { 0, };
1405 cid id;
1406 struct universal target;
1407 struct sprite *sprite;
1408 GdkPixbuf *pix;
1409 GtkWidget *img;
1410
1411 g_value_init(&val, G_TYPE_INT);
1412 if (gdk_content_provider_get_value(content, &val, NULL)) {
1413 id = g_value_get_int(&val);
1414 target = cid_production(id);
1415
1416 if (VUT_UTYPE == target.kind) {
1421 } else {
1423 }
1426
1428
1431 }
1432}
1433
1434/************************************************************************/
1438{
1439 struct worklist_data *ptr;
1441
1442 ptr = g_object_get_data(G_OBJECT(editor), "data");
1443
1444 ptr->global_worklist_id = -1;
1445 ptr->pcity = pcity;
1446
1449
1450 g_object_set(ptr->src_col, "visible", TRUE, NULL);
1451 g_object_set(ptr->dst_col, "visible", TRUE, NULL);
1452
1454
1456 g_signal_connect(dnd_src, "drag-begin", G_CALLBACK(drag_begin), ptr);
1457
1460}
1461
1462/************************************************************************/
1466 struct global_worklist *pgwl)
1467{
1468 struct worklist_data *ptr;
1469
1470 ptr = g_object_get_data(G_OBJECT(editor), "data");
1471
1473 ptr->pcity = nullptr;
1474
1477
1479 g_object_set(ptr->src_col, "visible", FALSE, NULL);
1480 g_object_set(ptr->dst_col, "visible", FALSE, NULL);
1481
1483}
1484
1485/************************************************************************/
1489{
1490 struct worklist_data *ptr;
1491 struct worklist queue;
1492 struct universal targets[MAX_NUM_PRODUCTION_TARGETS];
1493 int i, targets_used;
1494 struct item items[MAX_NUM_PRODUCTION_TARGETS];
1495 bool selected;
1496 gint id;
1497 GtkTreeIter it;
1498 GtkTreePath *path;
1499 GtkTreeModel *model;
1501
1502 ptr = g_object_get_data(G_OBJECT(editor), "data");
1503
1504 /* Refresh source tasks. */
1506 gtk_tree_model_get(GTK_TREE_MODEL(ptr->src), &it, 0, &id, -1);
1507 selected = TRUE;
1508 } else {
1509 selected = FALSE;
1510 }
1511
1512 /* These behave just right if ptr->pcity is NULL -> in case of global
1513 * worklist. */
1515 ptr->future);
1516 name_and_sort_items(targets, targets_used, items, FALSE, ptr->pcity);
1517
1518 /* Re-purpose existing items in the list store -- this avoids the
1519 * UI jumping around (especially as the set of source tasks doesn't
1520 * actually change much in practice). */
1521 model = GTK_TREE_MODEL(ptr->src);
1523
1524 path = NULL;
1525 for (i = 0; i < targets_used; i++) {
1526 char buf[8192];
1527
1528 if (!exists) {
1529 gtk_list_store_append(ptr->src, &it);
1530 }
1531
1532 gtk_list_store_set(ptr->src, &it, 0, (gint)cid_encode(items[i].item),
1533 1, production_help(&(items[i].item),
1534 buf, sizeof(buf)), -1);
1535
1536 if (selected && cid_encode(items[i].item) == id) {
1537 path = gtk_tree_model_get_path(GTK_TREE_MODEL(ptr->src), &it);
1538 }
1539
1540 if (exists) {
1541 exists = gtk_tree_model_iter_next(model, &it);
1542 }
1543 }
1544
1545 /* If the list got shorter, delete any excess items. */
1546 if (exists) {
1548 bool more;
1549
1550 do {
1551 it_next = it;
1552 more = gtk_tree_model_iter_next(model, &it_next);
1553
1554 gtk_list_store_remove(ptr->src, &it);
1555 it = it_next;
1556 } while (more);
1557 }
1558
1559 /* Select the same item that was previously selected, if any. */
1560 if (path) {
1562 gtk_tree_path_free(path);
1563 }
1564
1565 /* Refresh target worklist. */
1566 model = GTK_TREE_MODEL(ptr->dst);
1568
1569 /* Dance around worklist braindamage. */
1570 if (ptr->pcity != NULL) {
1571 city_get_queue(ptr->pcity, &queue);
1572 } else {
1573 const struct global_worklist *pgwl;
1574
1576
1577 fc_assert(NULL != pgwl);
1578
1580 }
1581
1582 for (i = 0; i < worklist_length(&queue); i++) {
1583 struct universal target = queue.entries[i];
1584 char buf[8192];
1585
1586 if (!exists) {
1587 gtk_list_store_append(ptr->dst, &it);
1588 }
1589
1590 gtk_list_store_set(ptr->dst, &it, 0, (gint)cid_encode(target),
1591 1, production_help(&target,
1592 buf, sizeof(buf)), -1);
1593
1594 if (exists) {
1595 exists = gtk_tree_model_iter_next(model, &it);
1596 }
1597 }
1598
1599 if (exists) {
1601 bool more;
1602
1603 do {
1604 it_next = it;
1605 more = gtk_tree_model_iter_next(model, &it_next);
1606
1607 gtk_list_store_remove(ptr->dst, &it);
1608 it = it_next;
1609 } while (more);
1610 }
1611
1612 create_wl_menu(ptr);
1613
1614 /* Update widget sensitivity. */
1615 if (ptr->pcity) {
1617 && city_owner(ptr->pcity) == client.conn.playing)) {
1619 } else {
1621 }
1622 } else {
1624 }
1625}
1626
1627/************************************************************************/
1630static void commit_worklist(struct worklist_data *ptr)
1631{
1632 struct worklist queue;
1633 GtkTreeModel *model;
1634 GtkTreeIter it;
1635 size_t i;
1636
1637 model = GTK_TREE_MODEL(ptr->dst);
1638
1639 worklist_init(&queue);
1640
1641 i = 0;
1642 if (gtk_tree_model_get_iter_first(model, &it)) {
1643 do {
1644 gint id;
1645 struct universal univ;
1646
1647 /* Oops, the player has a worklist longer than what we can store. */
1648 if (i >= MAX_LEN_WORKLIST) {
1649 break;
1650 }
1651
1652 gtk_tree_model_get(model, &it, 0, &id, -1);
1653 univ = cid_production(id);
1654 worklist_append(&queue, &univ);
1655
1656 i++;
1657 } while (gtk_tree_model_iter_next(model, &it));
1658 }
1659
1660 /* Dance around worklist braindamage. */
1661 if (ptr->pcity) {
1662 if (!city_set_queue(ptr->pcity, &queue)) {
1663 /* Failed to change worklist. This means worklist visible
1664 * on screen is not true. */
1666 }
1667 } else {
1668 struct global_worklist *pgwl;
1669
1671 if (pgwl) {
1672 global_worklist_set(pgwl, &queue);
1673 }
1674 }
1675}
#define city_owner(_pcity_)
Definition city.h:564
void get_city_dialog_production_row(char *buf[], size_t column_size, struct universal *target, struct city *pcity)
bool city_set_queue(struct city *pcity, const struct worklist *pqueue)
int city_change_production(struct city *pcity, struct universal *target)
void city_get_queue(struct city *pcity, struct worklist *pqueue)
struct civclient client
bool can_client_issue_orders(void)
int collect_eventually_buildable_targets(struct universal *targets, struct city *pcity, bool advanced_tech)
Definition climisc.c:821
void name_and_sort_items(struct universal *targets, int num_targets, struct item *items, bool show_cost, struct city *pcity)
Definition climisc.c:650
cid cid_encode(struct universal target)
Definition climisc.c:483
struct universal cid_decode(cid id)
Definition climisc.c:526
#define MAX_NUM_PRODUCTION_TARGETS
Definition climisc.h:89
#define cid_production
Definition climisc.h:71
int cid
Definition climisc.h:31
static struct fc_sockaddr_list * list
Definition clinet.c:102
char * incite_cost
Definition comments.c:77
struct unit struct city struct unit struct tile struct extra_type const struct act_prob *act_probs int actor_unit_id struct unit struct unit int const struct action *paction struct unit struct city * pcity
Definition dialogs_g.h:77
int int id
Definition editgui_g.h:28
static struct editor_state * editor
Definition editor.c:100
#define _(String)
Definition fcintl.h:67
#define N_(String)
Definition fcintl.h:69
struct global_worklist * global_worklist_by_id(int id)
bool global_worklist_set(struct global_worklist *pgwl, const struct worklist *pwl)
const char * global_worklist_name(const struct global_worklist *pgwl)
int global_worklist_id(const struct global_worklist *pgwl)
void global_worklist_destroy(struct global_worklist *pgwl)
const struct worklist * global_worklist_get(const struct global_worklist *pgwl)
struct global_worklist * global_worklist_new(const char *name)
void global_worklist_set_name(struct global_worklist *pgwl, const char *name)
#define global_worklists_iterate(pgwl)
#define global_worklists_iterate_end
static struct tile * pos
Definition finddlg.c:53
static GtkWidget * source
Definition gotodlg.c:58
GtkWidget * toplevel
Definition gui_main.c:126
#define GUI_GTK_OPTION(optname)
Definition gui_main.h:32
GtkWidget * icon_label_button_new(const gchar *icon_name, const gchar *label_text)
Definition gui_stuff.c:76
void setup_dialog(GtkWidget *shell, GtkWidget *parent)
Definition gui_stuff.c:287
void intl_slist(int n, const char **s, bool *done)
Definition gui_stuff.c:111
void popup_help_dialog_string(const char *item)
Definition helpdlg.c:212
void popup_help_dialog_typed(const char *item, enum help_page_type htype)
Definition helpdlg.c:196
static struct gui_dialog * shell
Definition messagedlg.c:39
void free_sprite(struct sprite *s)
Definition sprite.c:278
struct sprite * sprite_scale(struct sprite *src, int new_w, int new_h)
Definition sprite.c:291
GdkPixbuf * sprite_get_pixbuf(struct sprite *sprite)
Definition sprite.c:402
void sprite_get_bounding_box(struct sprite *sprite, int *start_x, int *start_y, int *end_x, int *end_y)
Definition sprite.c:321
static GHashTable * hash
Definition wldlg.c:322
static void dst_selection_callback(GtkTreeSelection *selection, gpointer data)
Definition wldlg.c:891
static void worklists_response(GtkWidget *w, gint response)
Definition wldlg.c:134
void update_worklist_report_dialog(void)
Definition wldlg.c:116
static void queue_remove(struct worklist_data *ptr)
Definition wldlg.c:624
static GtkWidget * get_worklist(int global_worklist_id)
Definition wldlg.c:349
static void reset_global_worklist(GtkWidget *editor, struct global_worklist *pgwl)
Definition wldlg.c:1304
static void future_callback(GtkToggleButton *toggle, gpointer data)
Definition wldlg.c:579
void blank_max_unit_size(void)
Definition wldlg.c:79
static void src_selection_callback(GtkTreeSelection *selection, gpointer data)
Definition wldlg.c:860
static void help_callback(GtkWidget *w, gpointer data)
Definition wldlg.c:521
static void src_row_callback(GtkTreeView *view, GtkTreePath *path, GtkTreeViewColumn *col, gpointer data)
Definition wldlg.c:732
static void dst_row_callback(GtkTreeView *view, GtkTreePath *path, GtkTreeViewColumn *col, gpointer data)
Definition wldlg.c:766
static void delete_worklist(int global_worklist_id)
Definition wldlg.c:375
void refresh_worklist(GtkWidget *editor)
Definition wldlg.c:1327
void add_worklist_dnd_target(GtkWidget *w)
Definition wldlg.c:339
static gboolean src_key_press_callback(GtkWidget *w, GdkEventKey *ev, gpointer data)
Definition wldlg.c:785
static void popdown_worklist(struct global_worklist *pgwl)
Definition wldlg.c:420
static GtkWidget * worklists_shell
Definition wldlg.c:55
static void popup_worklist(struct global_worklist *pgwl)
Definition wldlg.c:385
static GtkWidget * worklists_list
Definition wldlg.c:56
static void queue_bubble_up(struct worklist_data *ptr)
Definition wldlg.c:592
static GtkWidget * create_worklists_report(void)
Definition wldlg.c:213
static void cell_edited(GtkCellRendererText *cell, const gchar *spath, const gchar *text, gpointer data)
Definition wldlg.c:185
static void cell_render_func(GtkTreeViewColumn *col, GtkCellRenderer *rend, GtkTreeModel *model, GtkTreeIter *it, gpointer data)
Definition wldlg.c:934
static gboolean dst_key_press_callback(GtkWidget *w, GdkEventKey *ev, gpointer data)
Definition wldlg.c:810
static void worklist_destroy(GtkWidget *editor, gpointer data)
Definition wldlg.c:435
static void worklists_destroy_callback(GtkWidget *w, gpointer data)
Definition wldlg.c:108
static void change_callback(GtkWidget *w, gpointer data)
Definition wldlg.c:556
void reset_city_worklist(GtkWidget *editor, struct city *pcity)
Definition wldlg.c:1279
static void queue_insert(struct worklist_data *ptr, bool prepend)
Definition wldlg.c:670
static void menu_item_callback(GtkMenuItem *item, struct worklist_data *ptr)
Definition wldlg.c:451
static void populate_view(GtkTreeView *view, struct city **ppcity, GtkTreeViewColumn **pcol)
Definition wldlg.c:992
@ WORKLISTS_NEW
Definition wldlg.c:59
@ WORKLISTS_CLOSE
Definition wldlg.c:62
@ WORKLISTS_DELETE
Definition wldlg.c:60
@ WORKLISTS_PROPERTIES
Definition wldlg.c:61
static void insert_worklist(int global_worklist_id, GtkWidget *editor)
Definition wldlg.c:364
static void queue_append(struct worklist_data *ptr)
Definition wldlg.c:724
GtkWidget * create_worklist(void)
Definition wldlg.c:1054
static void commit_worklist(struct worklist_data *ptr)
Definition wldlg.c:1470
static void queue_bubble_down(struct worklist_data *ptr)
Definition wldlg.c:639
static int max_unit_width
Definition wldlg.c:67
static int max_unit_height
Definition wldlg.c:67
static void update_max_unit_size(void)
Definition wldlg.c:88
static void queue_prepend(struct worklist_data *ptr)
Definition wldlg.c:716
static GtkListStore * worklists_store
Definition wldlg.c:65
void popup_worklists_report(void)
Definition wldlg.c:287
void refresh_all_city_worklists(void)
Definition citydlg.c:3792
GtkWidget * aux_menu_new(void)
Definition gui_stuff.c:244
#define menu_item_insert_unref(menu, index, item)
Definition gui_stuff.h:142
static void drag_begin(GtkDragSource *source, GdkDrag *drag, gpointer *data)
Definition wldlg.c:1399
static gboolean wl_right_button_up(GtkGestureClick *gesture, int n_press, double x, double y)
Definition wldlg.c:1078
static void wl_help_from_iter(GtkTreeModel *model, GtkTreeIter *it)
Definition wldlg.c:543
static GMenu * create_wl_menu(struct worklist_data *ptr)
Definition wldlg.c:486
static GdkContentProvider * drag_prepare(GtkDragSource *source, double x, double y, gpointer data)
Definition wldlg.c:1373
static gboolean drag_drop(GtkDropTarget *target, const GValue *value, double x, double y, gpointer data)
Definition wldlg.c:1104
#define HELP_WORKLIST_EDITOR_ITEM
@ HELP_IMPROVEMENT
Definition helpdlg_g.h:20
@ HELP_UNIT
Definition helpdlg_g.h:20
@ HELP_WONDER
Definition helpdlg_g.h:21
bool is_improvement_redundant(const struct city *pcity, const struct impr_type *pimprove)
bool is_great_wonder(const struct impr_type *pimprove)
const char * improvement_name_translation(const struct impr_type *pimprove)
#define fc_assert(condition)
Definition log.h:177
#define fc_malloc(sz)
Definition mem.h:34
#define ARRAY_SIZE(x)
Definition shared.h:85
#define MAX(x, y)
Definition shared.h:54
struct sprite int int y
Definition sprite_g.h:31
struct sprite int x
Definition sprite_g.h:31
Definition city.h:318
struct connection conn
Definition client_main.h:96
struct player * playing
Definition connection.h:151
Definition mapimg.c:367
Definition climisc.h:82
enum universals_n kind
Definition fc_types.h:595
universals_u value
Definition fc_types.h:594
GtkWidget * prepend_cmd
Definition wldlg.c:317
GActionGroup * group
Definition wldlg.c:311
GtkWidget * dst_view
Definition wldlg.c:311
GtkTreeViewColumn * dst_col
Definition wldlg.c:314
GtkTreeSelection * dst_selection
Definition wldlg.c:312
int menu_size
Definition wldlg.c:310
GtkWidget * src_view
Definition wldlg.c:311
GtkWidget * up_cmd
Definition wldlg.c:317
bool future
Definition wldlg.c:319
GtkTreeSelection * src_selection
Definition wldlg.c:312
GtkListStore * src
Definition wldlg.c:310
GtkTreeViewColumn * src_col
Definition wldlg.c:314
GtkWidget * remove_cmd
Definition wldlg.c:317
GtkListStore * dst
Definition wldlg.c:310
GtkWidget * editor
Definition wldlg.c:308
int global_worklist_id
Definition wldlg.c:305
GtkWidget * append_cmd
Definition wldlg.c:317
GtkWidget * help_cmd
Definition wldlg.c:316
struct city * pcity
Definition wldlg.c:306
GMenu * menu
Definition wldlg.c:309
GtkWidget * down_cmd
Definition wldlg.c:317
GtkWidget * change_cmd
Definition wldlg.c:316
struct universal entries[MAX_LEN_WORKLIST]
Definition worklist.h:30
int fc_snprintf(char *str, size_t n, const char *format,...)
Definition support.c:925
#define TRUE
Definition support.h:46
#define FALSE
Definition support.h:47
const char * production_help(const struct universal *uni, char *buf, size_t bufsize)
Definition text.c:2169
struct sprite * get_building_sprite(const struct tileset *t, const struct impr_type *pimprove)
Definition tilespec.c:7033
struct sprite * get_unittype_sprite(const struct tileset *t, const struct unit_type *punittype, enum unit_activity activity, enum direction8 facing)
Definition tilespec.c:7055
const struct unit_type * utype
Definition fc_types.h:536
const struct impr_type * building
Definition fc_types.h:529
const char * utype_name_translation(const struct unit_type *punittype)
Definition unittype.c:1586
#define unit_type_iterate(_p)
Definition unittype.h:865
#define unit_type_iterate_end
Definition unittype.h:872
void worklist_copy(struct worklist *dst, const struct worklist *src)
Definition worklist.c:112
void worklist_init(struct worklist *pwl)
Definition worklist.c:38
bool worklist_append(struct worklist *pwl, const struct universal *prod)
Definition worklist.c:147
int worklist_length(const struct worklist *pwl)
Definition worklist.c:57
#define MAX_LEN_WORKLIST
Definition worklist.h:24