Freeciv-3.3
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/gdkkeysyms.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);
980 if (VUT_UTYPE == target.kind) {
982 }
983 } else {
984 struct city **pcity = data;
985 gint column;
986 char *row[4];
987 char buf[4][64];
988 guint i;
989 gboolean useless;
990
991 for (i = 0; i < ARRAY_SIZE(row); i++) {
992 row[i] = buf[i];
993 }
995
996 get_city_dialog_production_row(row, sizeof(buf[0]), &target, *pcity);
997 g_object_set(rend, "text", row[column], NULL);
998
999 if (NULL != *pcity && VUT_IMPROVEMENT == target.kind) {
1000 useless = is_improvement_redundant(*pcity, target.value.building);
1001 /* Mark building redundant if we are really certain that there is
1002 * no use for it. */
1003 g_object_set(rend, "strikethrough", useless, NULL);
1004 } else {
1005 g_object_set(rend, "strikethrough", FALSE, NULL);
1006 }
1007 }
1008}
1009
1010/************************************************************************/
1015{
1016 static const char *titles[] =
1017 { N_("Type"), N_("Name"), N_("Info"), N_("Cost"), N_("Turns") };
1018
1019 static bool titles_done;
1020 guint i;
1023
1025
1026 /* Case i == 0 taken out of the loop to workaround gcc-4.2.1 bug
1027 * https://gcc.gnu.org/PR33381
1028 * Some values would 'stick' from i == 0 round. */
1029 i = 0;
1030
1032
1036
1038 if (max_unit_width == -1 || max_unit_height == -1) {
1040 }
1041 } else {
1042 g_object_set(col, "visible", FALSE, NULL);
1043 }
1046 }
1047
1048 for (i = 1; i < ARRAY_SIZE(titles); i++) {
1049 gint pos = i - 1;
1050
1053
1055 i, titles[i], rend,
1058
1059 if (pos >= 2) {
1060 g_object_set(G_OBJECT(rend), "xalign", 1.0, NULL);
1062 }
1063
1064 if (pos == 3) {
1065 *pcol = col;
1066 }
1069 }
1070 }
1071}
1072
1073/************************************************************************/
1077 int n_press,
1078 double x, double y)
1079{
1083 GtkTreePath *path;
1084 int bx, by;
1085
1087
1090
1091 if (gtk_tree_model_get_iter(model, &iter, path)) {
1092 wl_help_from_iter(model, &iter);
1093 }
1094 }
1095
1096 return TRUE;
1097}
1098
1099/************************************************************************/
1102static gboolean drag_drop(GtkDropTarget *target, const GValue *value,
1103 double x, double y, gpointer data)
1104{
1105 struct worklist_data *ptr = (struct worklist_data *)data;
1106 GtkTreeIter it;
1107 char buf[8192];
1108 cid id = g_value_get_int(value);
1109 struct universal univ;
1110
1111 univ = cid_production(id);
1112 gtk_list_store_append(ptr->dst, &it);
1113 gtk_list_store_set(ptr->dst, &it, 0, id, 1,
1114 production_help(&univ, buf, sizeof(buf)), -1);
1115
1116 commit_worklist(ptr);
1117
1118 return TRUE;
1119}
1120
1121/************************************************************************/
1125{
1126 GtkWidget *editor, *table, *sw, *bbox;
1127 GtkWidget *src_view, *dst_view, *label, *button;
1129 GMenu *menu;
1130 GtkWidget *table2, *arrow, *check;
1133 struct worklist_data *ptr;
1134 int editor_row = 0;
1138
1139 ptr = fc_malloc(sizeof(*ptr));
1140
1143
1144 ptr->global_worklist_id = -1;
1145 ptr->pcity = NULL;
1146 ptr->src = src_store;
1147 ptr->dst = dst_store;
1148 ptr->future = FALSE;
1149
1150 /* Create shell. */
1151 editor = gtk_grid_new();
1156 g_object_set_data(G_OBJECT(editor), "data", ptr);
1157
1158 ptr->editor = editor;
1159
1160 /* Add source and target lists. */
1161 table = gtk_grid_new();
1163
1165
1170 gtk_grid_attach(GTK_GRID(table), sw, 3, 1, 2, 1);
1171
1177 gtk_widget_set_name(src_view, "small_font");
1179
1183 g_signal_connect(controller, "pressed",
1186
1189
1191 "use-underline", TRUE,
1192 "mnemonic-widget", src_view,
1193 "label", _("Source _Tasks:"),
1194 "xalign", 0.0, "yalign", 0.5, NULL);
1195 gtk_grid_attach(GTK_GRID(table), label, 3, 0, 1, 1);
1196
1197 check = gtk_check_button_new_with_mnemonic(_("Show _Future Targets"));
1198 gtk_grid_attach(GTK_GRID(table), check, 4, 0, 1, 1);
1200
1201 table2 = gtk_grid_new();
1202 gtk_grid_attach(GTK_GRID(table), table2, 2, 1, 1, 1);
1203
1204 button = gtk_button_new();
1205 gtk_widget_set_margin_top(button, 24);
1206 gtk_widget_set_margin_bottom(button, 24);
1207 ptr->prepend_cmd = button;
1209 gtk_grid_attach(GTK_GRID(table2), button, 0, 0, 1, 1);
1210
1211 arrow = gtk_image_new_from_icon_name("pan-start-symbolic");
1212 gtk_button_set_child(GTK_BUTTON(button), arrow);
1213 g_signal_connect_swapped(button, "clicked",
1216
1217 button = gtk_button_new();
1218 ptr->up_cmd = button;
1220 gtk_grid_attach(GTK_GRID(table2), button, 0, 1, 1, 1);
1221
1222 arrow = gtk_image_new_from_icon_name("pan-up-symbolic");
1223 gtk_button_set_child(GTK_BUTTON(button), arrow);
1224 g_signal_connect_swapped(button, "clicked",
1227
1228 button = gtk_button_new();
1229 ptr->down_cmd = button;
1231 gtk_grid_attach(GTK_GRID(table2), button, 0, 2, 1, 1);
1232
1233 arrow = gtk_image_new_from_icon_name("pan-down-symbolic");
1234 gtk_button_set_child(GTK_BUTTON(button), arrow);
1235 g_signal_connect_swapped(button, "clicked",
1238
1239 button = gtk_button_new();
1240 gtk_widget_set_margin_top(button, 24);
1241 gtk_widget_set_margin_bottom(button, 24);
1242 ptr->append_cmd = button;
1244 gtk_grid_attach(GTK_GRID(table2), button, 0, 3, 1, 1);
1245
1246 arrow = gtk_image_new_from_icon_name("pan-start-symbolic");
1247 gtk_button_set_child(GTK_BUTTON(button), arrow);
1248 g_signal_connect_swapped(button, "clicked",
1249 G_CALLBACK(queue_append), ptr);
1251
1252 button = gtk_button_new();
1253 gtk_widget_set_margin_top(button, 24);
1254 gtk_widget_set_margin_bottom(button, 24);
1255 ptr->remove_cmd = button;
1257 gtk_grid_attach(GTK_GRID(table2), button, 0, 4, 1, 1);
1258
1259 arrow = gtk_image_new_from_icon_name("pan-end-symbolic");
1260 gtk_button_set_child(GTK_BUTTON(button), arrow);
1261 g_signal_connect_swapped(button, "clicked",
1262 G_CALLBACK(queue_remove), ptr);
1264
1269 gtk_grid_attach(GTK_GRID(table), sw, 0, 1, 2, 1);
1270
1276 gtk_widget_set_name(dst_view, "small_font");
1278
1282 g_signal_connect(controller, "pressed",
1285
1288
1290 "use-underline", TRUE,
1291 "mnemonic-widget", dst_view,
1292 "label", _("Target _Worklist:"),
1293 "xalign", 0.0, "yalign", 0.5, NULL);
1294 gtk_grid_attach(GTK_GRID(table), label, 0, 0, 1, 1);
1295
1296 /* Add bottom menu and buttons. */
1300
1301 ptr->menu = NULL;
1304 menu = create_wl_menu(ptr);
1306
1309
1310 button = icon_label_button_new("help-browser", _("Help"));
1311 gtk_box_append(GTK_BOX(bbox), button);
1312 g_signal_connect(button, "clicked",
1314 ptr->help_cmd = button;
1316
1317 button = gtk_button_new_with_mnemonic(_("Change Prod_uction"));
1318 gtk_box_append(GTK_BOX(bbox), button);
1319 g_signal_connect(button, "clicked",
1321 ptr->change_cmd = button;
1323
1324 ptr->src_view = src_view;
1325 ptr->dst_view = dst_view;
1329
1330 /* DND and other state changing callbacks. */
1332
1334
1337
1339 g_signal_connect(controller, "key-pressed",
1342
1344 g_signal_connect(controller, "key-pressed",
1347
1348 g_signal_connect(src_view, "row_activated",
1350
1351 g_signal_connect(dst_view, "row_activated",
1353
1354 g_signal_connect(ptr->src_selection, "changed",
1356 g_signal_connect(ptr->dst_selection, "changed",
1358
1359
1362
1363 return editor;
1364}
1365
1366/************************************************************************/
1370 double x, double y,
1371 gpointer data)
1372{
1373 GtkTreeIter it;
1374 struct worklist_data *ptr = (struct worklist_data *)data;
1375
1377 gint id;
1379
1380 gtk_tree_model_get(GTK_TREE_MODEL(ptr->src), &it, 0, &id, -1);
1381
1383
1385
1386 return provider;
1387 }
1388
1389 return NULL;
1390}
1391
1392/************************************************************************/
1396 gpointer *data)
1397{
1399 GValue val = { 0, };
1401 cid id;
1402 struct universal target;
1403 struct sprite *sprite;
1404 GdkPixbuf *pix;
1405 GtkWidget *img;
1406
1407 g_value_init(&val, G_TYPE_INT);
1408 if (gdk_content_provider_get_value(content, &val, NULL)) {
1409 id = g_value_get_int(&val);
1410 target = cid_production(id);
1411
1412 if (VUT_UTYPE == target.kind) {
1417 } else {
1419 }
1422
1424
1427 }
1428}
1429
1430/************************************************************************/
1434{
1435 struct worklist_data *ptr;
1437
1438 ptr = g_object_get_data(G_OBJECT(editor), "data");
1439
1440 ptr->global_worklist_id = -1;
1441 ptr->pcity = pcity;
1442
1445
1446 g_object_set(ptr->src_col, "visible", TRUE, NULL);
1447 g_object_set(ptr->dst_col, "visible", TRUE, NULL);
1448
1450
1452 g_signal_connect(dnd_src, "drag-begin", G_CALLBACK(drag_begin), ptr);
1453
1456}
1457
1458/************************************************************************/
1462 struct global_worklist *pgwl)
1463{
1464 struct worklist_data *ptr;
1465
1466 ptr = g_object_get_data(G_OBJECT(editor), "data");
1467
1469 ptr->pcity = nullptr;
1470
1473
1475 g_object_set(ptr->src_col, "visible", FALSE, NULL);
1476 g_object_set(ptr->dst_col, "visible", FALSE, NULL);
1477
1479}
1480
1481/************************************************************************/
1485{
1486 struct worklist_data *ptr;
1487 struct worklist queue;
1488 struct universal targets[MAX_NUM_PRODUCTION_TARGETS];
1489 int i, targets_used;
1490 struct item items[MAX_NUM_PRODUCTION_TARGETS];
1491 bool selected;
1492 gint id;
1493 GtkTreeIter it;
1494 GtkTreePath *path;
1495 GtkTreeModel *model;
1497
1498 ptr = g_object_get_data(G_OBJECT(editor), "data");
1499
1500 /* Refresh source tasks. */
1502 gtk_tree_model_get(GTK_TREE_MODEL(ptr->src), &it, 0, &id, -1);
1503 selected = TRUE;
1504 } else {
1505 selected = FALSE;
1506 }
1507
1508 /* These behave just right if ptr->pcity is NULL -> in case of global
1509 * worklist. */
1511 ptr->future);
1512 name_and_sort_items(targets, targets_used, items, FALSE, ptr->pcity);
1513
1514 /* Re-purpose existing items in the list store -- this avoids the
1515 * UI jumping around (especially as the set of source tasks doesn't
1516 * actually change much in practice). */
1517 model = GTK_TREE_MODEL(ptr->src);
1519
1520 path = NULL;
1521 for (i = 0; i < targets_used; i++) {
1522 char buf[8192];
1523
1524 if (!exists) {
1525 gtk_list_store_append(ptr->src, &it);
1526 }
1527
1528 gtk_list_store_set(ptr->src, &it, 0, (gint)cid_encode(items[i].item),
1529 1, production_help(&(items[i].item),
1530 buf, sizeof(buf)), -1);
1531
1532 if (selected && cid_encode(items[i].item) == id) {
1533 path = gtk_tree_model_get_path(GTK_TREE_MODEL(ptr->src), &it);
1534 }
1535
1536 if (exists) {
1537 exists = gtk_tree_model_iter_next(model, &it);
1538 }
1539 }
1540
1541 /* If the list got shorter, delete any excess items. */
1542 if (exists) {
1544 bool more;
1545
1546 do {
1547 it_next = it;
1548 more = gtk_tree_model_iter_next(model, &it_next);
1549
1550 gtk_list_store_remove(ptr->src, &it);
1551 it = it_next;
1552 } while (more);
1553 }
1554
1555 /* Select the same item that was previously selected, if any. */
1556 if (path) {
1558 gtk_tree_path_free(path);
1559 }
1560
1561 /* Refresh target worklist. */
1562 model = GTK_TREE_MODEL(ptr->dst);
1564
1565 /* Dance around worklist braindamage. */
1566 if (ptr->pcity != NULL) {
1567 city_get_queue(ptr->pcity, &queue);
1568 } else {
1569 const struct global_worklist *pgwl;
1570
1572
1573 fc_assert(NULL != pgwl);
1574
1576 }
1577
1578 for (i = 0; i < worklist_length(&queue); i++) {
1579 struct universal target = queue.entries[i];
1580 char buf[8192];
1581
1582 if (!exists) {
1583 gtk_list_store_append(ptr->dst, &it);
1584 }
1585
1586 gtk_list_store_set(ptr->dst, &it, 0, (gint)cid_encode(target),
1587 1, production_help(&target,
1588 buf, sizeof(buf)), -1);
1589
1590 if (exists) {
1591 exists = gtk_tree_model_iter_next(model, &it);
1592 }
1593 }
1594
1595 if (exists) {
1597 bool more;
1598
1599 do {
1600 it_next = it;
1601 more = gtk_tree_model_iter_next(model, &it_next);
1602
1603 gtk_list_store_remove(ptr->dst, &it);
1604 it = it_next;
1605 } while (more);
1606 }
1607
1608 create_wl_menu(ptr);
1609
1610 /* Update widget sensitivity. */
1611 if (ptr->pcity) {
1613 && city_owner(ptr->pcity) == client.conn.playing)) {
1615 } else {
1617 }
1618 } else {
1620 }
1621}
1622
1623/************************************************************************/
1626static void commit_worklist(struct worklist_data *ptr)
1627{
1628 struct worklist queue;
1629 GtkTreeModel *model;
1630 GtkTreeIter it;
1631 size_t i;
1632
1633 model = GTK_TREE_MODEL(ptr->dst);
1634
1635 worklist_init(&queue);
1636
1637 i = 0;
1638 if (gtk_tree_model_get_iter_first(model, &it)) {
1639 do {
1640 gint id;
1641 struct universal univ;
1642
1643 /* Oops, the player has a worklist longer than what we can store. */
1644 if (i >= MAX_LEN_WORKLIST) {
1645 break;
1646 }
1647
1648 gtk_tree_model_get(model, &it, 0, &id, -1);
1649 univ = cid_production(id);
1650 worklist_append(&queue, &univ);
1651
1652 i++;
1653 } while (gtk_tree_model_iter_next(model, &it));
1654 }
1655
1656 /* Dance around worklist braindamage. */
1657 if (ptr->pcity) {
1658 if (!city_set_queue(ptr->pcity, &queue)) {
1659 /* Failed to change worklist. This means worklist visible
1660 * on screen is not true. */
1662 }
1663 } else {
1664 struct global_worklist *pgwl;
1665
1667 if (pgwl) {
1668 global_worklist_set(pgwl, &queue);
1669 }
1670 }
1671}
#define city_owner(_pcity_)
Definition city.h:560
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:819
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:76
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:78
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:25
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
@ 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 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
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:3735
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:1395
static gboolean wl_right_button_up(GtkGestureClick *gesture, int n_press, double x, double y)
Definition wldlg.c:1076
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:1369
static gboolean drag_drop(GtkDropTarget *target, const GValue *value, double x, double y, gpointer data)
Definition wldlg.c:1102
#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:317
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:608
universals_u value
Definition fc_types.h:607
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:960
#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:2137
struct sprite * get_building_sprite(const struct tileset *t, const struct impr_type *pimprove)
Definition tilespec.c:7007
struct sprite * get_unittype_sprite(const struct tileset *t, const struct unit_type *punittype, enum unit_activity activity, enum direction8 facing)
Definition tilespec.c:7029
const struct unit_type * utype
Definition fc_types.h:553
const struct impr_type * building
Definition fc_types.h:546
const char * utype_name_translation(const struct unit_type *punittype)
Definition unittype.c:1566
#define unit_type_iterate(_p)
Definition unittype.h:862
#define unit_type_iterate_end
Definition unittype.h:869
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