Freeciv-3.1: /fast/freeciv/nightly/S3_1/client/gui-gtk-3.22/wldlg.c Source File

Freeciv-3.1

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-3.22 */
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
55 static GtkWidget *worklists_shell;
56 static GtkWidget *worklists_list;
57
58enum {
59 WORKLISTS_NEW,
60 WORKLISTS_DELETE,
61 WORKLISTS_PROPERTIES,
62 WORKLISTS_CLOSE
63};
64
65 static GtkListStore *worklists_store;
66
67 static int max_unit_height = -1, max_unit_width = -1;
68
69static void reset_global_worklist(GtkWidget *editor,
70 struct global_worklist *pgwl);
71static void popup_worklist(struct global_worklist *pgwl);
72static void popdown_worklist(struct global_worklist *pgwl);
73static void dst_row_callback(GtkTreeView *view, GtkTreePath *path,
74 GtkTreeViewColumn *col, gpointer data);
75
76/************************************************************************/
79 void blank_max_unit_size(void)
80{
81 max_unit_height = -1;
82 max_unit_width = -1;
83}
84
85/************************************************************************/
88 static void update_max_unit_size(void)
89{
90 max_unit_height = 0;
91 max_unit_width = 0;
92
93 unit_type_iterate(i) {
94 int x1, x2, y1, y2;
95 struct sprite *sprite = get_unittype_sprite(tileset, i,
96 direction8_invalid());
97
98 sprite_get_bounding_box(sprite, &x1, &y1, &x2, &y2);
99 max_unit_width = MAX(max_unit_width, x2 - x1);
100 max_unit_height = MAX(max_unit_height, y2 - y1);
101 } unit_type_iterate_end;
102}
103
104/************************************************************************/
107 static void worklists_destroy_callback(GtkWidget *w, gpointer data)
108{
109 worklists_shell = NULL;
110}
111
112/************************************************************************/
115 void update_worklist_report_dialog(void)
116{
117 GtkTreeIter it;
118
119 gtk_list_store_clear(worklists_store);
120 global_worklists_iterate(pgwl) {
121 gtk_list_store_append(worklists_store, &it);
122
123 gtk_list_store_set(worklists_store, &it,
124 0, global_worklist_name(pgwl),
125 1, global_worklist_id(pgwl),
126 -1);
127 } global_worklists_iterate_end;
128}
129
130/************************************************************************/
133 static void worklists_response(GtkWidget *w, gint response)
134{
135 struct global_worklist *pgwl;
136 int id;
137 GtkTreeSelection *selection;
138 GtkTreeModel *model;
139 GtkTreeIter it;
140
141 selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(worklists_list));
142
143 if (gtk_tree_selection_get_selected(selection, &model, &it)) {
144 gtk_tree_model_get(model, &it, 1, &id, -1);
145 pgwl = global_worklist_by_id(id);
146 } else {
147 pgwl = NULL;
148 id = -1;
149 }
150
151 switch (response) {
152 case WORKLISTS_NEW:
153 global_worklist_new(_("new"));
154 update_worklist_report_dialog();
155 return;
156
157 case WORKLISTS_DELETE:
158 if (!pgwl) {
159 return;
160 }
161
162 popdown_worklist(pgwl);
163 global_worklist_destroy(pgwl);
164 update_worklist_report_dialog();
165 return;
166
167 case WORKLISTS_PROPERTIES:
168 if (!pgwl) {
169 return;
170 }
171
172 popup_worklist(pgwl);
173 return;
174
175 default:
176 gtk_widget_destroy(worklists_shell);
177 return;
178 }
179}
180
181/************************************************************************/
184 static void cell_edited(GtkCellRendererText *cell,
185 const gchar *spath,
186 const gchar *text, gpointer data)
187{
188 GtkTreePath *path;
189 GtkTreeIter it;
190 struct global_worklist *pgwl;
191 int id;
192
193 path = gtk_tree_path_new_from_string(spath);
194 gtk_tree_model_get_iter(GTK_TREE_MODEL(worklists_store), &it, path);
195 gtk_tree_path_free(path);
196
197 gtk_tree_model_get(GTK_TREE_MODEL(worklists_store), &it, 1, &id, -1);
198 pgwl = global_worklist_by_id(id);
199
200 if (!pgwl) {
201 gtk_list_store_remove(worklists_store, &it);
202 return;
203 }
204
205 global_worklist_set_name(pgwl, text);
206 gtk_list_store_set(worklists_store, &it, 0, text, -1);
207}
208
209/************************************************************************/
212 static GtkWidget *create_worklists_report(void)
213{
214 GtkWidget *shell, *list;
215 GtkWidget *vbox, *label, *sw;
216 GtkCellRenderer *rend;
217
218 shell = gtk_dialog_new_with_buttons(_("Edit worklists"),
219 NULL,
220 0,
221 _("_New"),
222 WORKLISTS_NEW,
223 _("_Delete"),
224 WORKLISTS_DELETE,
225 _("_Properties"),
226 WORKLISTS_PROPERTIES,
227 _("_Close"),
228 WORKLISTS_CLOSE,
229 NULL);
230 setup_dialog(shell, toplevel);
231 gtk_window_set_position(GTK_WINDOW(shell), GTK_WIN_POS_MOUSE);
232
233 g_signal_connect(shell, "response",
234 G_CALLBACK(worklists_response), NULL);
235 g_signal_connect(shell, "destroy",
236 G_CALLBACK(worklists_destroy_callback), NULL);
237
238 vbox = gtk_grid_new();
239 gtk_grid_set_row_spacing(GTK_GRID(vbox), 2);
240 gtk_orientable_set_orientation(GTK_ORIENTABLE(vbox),
241 GTK_ORIENTATION_VERTICAL);
242 gtk_container_add(GTK_CONTAINER(gtk_dialog_get_content_area(GTK_DIALOG(shell))), vbox);
243
244 worklists_store = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_INT);
245
246 list = gtk_tree_view_new_with_model(GTK_TREE_MODEL(worklists_store));
247 gtk_widget_set_hexpand(list, TRUE);
248 gtk_widget_set_vexpand(list, TRUE);
249
250 g_object_unref(worklists_store);
251 gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(list), FALSE);
252
253 worklists_list = list;
254
255 rend = gtk_cell_renderer_text_new();
256 g_object_set(rend, "editable", TRUE, NULL);
257 g_signal_connect(rend, "edited",
258 G_CALLBACK(cell_edited), NULL);
259 gtk_tree_view_insert_column_with_attributes(GTK_TREE_VIEW(list), -1, NULL,
260 rend, "text", 0, NULL);
261
262 sw = gtk_scrolled_window_new(NULL, NULL);
263 gtk_scrolled_window_set_min_content_height(GTK_SCROLLED_WINDOW(sw), 200);
264 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(sw),
265 GTK_SHADOW_ETCHED_IN);
266 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw),
267 GTK_POLICY_NEVER, GTK_POLICY_ALWAYS);
268 gtk_container_add(GTK_CONTAINER(sw), list);
269
270 label = g_object_new(GTK_TYPE_LABEL,
271 "use-underline", TRUE,
272 "mnemonic-widget", list,
273 "label", _("_Worklists:"),
274 "xalign", 0.0, "yalign", 0.5, NULL);
275
276 gtk_container_add(GTK_CONTAINER(vbox), label);
277 gtk_container_add(GTK_CONTAINER(vbox), sw);
278 gtk_widget_show_all(vbox);
279
280 return shell;
281}
282
283/************************************************************************/
286 void popup_worklists_report(void)
287{
288 if (!worklists_shell) {
289 worklists_shell = create_worklists_report();
290
291 update_worklist_report_dialog();
292 }
293
294 gtk_window_present(GTK_WINDOW(worklists_shell));
295}
296
297
298
299
300/****************************************************************
301...
302*****************************************************************/
303struct worklist_data {
304 int global_worklist_id;
305 struct city *pcity;
306
307 GtkWidget *editor;
308
309 GtkListStore *src, *dst;
310 GtkWidget *src_view, *dst_view;
311 GtkTreeSelection *src_selection, *dst_selection;
312
313 GtkTreeViewColumn *src_col, *dst_col;
314
315 GtkWidget *add_cmd, *change_cmd, *help_cmd;
316 GtkWidget *up_cmd, *down_cmd, *prepend_cmd, *append_cmd, *remove_cmd;
317
318 bool future;
319};
320
321 static GHashTable *hash;
322
323static void commit_worklist(struct worklist_data *ptr);
324
325
326enum {
327 TARGET_GTK_TREE_MODEL_ROW
328};
329
330 static GtkTargetEntry wl_dnd_targets[] = {
331 { "GTK_TREE_MODEL_ROW", GTK_TARGET_SAME_APP, TARGET_GTK_TREE_MODEL_ROW },
332};
333
334
335/************************************************************************/
338 void add_worklist_dnd_target(GtkWidget *w)
339{
340 gtk_drag_dest_set(w, GTK_DEST_DEFAULT_ALL,
341 wl_dnd_targets, G_N_ELEMENTS(wl_dnd_targets),
342 GDK_ACTION_COPY);
343}
344
345/************************************************************************/
348 static GtkWidget *get_worklist(int global_worklist_id)
349{
350 if (hash) {
351 gpointer ret;
352
353 ret = g_hash_table_lookup(hash, GINT_TO_POINTER(global_worklist_id));
354 return ret;
355 } else {
356 return NULL;
357 }
358}
359
360/************************************************************************/
363 static void insert_worklist(int global_worklist_id, GtkWidget *editor)
364{
365 if (!hash) {
366 hash = g_hash_table_new(g_direct_hash, g_direct_equal);
367 }
368 g_hash_table_insert(hash, GINT_TO_POINTER(global_worklist_id), editor);
369}
370
371/************************************************************************/
374 static void delete_worklist(int global_worklist_id)
375{
376 if (hash) {
377 g_hash_table_remove(hash, GINT_TO_POINTER(global_worklist_id));
378 }
379}
380
381/************************************************************************/
384 static void popup_worklist(struct global_worklist *pgwl)
385{
386 GtkWidget *shell;
387
388 if (!(shell = get_worklist(global_worklist_id(pgwl)))) {
389 GtkWidget *editor;
390
391 shell = gtk_dialog_new_with_buttons(global_worklist_name(pgwl),
392 GTK_WINDOW(worklists_shell),
393 GTK_DIALOG_DESTROY_WITH_PARENT,
394 _("_Close"),
395 GTK_RESPONSE_CLOSE,
396 NULL);
397 gtk_window_set_role(GTK_WINDOW(shell), "worklist");
398 gtk_window_set_position(GTK_WINDOW(shell), GTK_WIN_POS_MOUSE);
399 g_signal_connect(shell, "response", G_CALLBACK(gtk_widget_destroy), NULL);
400 gtk_window_set_default_size(GTK_WINDOW(shell), 500, 400);
401
402 editor = create_worklist();
403 reset_global_worklist(editor, pgwl);
404 insert_worklist(global_worklist_id(pgwl), editor);
405
406 gtk_container_add(GTK_CONTAINER(gtk_dialog_get_content_area(GTK_DIALOG(shell))),
407 editor);
408 gtk_widget_show(editor);
409
410 refresh_worklist(editor);
411 }
412
413 gtk_window_present(GTK_WINDOW(shell));
414}
415
416/************************************************************************/
419 static void popdown_worklist(struct global_worklist *pgwl)
420{
421 GtkWidget *shell;
422
423 if ((shell = get_worklist(global_worklist_id(pgwl)))) {
424 GtkWidget *parent;
425
426 parent = gtk_widget_get_toplevel(shell);
427 gtk_widget_destroy(parent);
428 }
429}
430
431/************************************************************************/
434 static void worklist_destroy(GtkWidget *editor, gpointer data)
435{
436 struct worklist_data *ptr;
437
438 ptr = data;
439
440 if (ptr->global_worklist_id != -1) {
441 delete_worklist(ptr->global_worklist_id);
442 }
443
444 free(ptr);
445}
446
447/************************************************************************/
450 static void menu_item_callback(GtkMenuItem *item, struct worklist_data *ptr)
451{
452 struct global_worklist *pgwl;
453 const struct worklist *pwl;
454 size_t i;
455
456 if (NULL == client.conn.playing) {
457 return;
458 }
459
460 pgwl = global_worklist_by_id(GPOINTER_TO_INT
461 (g_object_get_data(G_OBJECT(item), "id")));
462 if (!pgwl) {
463 return;
464 }
465 pwl = global_worklist_get(pgwl);
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/************************************************************************/
486 static void popup_add_menu(GtkMenuShell *menu, gpointer data)
487{
488 GtkWidget *item;
489
490 gtk_container_foreach(GTK_CONTAINER(menu),
491 (GtkCallback) gtk_widget_destroy, NULL);
492
493 global_worklists_iterate(pgwl) {
494 item = gtk_menu_item_new_with_label(global_worklist_name(pgwl));
495 g_object_set_data(G_OBJECT(item), "id",
496 GINT_TO_POINTER(global_worklist_id(pgwl)));
497 gtk_widget_show(item);
498
499 gtk_container_add(GTK_CONTAINER(menu), item);
500 g_signal_connect(item, "activate",
501 G_CALLBACK(menu_item_callback), data);
502 } global_worklists_iterate_end;
503
504 item = gtk_separator_menu_item_new();
505 gtk_widget_show(item);
506
507 gtk_container_add(GTK_CONTAINER(menu), item);
508
509 item = gtk_menu_item_new_with_mnemonic(_("Edit Global _Worklists"));
510 gtk_widget_show(item);
511
512 gtk_container_add(GTK_CONTAINER(menu), item);
513 g_signal_connect(item, "activate",
514 G_CALLBACK(popup_worklists_report), NULL);
515}
516
517/************************************************************************/
520 static void help_callback(GtkWidget *w, gpointer data)
521{
522 struct worklist_data *ptr;
523 GtkTreeSelection *selection;
524 GtkTreeModel *model;
525 GtkTreeIter it;
526
527 ptr = data;
528 selection = ptr->src_selection;
529
530 if (gtk_tree_selection_get_selected(selection, &model, &it)) {
531 gint id;
532 struct universal target;
533
534 gtk_tree_model_get(model, &it, 0, &id, -1);
535 target = cid_decode(id);
536
537 if (VUT_UTYPE == target.kind) {
538 popup_help_dialog_typed(utype_name_translation(target.value.utype),
539 HELP_UNIT);
540 } else if (is_great_wonder(target.value.building)) {
541 popup_help_dialog_typed(improvement_name_translation(target.value.building),
542 HELP_WONDER);
543 } else {
544 popup_help_dialog_typed(improvement_name_translation(target.value.building),
545 HELP_IMPROVEMENT);
546 }
547 } else {
548 popup_help_dialog_string(HELP_WORKLIST_EDITOR_ITEM);
549 }
550}
551
552/************************************************************************/
555 static void change_callback(GtkWidget *w, gpointer data)
556{
557 struct worklist_data *ptr;
558 GtkTreeSelection *selection;
559 GtkTreeModel *model;
560 GtkTreeIter it;
561
562 ptr = data;
563 selection = ptr->src_selection;
564
565 if (gtk_tree_selection_get_selected(selection, &model, &it)) {
566 gint id;
567 struct universal univ;
568
569 gtk_tree_model_get(model, &it, 0, &id, -1);
570 univ = cid_production(id);
571 city_change_production(ptr->pcity, &univ);
572 }
573}
574
575/************************************************************************/
578 static void future_callback(GtkToggleButton *toggle, gpointer data)
579{
580 struct worklist_data *ptr;
581
582 ptr = data;
583 ptr->future = !ptr->future;
584
585 refresh_worklist(ptr->editor);
586}
587
588/************************************************************************/
591 static void queue_bubble_up(struct worklist_data *ptr)
592{
593 GtkTreePath *path;
594 GtkTreeViewColumn *col;
595 GtkTreeModel *model;
596
597 if (!gtk_widget_is_sensitive(ptr->dst_view)) {
598 return;
599 }
600
601 model = GTK_TREE_MODEL(ptr->dst);
602 gtk_tree_view_get_cursor(GTK_TREE_VIEW(ptr->dst_view), &path, &col);
603 if (path) {
604 GtkTreeIter it, it_prev;
605
606 if (gtk_tree_path_prev(path)) {
607 gtk_tree_model_get_iter(model, &it_prev, path);
608 it = it_prev;
609 gtk_tree_model_iter_next(model, &it);
610
611 gtk_list_store_swap(GTK_LIST_STORE(model), &it, &it_prev);
612
613 gtk_tree_view_set_cursor(GTK_TREE_VIEW(ptr->dst_view), path, col, FALSE);
614 commit_worklist(ptr);
615 }
616 }
617 gtk_tree_path_free(path);
618}
619
620/************************************************************************/
623 static void queue_remove(struct worklist_data *ptr)
624{
625 GtkTreePath *path;
626 GtkTreeViewColumn *col;
627
628 gtk_tree_view_get_cursor(GTK_TREE_VIEW(ptr->dst_view), &path, &col);
629 if (path) {
630 dst_row_callback(GTK_TREE_VIEW(ptr->dst_view), path, col, ptr);
631 gtk_tree_path_free(path);
632 }
633}
634
635/************************************************************************/
638 static void queue_bubble_down(struct worklist_data *ptr)
639{
640 GtkTreePath *path;
641 GtkTreeViewColumn *col;
642 GtkTreeModel *model;
643
644 if (!gtk_widget_is_sensitive(ptr->dst_view)) {
645 return;
646 }
647
648 model = GTK_TREE_MODEL(ptr->dst);
649 gtk_tree_view_get_cursor(GTK_TREE_VIEW(ptr->dst_view), &path, &col);
650 if (path) {
651 GtkTreeIter it, it_next;
652
653 gtk_tree_model_get_iter(model, &it, path);
654 it_next = it;
655 if (gtk_tree_model_iter_next(model, &it_next)) {
656 gtk_list_store_swap(GTK_LIST_STORE(model), &it, &it_next);
657
658 gtk_tree_path_next(path);
659 gtk_tree_view_set_cursor(GTK_TREE_VIEW(ptr->dst_view), path, col, FALSE);
660 commit_worklist(ptr);
661 }
662 }
663 gtk_tree_path_free(path);
664}
665
666/************************************************************************/
669 static void queue_insert(struct worklist_data *ptr, bool prepend)
670{
671 GtkTreeModel *model;
672 GtkTreeIter it;
673 GtkTreePath *path;
674
675 GtkTreeModel *src_model, *dst_model;
676 GtkTreeIter src_it, dst_it;
677 gint i, ncols;
678
679 if (!gtk_widget_is_sensitive(ptr->dst_view)) {
680 return;
681 }
682
683 if (!gtk_tree_selection_get_selected(ptr->src_selection, &model, &it)) {
684 return;
685 }
686
687 path = gtk_tree_model_get_path(model, &it);
688
689 src_model = GTK_TREE_MODEL(ptr->src);
690 dst_model = GTK_TREE_MODEL(ptr->dst);
691
692 gtk_tree_model_get_iter(src_model, &src_it, path);
693 if (prepend) {
694 gtk_list_store_prepend(GTK_LIST_STORE(dst_model), &dst_it);
695 } else {
696 gtk_list_store_append(GTK_LIST_STORE(dst_model), &dst_it);
697 }
698
699 ncols = gtk_tree_model_get_n_columns(src_model);
700
701 for (i = 0; i < ncols; i++) {
702 GValue value = { 0, };
703
704 gtk_tree_model_get_value(src_model, &src_it, i, &value);
705 gtk_list_store_set_value(GTK_LIST_STORE(dst_model), &dst_it, i, &value);
706 }
707 commit_worklist(ptr);
708
709 gtk_tree_path_free(path);
710}
711
712/************************************************************************/
715 static void queue_prepend(struct worklist_data *ptr)
716{
717 queue_insert(ptr, TRUE);
718}
719
720/************************************************************************/
723 static void queue_append(struct worklist_data *ptr)
724{
725 queue_insert(ptr, FALSE);
726}
727
728/************************************************************************/
731 static void src_row_callback(GtkTreeView *view, GtkTreePath *path,
732 GtkTreeViewColumn *col, gpointer data)
733{
734 struct worklist_data *ptr;
735 GtkTreeModel *src_model, *dst_model;
736 GtkTreeIter src_it, dst_it;
737 gint i, ncols;
738
739 ptr = data;
740
741 if (!gtk_widget_is_sensitive(ptr->dst_view)) {
742 return;
743 }
744
745 src_model = GTK_TREE_MODEL(ptr->src);
746 dst_model = GTK_TREE_MODEL(ptr->dst);
747
748 gtk_tree_model_get_iter(src_model, &src_it, path);
749 gtk_list_store_append(GTK_LIST_STORE(dst_model), &dst_it);
750
751 ncols = gtk_tree_model_get_n_columns(src_model);
752
753 for (i = 0; i < ncols; i++) {
754 GValue value = { 0, };
755
756 gtk_tree_model_get_value(src_model, &src_it, i, &value);
757 gtk_list_store_set_value(GTK_LIST_STORE(dst_model), &dst_it, i, &value);
758 }
759 commit_worklist(ptr);
760}
761
762/************************************************************************/
765 static void dst_row_callback(GtkTreeView *view, GtkTreePath *path,
766 GtkTreeViewColumn *col, gpointer data)
767{
768 struct worklist_data *ptr;
769 GtkTreeModel *dst_model;
770 GtkTreeIter it;
771
772 ptr = data;
773 dst_model = GTK_TREE_MODEL(ptr->dst);
774
775 gtk_tree_model_get_iter(dst_model, &it, path);
776
777 gtk_list_store_remove(GTK_LIST_STORE(dst_model), &it);
778 commit_worklist(ptr);
779}
780
781/************************************************************************/
784 static gboolean src_key_press_callback(GtkWidget *w, GdkEventKey *ev,
785 gpointer data)
786{
787 struct worklist_data *ptr;
788
789 ptr = data;
790
791 if (!gtk_widget_is_sensitive(ptr->dst_view)) {
792 return FALSE;
793 }
794
795 if ((ev->state & GDK_SHIFT_MASK) && ev->keyval == GDK_KEY_Insert) {
796 queue_prepend(ptr);
797 return TRUE;
798 } else if (ev->keyval == GDK_KEY_Insert) {
799 queue_append(ptr);
800 return TRUE;
801 } else {
802 return FALSE;
803 }
804}
805
806/************************************************************************/
809 static gboolean dst_key_press_callback(GtkWidget *w, GdkEventKey *ev,
810 gpointer data)
811{
812 GtkTreeModel *model;
813 struct worklist_data *ptr;
814
815 ptr = data;
816 model = GTK_TREE_MODEL(ptr->dst);
817
818 if (ev->keyval == GDK_KEY_Delete) {
819 GtkTreeIter it, it_next;
820 bool deleted = FALSE;
821
822 if (gtk_tree_model_get_iter_first(model, &it)) {
823 bool more;
824
825 do {
826 it_next = it;
827 more = gtk_tree_model_iter_next(model, &it_next);
828
829 if (gtk_tree_selection_iter_is_selected(ptr->dst_selection, &it)) {
830 gtk_list_store_remove(GTK_LIST_STORE(model), &it);
831 deleted = TRUE;
832 }
833 it = it_next;
834
835 } while (more);
836 }
837
838 if (deleted) {
839 commit_worklist(ptr);
840 }
841 return TRUE;
842
843 } else if ((ev->state & GDK_MOD1_MASK) && ev->keyval == GDK_KEY_Up) {
844 queue_bubble_up(ptr);
845 return TRUE;
846
847 } else if ((ev->state & GDK_MOD1_MASK) && ev->keyval == GDK_KEY_Down) {
848 queue_bubble_down(ptr);
849 return TRUE;
850
851 } else {
852 return FALSE;
853 }
854}
855
856/************************************************************************/
859 static void src_selection_callback(GtkTreeSelection *selection, gpointer data)
860{
861 struct worklist_data *ptr;
862
863 ptr = data;
864
865 /* update widget sensitivity. */
866 if (gtk_tree_selection_get_selected(selection, NULL, NULL)) {
867 if (can_client_issue_orders()
868 && (!ptr->pcity || city_owner(ptr->pcity) == client.conn.playing)) {
869 /* if ptr->pcity is NULL, this is a global worklist */
870 gtk_widget_set_sensitive(ptr->change_cmd, TRUE);
871 gtk_widget_set_sensitive(ptr->prepend_cmd, TRUE);
872 gtk_widget_set_sensitive(ptr->append_cmd, TRUE);
873 } else {
874 gtk_widget_set_sensitive(ptr->change_cmd, FALSE);
875 gtk_widget_set_sensitive(ptr->prepend_cmd, FALSE);
876 gtk_widget_set_sensitive(ptr->append_cmd, FALSE);
877 }
878 gtk_widget_set_sensitive(ptr->help_cmd, TRUE);
879 } else {
880 gtk_widget_set_sensitive(ptr->change_cmd, FALSE);
881 gtk_widget_set_sensitive(ptr->help_cmd, FALSE);
882 gtk_widget_set_sensitive(ptr->prepend_cmd, FALSE);
883 gtk_widget_set_sensitive(ptr->append_cmd, FALSE);
884 }
885}
886
887/************************************************************************/
890 static void dst_selection_callback(GtkTreeSelection *selection, gpointer data)
891{
892 struct worklist_data *ptr;
893
894 ptr = data;
895
896 /* update widget sensitivity. */
897 if (gtk_tree_selection_count_selected_rows(selection) > 0) {
898 int num_rows = 0;
899 GtkTreeIter it;
900
901 gtk_widget_set_sensitive(ptr->up_cmd, TRUE);
902 gtk_widget_set_sensitive(ptr->down_cmd, TRUE);
903 if (gtk_tree_model_get_iter_first(GTK_TREE_MODEL(ptr->dst), &it)) {
904 do {
905 num_rows++;
906 } while (gtk_tree_model_iter_next(GTK_TREE_MODEL(ptr->dst), &it));
907 }
908 if (num_rows > 1) {
909 gtk_widget_set_sensitive(ptr->remove_cmd, TRUE);
910 } else {
911 gtk_widget_set_sensitive(ptr->remove_cmd, FALSE);
912 }
913 } else {
914 gtk_widget_set_sensitive(ptr->up_cmd, FALSE);
915 gtk_widget_set_sensitive(ptr->down_cmd, FALSE);
916 gtk_widget_set_sensitive(ptr->remove_cmd, FALSE);
917 }
918}
919
920/************************************************************************/
923 static gboolean dst_dnd_callback(GtkWidget *w, GdkDragContext *context,
924 struct worklist_data *ptr)
925{
926 commit_worklist(ptr);
927 return FALSE;
928}
929
930/************************************************************************/
933 static void cell_render_func(GtkTreeViewColumn *col, GtkCellRenderer *rend,
934 GtkTreeModel *model, GtkTreeIter *it,
935 gpointer data)
936{
937 gint id;
938 struct universal target;
939
940 gtk_tree_model_get(model, it, 0, &id, -1);
941 target = cid_production(id);
942
943 if (GTK_IS_CELL_RENDERER_PIXBUF(rend)) {
944 GdkPixbuf *pix;
945 struct sprite *sprite;
946
947 if (VUT_UTYPE == target.kind) {
948 sprite = sprite_scale(get_unittype_sprite(tileset, target.value.utype,
949 direction8_invalid()),
950 max_unit_width, max_unit_height);
951 } else {
952 sprite = get_building_sprite(tileset, target.value.building);
953 }
954 pix = sprite_get_pixbuf(sprite);
955 g_object_set(rend, "pixbuf", pix, NULL);
956 g_object_unref(G_OBJECT(pix));
957 if (VUT_UTYPE == target.kind) {
958 free_sprite(sprite);
959 }
960 } else {
961 struct city **pcity = data;
962 gint column;
963 char *row[4];
964 char buf[4][64];
965 guint i;
966 gboolean useless;
967
968 for (i = 0; i < ARRAY_SIZE(row); i++) {
969 row[i] = buf[i];
970 }
971 column = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(rend), "column"));
972
973 get_city_dialog_production_row(row, sizeof(buf[0]), &target, *pcity);
974 g_object_set(rend, "text", row[column], NULL);
975
976 if (NULL != *pcity && VUT_IMPROVEMENT == target.kind) {
977 useless = is_improvement_redundant(*pcity, target.value.building);
978 /* Mark building redundant if we are really certain that there is
979 * no use for it. */
980 g_object_set(rend, "strikethrough", useless, NULL);
981 } else {
982 g_object_set(rend, "strikethrough", FALSE, NULL);
983 }
984 }
985}
986
987/************************************************************************/
990 static void populate_view(GtkTreeView *view, struct city **ppcity,
991 GtkTreeViewColumn **pcol)
992{
993 static const char *titles[] =
994 { N_("Type"), N_("Name"), N_("Info"), N_("Cost"), N_("Turns") };
995
996 static bool titles_done;
997 guint i;
998 GtkCellRenderer *rend;
999 GtkTreeViewColumn *col;
1000
1001 intl_slist(ARRAY_SIZE(titles), titles, &titles_done);
1002
1003 /* Case i == 0 taken out of the loop to workaround gcc-4.2.1 bug
1004 * https://gcc.gnu.org/PR33381
1005 * Some values would 'stick' from i == 0 round. */
1006 i = 0;
1007
1008 rend = gtk_cell_renderer_pixbuf_new();
1009
1010 gtk_tree_view_insert_column_with_data_func(view,
1011 i, titles[i], rend, cell_render_func, ppcity, NULL);
1012 col = gtk_tree_view_get_column(view, i);
1013
1014 if (GUI_GTK_OPTION(show_task_icons)) {
1015 if (max_unit_width == -1 || max_unit_height == -1) {
1016 update_max_unit_size();
1017 }
1018 } else {
1019 g_object_set(col, "visible", FALSE, NULL);
1020 }
1021 if (GUI_GTK_OPTION(show_task_icons)) {
1022 g_object_set(rend, "height", max_unit_height, NULL);
1023 }
1024
1025 for (i = 1; i < ARRAY_SIZE(titles); i++) {
1026 gint pos = i - 1;
1027
1028 rend = gtk_cell_renderer_text_new();
1029 g_object_set_data(G_OBJECT(rend), "column", GINT_TO_POINTER(pos));
1030
1031 gtk_tree_view_insert_column_with_data_func(view,
1032 i, titles[i], rend, cell_render_func, ppcity, NULL);
1033 col = gtk_tree_view_get_column(view, i);
1034
1035 if (pos >= 2) {
1036 g_object_set(G_OBJECT(rend), "xalign", 1.0, NULL);
1037 gtk_tree_view_column_set_alignment(col, 1.0);
1038 }
1039
1040 if (pos == 3) {
1041 *pcol = col;
1042 }
1043 if (GUI_GTK_OPTION(show_task_icons)) {
1044 g_object_set(rend, "height", max_unit_height, NULL);
1045 }
1046 }
1047}
1048
1049/************************************************************************/
1052GtkWidget *create_worklist(void)
1053{
1054 GtkWidget *editor, *table, *sw, *bbox;
1055 GtkWidget *src_view, *dst_view, *label, *button;
1056 GtkWidget *menubar, *item, *menu;
1057 GtkWidget *table2, *arrow, *check;
1058 GtkSizeGroup *group;
1059 GtkListStore *src_store, *dst_store;
1060 struct worklist_data *ptr;
1061
1062 ptr = fc_malloc(sizeof(*ptr));
1063
1064 src_store = gtk_list_store_new(2, G_TYPE_INT, G_TYPE_STRING);
1065 dst_store = gtk_list_store_new(2, G_TYPE_INT, G_TYPE_STRING);
1066
1067 ptr->global_worklist_id = -1;
1068 ptr->pcity = NULL;
1069 ptr->src = src_store;
1070 ptr->dst = dst_store;
1071 ptr->future = FALSE;
1072
1073 /* create shell. */
1074 editor = gtk_grid_new();
1075 gtk_grid_set_row_spacing(GTK_GRID(editor), 6);
1076 gtk_orientable_set_orientation(GTK_ORIENTABLE(editor),
1077 GTK_ORIENTATION_VERTICAL);
1078 g_signal_connect(editor, "destroy", G_CALLBACK(worklist_destroy), ptr);
1079 g_object_set_data(G_OBJECT(editor), "data", ptr);
1080
1081 ptr->editor = editor;
1082
1083 /* add source and target lists. */
1084 table = gtk_grid_new();
1085 gtk_container_add(GTK_CONTAINER(editor), table);
1086
1087 group = gtk_size_group_new(GTK_SIZE_GROUP_HORIZONTAL);
1088
1089 sw = gtk_scrolled_window_new(NULL, NULL);
1090 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(sw),
1091 GTK_SHADOW_ETCHED_IN);
1092 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw),
1093 GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
1094 gtk_grid_attach(GTK_GRID(table), sw, 3, 1, 2, 1);
1095
1096 src_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(src_store));
1097 gtk_widget_set_hexpand(src_view, TRUE);
1098 gtk_widget_set_vexpand(src_view, TRUE);
1099 g_object_unref(src_store);
1100 gtk_size_group_add_widget(group, src_view);
1101 gtk_widget_set_name(src_view, "small_font");
1102 gtk_tree_view_set_tooltip_column(GTK_TREE_VIEW(src_view), 1);
1103
1104 populate_view(GTK_TREE_VIEW(src_view), &ptr->pcity, &ptr->src_col);
1105 gtk_container_add(GTK_CONTAINER(sw), src_view);
1106
1107 label = g_object_new(GTK_TYPE_LABEL,
1108 "use-underline", TRUE,
1109 "mnemonic-widget", src_view,
1110 "label", _("Source _Tasks:"),
1111 "xalign", 0.0, "yalign", 0.5, NULL);
1112 gtk_grid_attach(GTK_GRID(table), label, 3, 0, 1, 1);
1113
1114 check = gtk_check_button_new_with_mnemonic(_("Show _Future Targets"));
1115 gtk_grid_attach(GTK_GRID(table), check, 4, 0, 1, 1);
1116 g_signal_connect(check, "toggled", G_CALLBACK(future_callback), ptr);
1117
1118 table2 = gtk_grid_new();
1119 gtk_grid_attach(GTK_GRID(table), table2, 2, 1, 1, 1);
1120
1121 button = gtk_button_new();
1122 gtk_widget_set_margin_top(button, 24);
1123 gtk_widget_set_margin_bottom(button, 24);
1124 ptr->prepend_cmd = button;
1125 gtk_button_set_relief(GTK_BUTTON(button), GTK_RELIEF_NONE);
1126 gtk_grid_attach(GTK_GRID(table2), button, 0, 0, 1, 1);
1127
1128 arrow = gtk_image_new_from_icon_name("pan-start-symbolic", GTK_ICON_SIZE_MENU);
1129 gtk_container_add(GTK_CONTAINER(button), arrow);
1130 g_signal_connect_swapped(button, "clicked",
1131 G_CALLBACK(queue_prepend), ptr);
1132 gtk_widget_set_sensitive(ptr->prepend_cmd, FALSE);
1133
1134 button = gtk_button_new();
1135 ptr->up_cmd = button;
1136 gtk_button_set_relief(GTK_BUTTON(button), GTK_RELIEF_NONE);
1137 gtk_grid_attach(GTK_GRID(table2), button, 0, 1, 1, 1);
1138
1139 arrow = gtk_image_new_from_icon_name("pan-up-symbolic", GTK_ICON_SIZE_MENU);
1140 gtk_container_add(GTK_CONTAINER(button), arrow);
1141 g_signal_connect_swapped(button, "clicked",
1142 G_CALLBACK(queue_bubble_up), ptr);
1143 gtk_widget_set_sensitive(ptr->up_cmd, FALSE);
1144
1145 button = gtk_button_new();
1146 ptr->down_cmd = button;
1147 gtk_button_set_relief(GTK_BUTTON(button), GTK_RELIEF_NONE);
1148 gtk_grid_attach(GTK_GRID(table2), button, 0, 2, 1, 1);
1149
1150 arrow = gtk_image_new_from_icon_name("pan-down-symbolic", GTK_ICON_SIZE_MENU);
1151 gtk_container_add(GTK_CONTAINER(button), arrow);
1152 g_signal_connect_swapped(button, "clicked",
1153 G_CALLBACK(queue_bubble_down), ptr);
1154 gtk_widget_set_sensitive(ptr->down_cmd, FALSE);
1155
1156 button = gtk_button_new();
1157 gtk_widget_set_margin_top(button, 24);
1158 gtk_widget_set_margin_bottom(button, 24);
1159 ptr->append_cmd = button;
1160 gtk_button_set_relief(GTK_BUTTON(button), GTK_RELIEF_NONE);
1161 gtk_grid_attach(GTK_GRID(table2), button, 0, 3, 1, 1);
1162
1163 arrow = gtk_image_new_from_icon_name("pan-start-symbolic", GTK_ICON_SIZE_MENU);
1164 gtk_container_add(GTK_CONTAINER(button), arrow);
1165 g_signal_connect_swapped(button, "clicked",
1166 G_CALLBACK(queue_append), ptr);
1167 gtk_widget_set_sensitive(ptr->append_cmd, FALSE);
1168
1169 button = gtk_button_new();
1170 gtk_widget_set_margin_top(button, 24);
1171 gtk_widget_set_margin_bottom(button, 24);
1172 ptr->remove_cmd = button;
1173 gtk_button_set_relief(GTK_BUTTON(button), GTK_RELIEF_NONE);
1174 gtk_grid_attach(GTK_GRID(table2), button, 0, 4, 1, 1);
1175
1176 arrow = gtk_image_new_from_icon_name("pan-end-symbolic", GTK_ICON_SIZE_MENU);
1177 gtk_container_add(GTK_CONTAINER(button), arrow);
1178 g_signal_connect_swapped(button, "clicked",
1179 G_CALLBACK(queue_remove), ptr);
1180 gtk_widget_set_sensitive(ptr->remove_cmd, FALSE);
1181
1182 sw = gtk_scrolled_window_new(NULL, NULL);
1183 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(sw),
1184 GTK_SHADOW_ETCHED_IN);
1185 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw),
1186 GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC);
1187 gtk_grid_attach(GTK_GRID(table), sw, 0, 1, 2, 1);
1188
1189 dst_view = gtk_tree_view_new_with_model(GTK_TREE_MODEL(dst_store));
1190 gtk_widget_set_hexpand(dst_view, TRUE);
1191 gtk_widget_set_vexpand(dst_view, TRUE);
1192 g_object_unref(dst_store);
1193 gtk_size_group_add_widget(group, dst_view);
1194 gtk_widget_set_name(dst_view, "small_font");
1195 gtk_tree_view_set_tooltip_column(GTK_TREE_VIEW(dst_view), 1);
1196
1197 populate_view(GTK_TREE_VIEW(dst_view), &ptr->pcity, &ptr->dst_col);
1198 gtk_container_add(GTK_CONTAINER(sw), dst_view);
1199
1200 label = g_object_new(GTK_TYPE_LABEL,
1201 "use-underline", TRUE,
1202 "mnemonic-widget", dst_view,
1203 "label", _("Target _Worklist:"),
1204 "xalign", 0.0, "yalign", 0.5, NULL);
1205 gtk_grid_attach(GTK_GRID(table), label, 0, 0, 1, 1);
1206
1207 /* add bottom menu and buttons. */
1208 bbox = gtk_button_box_new(GTK_ORIENTATION_HORIZONTAL);
1209 gtk_button_box_set_layout(GTK_BUTTON_BOX(bbox), GTK_BUTTONBOX_END);
1210 gtk_box_set_spacing(GTK_BOX(bbox), 10);
1211 gtk_container_add(GTK_CONTAINER(editor), bbox);
1212
1213 menubar = gtk_aux_menu_bar_new();
1214 gtk_container_add(GTK_CONTAINER(bbox), menubar);
1215 gtk_button_box_set_child_secondary(GTK_BUTTON_BOX(bbox), menubar, TRUE);
1216
1217 menu = gtk_menu_new();
1218
1219 item = gtk_menu_item_new_with_mnemonic(_("_Add Global Worklist"));
1220 gtk_menu_item_set_submenu(GTK_MENU_ITEM(item), menu);
1221 gtk_menu_shell_append(GTK_MENU_SHELL(menubar), item);
1222 g_signal_connect(menu, "show",
1223 G_CALLBACK(popup_add_menu), ptr);
1224 ptr->add_cmd = item;
1225 gtk_widget_set_sensitive(ptr->add_cmd, FALSE);
1226
1227 button = icon_label_button_new("help-browser", _("Help"));
1228 gtk_container_add(GTK_CONTAINER(bbox), button);
1229 g_signal_connect(button, "clicked",
1230 G_CALLBACK(help_callback), ptr);
1231 ptr->help_cmd = button;
1232 gtk_widget_set_sensitive(ptr->help_cmd, FALSE);
1233
1234 button = gtk_button_new_with_mnemonic(_("Change Prod_uction"));
1235 gtk_container_add(GTK_CONTAINER(bbox), button);
1236 g_signal_connect(button, "clicked",
1237 G_CALLBACK(change_callback), ptr);
1238 ptr->change_cmd = button;
1239 gtk_widget_set_sensitive(ptr->change_cmd, FALSE);
1240
1241 ptr->src_view = src_view;
1242 ptr->dst_view = dst_view;
1243 ptr->src_selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(src_view));
1244 ptr->dst_selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(dst_view));
1245 gtk_tree_selection_set_mode(ptr->dst_selection, GTK_SELECTION_MULTIPLE);
1246
1247 /* DND and other state changing callbacks. */
1248 gtk_tree_view_set_reorderable(GTK_TREE_VIEW(dst_view), TRUE);
1249 g_signal_connect(dst_view, "drag_end",
1250 G_CALLBACK(dst_dnd_callback), ptr);
1251
1252 g_signal_connect(src_view, "row_activated",
1253 G_CALLBACK(src_row_callback), ptr);
1254 g_signal_connect(src_view, "key_press_event",
1255 G_CALLBACK(src_key_press_callback), ptr);
1256
1257 g_signal_connect(dst_view, "row_activated",
1258 G_CALLBACK(dst_row_callback), ptr);
1259 g_signal_connect(dst_view, "key_press_event",
1260 G_CALLBACK(dst_key_press_callback), ptr);
1261
1262 g_signal_connect(ptr->src_selection, "changed",
1263 G_CALLBACK(src_selection_callback), ptr);
1264 g_signal_connect(ptr->dst_selection, "changed",
1265 G_CALLBACK(dst_selection_callback), ptr);
1266
1267
1268 gtk_widget_show_all(table);
1269 gtk_widget_show_all(bbox);
1270
1271 return editor;
1272}
1273
1274/************************************************************************/
1277 void reset_city_worklist(GtkWidget *editor, struct city *pcity)
1278{
1279 struct worklist_data *ptr;
1280
1281 ptr = g_object_get_data(G_OBJECT(editor), "data");
1282
1283 ptr->global_worklist_id = -1;
1284 ptr->pcity = pcity;
1285
1286 gtk_list_store_clear(ptr->src);
1287 gtk_list_store_clear(ptr->dst);
1288
1289 g_object_set(ptr->src_col, "visible", TRUE, NULL);
1290 g_object_set(ptr->dst_col, "visible", TRUE, NULL);
1291
1292 gtk_tree_view_enable_model_drag_source(GTK_TREE_VIEW(ptr->src_view),
1293 GDK_BUTTON1_MASK,
1294 wl_dnd_targets,
1295 G_N_ELEMENTS(wl_dnd_targets),
1296 GDK_ACTION_COPY);
1297}
1298
1299/************************************************************************/
1302 static void reset_global_worklist(GtkWidget *editor,
1303 struct global_worklist *pgwl)
1304{
1305 struct worklist_data *ptr;
1306
1307 ptr = g_object_get_data(G_OBJECT(editor), "data");
1308
1309 ptr->global_worklist_id = global_worklist_id(pgwl);
1310 ptr->pcity = NULL;
1311
1312 gtk_list_store_clear(ptr->src);
1313 gtk_list_store_clear(ptr->dst);
1314
1315 gtk_widget_hide(ptr->change_cmd);
1316 g_object_set(ptr->src_col, "visible", FALSE, NULL);
1317 g_object_set(ptr->dst_col, "visible", FALSE, NULL);
1318
1319 gtk_tree_view_unset_rows_drag_source(GTK_TREE_VIEW(ptr->src_view));
1320}
1321
1322/************************************************************************/
1325 void refresh_worklist(GtkWidget *editor)
1326{
1327 struct worklist_data *ptr;
1328 struct worklist queue;
1329 struct universal targets[MAX_NUM_PRODUCTION_TARGETS];
1330 int i, targets_used;
1331 struct item items[MAX_NUM_PRODUCTION_TARGETS];
1332 bool selected;
1333 gint id;
1334 GtkTreeIter it;
1335 GtkTreePath *path;
1336 GtkTreeModel *model;
1337 gboolean exists;
1338
1339 ptr = g_object_get_data(G_OBJECT(editor), "data");
1340
1341 /* refresh source tasks. */
1342 if (gtk_tree_selection_get_selected(ptr->src_selection, NULL, &it)) {
1343 gtk_tree_model_get(GTK_TREE_MODEL(ptr->src), &it, 0, &id, -1);
1344 selected = TRUE;
1345 } else {
1346 selected = FALSE;
1347 }
1348
1349 /* These behave just right if ptr->pcity is NULL -> in case of global
1350 * worklist. */
1351 targets_used = collect_eventually_buildable_targets(targets, ptr->pcity,
1352 ptr->future);
1353 name_and_sort_items(targets, targets_used, items, FALSE, ptr->pcity);
1354
1355 /* Re-purpose existing items in the list store -- this avoids the
1356 * UI jumping around (especially as the set of source tasks doesn't
1357 * actually change much in practice). */
1358 model = GTK_TREE_MODEL(ptr->src);
1359 exists = gtk_tree_model_get_iter_first(model, &it);
1360
1361 path = NULL;
1362 for (i = 0; i < targets_used; i++) {
1363 char buf[8192];
1364
1365 if (!exists) {
1366 gtk_list_store_append(ptr->src, &it);
1367 }
1368
1369 gtk_list_store_set(ptr->src, &it, 0, (gint)cid_encode(items[i].item),
1370 1, production_help(&(items[i].item),
1371 buf, sizeof(buf)), -1);
1372
1373 if (selected && cid_encode(items[i].item) == id) {
1374 path = gtk_tree_model_get_path(GTK_TREE_MODEL(ptr->src), &it);
1375 }
1376
1377 if (exists) {
1378 exists = gtk_tree_model_iter_next(model, &it);
1379 }
1380 }
1381
1382 /* If the list got shorter, delete any excess items. */
1383 if (exists) {
1384 GtkTreeIter it_next;
1385 bool more;
1386
1387 do {
1388 it_next = it;
1389 more = gtk_tree_model_iter_next(model, &it_next);
1390
1391 gtk_list_store_remove(ptr->src, &it);
1392 it = it_next;
1393 } while (more);
1394 }
1395
1396 /* Select the same item that was previously selected, if any. */
1397 if (path) {
1398 gtk_tree_view_set_cursor(GTK_TREE_VIEW(ptr->src_view), path, NULL, FALSE);
1399 gtk_tree_path_free(path);
1400 }
1401
1402 /* refresh target worklist. */
1403 model = GTK_TREE_MODEL(ptr->dst);
1404 exists = gtk_tree_model_get_iter_first(model, &it);
1405
1406 /* dance around worklist braindamage. */
1407 if (ptr->pcity != NULL) {
1408 city_get_queue(ptr->pcity, &queue);
1409 } else {
1410 const struct global_worklist *pgwl;
1411
1412 pgwl = global_worklist_by_id(ptr->global_worklist_id);
1413
1414 fc_assert(NULL != pgwl);
1415
1416 worklist_copy(&queue, global_worklist_get(pgwl));
1417 }
1418
1419 for (i = 0; i < worklist_length(&queue); i++) {
1420 struct universal target = queue.entries[i];
1421 char buf[8192];
1422
1423 if (!exists) {
1424 gtk_list_store_append(ptr->dst, &it);
1425 }
1426
1427 gtk_list_store_set(ptr->dst, &it, 0, (gint)cid_encode(target),
1428 1, production_help(&target,
1429 buf, sizeof(buf)), -1);
1430
1431 if (exists) {
1432 exists = gtk_tree_model_iter_next(model, &it);
1433 }
1434 }
1435
1436 if (exists) {
1437 GtkTreeIter it_next;
1438 bool more;
1439
1440 do {
1441 it_next = it;
1442 more = gtk_tree_model_iter_next(model, &it_next);
1443
1444 gtk_list_store_remove(ptr->dst, &it);
1445 it = it_next;
1446 } while (more);
1447 }
1448
1449 /* update widget sensitivity. */
1450 if (ptr->pcity) {
1451 if ((can_client_issue_orders()
1452 && city_owner(ptr->pcity) == client.conn.playing)) {
1453 gtk_widget_set_sensitive(ptr->add_cmd, TRUE);
1454 gtk_widget_set_sensitive(ptr->dst_view, TRUE);
1455 } else {
1456 gtk_widget_set_sensitive(ptr->add_cmd, FALSE);
1457 gtk_widget_set_sensitive(ptr->dst_view, FALSE);
1458 }
1459 } else {
1460 gtk_widget_set_sensitive(ptr->add_cmd, TRUE);
1461 gtk_widget_set_sensitive(ptr->dst_view, TRUE);
1462 }
1463}
1464
1465/************************************************************************/
1468 static void commit_worklist(struct worklist_data *ptr)
1469{
1470 struct worklist queue;
1471 GtkTreeModel *model;
1472 GtkTreeIter it;
1473 size_t i;
1474
1475 model = GTK_TREE_MODEL(ptr->dst);
1476
1477 worklist_init(&queue);
1478
1479 i = 0;
1480 if (gtk_tree_model_get_iter_first(model, &it)) {
1481 do {
1482 gint id;
1483 struct universal univ;
1484
1485 /* oops, the player has a worklist longer than what we can store. */
1486 if (i >= MAX_LEN_WORKLIST) {
1487 break;
1488 }
1489
1490 gtk_tree_model_get(model, &it, 0, &id, -1);
1491 univ = cid_production(id);
1492 worklist_append(&queue, &univ);
1493
1494 i++;
1495 } while (gtk_tree_model_iter_next(model, &it));
1496 }
1497
1498 /* dance around worklist braindamage. */
1499 if (ptr->pcity) {
1500 if (!city_set_queue(ptr->pcity, &queue)) {
1501 /* Failed to change worklist. This means worklist visible
1502 * on screen is not true. */
1503 refresh_worklist(ptr->editor);
1504 }
1505 } else {
1506 struct global_worklist *pgwl;
1507
1508 pgwl = global_worklist_by_id(ptr->global_worklist_id);
1509 if (pgwl) {
1510 global_worklist_set(pgwl, &queue);
1511 }
1512 }
1513}
city.h
city_owner
#define city_owner(_pcity_)
Definition city.h:543
get_city_dialog_production_row
void get_city_dialog_production_row(char *buf[], size_t column_size, struct universal *target, struct city *pcity)
Definition citydlg_common.c:364
city_set_queue
bool city_set_queue(struct city *pcity, const struct worklist *pqueue)
Definition citydlg_common.c:1459
city_change_production
int city_change_production(struct city *pcity, struct universal *target)
Definition citydlg_common.c:1261
city_get_queue
void city_get_queue(struct city *pcity, struct worklist *pqueue)
Definition citydlg_common.c:1442
citydlg_common.h
client
struct civclient client
Definition client_main.c:149
can_client_issue_orders
bool can_client_issue_orders(void)
Definition client_main.c:1265
client_main.h
collect_eventually_buildable_targets
int collect_eventually_buildable_targets(struct universal *targets, struct city *pcity, bool advanced_tech)
Definition climisc.c:802
name_and_sort_items
void name_and_sort_items(struct universal *targets, int num_targets, struct item *items, bool show_cost, struct city *pcity)
Definition climisc.c:633
cid_encode
cid cid_encode(struct universal target)
Definition climisc.c:475
cid_decode
struct universal cid_decode(cid id)
Definition climisc.c:518
climisc.h
MAX_NUM_PRODUCTION_TARGETS
#define MAX_NUM_PRODUCTION_TARGETS
Definition climisc.h:87
cid_production
#define cid_production
Definition climisc.h:71
cid
int cid
Definition climisc.h:31
list
static struct fc_sockaddr_list * list
Definition clinet.c:102
id
int int id
Definition editgui_g.h:28
editor
static struct editor_state * editor
Definition editor.c:100
fcintl.h
_
#define _(String)
Definition fcintl.h:67
N_
#define N_(String)
Definition fcintl.h:69
global_worklist_by_id
struct global_worklist * global_worklist_by_id(int id)
Definition global_worklist.c:298
global_worklist_set
bool global_worklist_set(struct global_worklist *pgwl, const struct worklist *pwl)
Definition global_worklist.c:263
global_worklist_name
const char * global_worklist_name(const struct global_worklist *pgwl)
Definition global_worklist.c:323
global_worklist_id
int global_worklist_id(const struct global_worklist *pgwl)
Definition global_worklist.c:288
global_worklist_destroy
void global_worklist_destroy(struct global_worklist *pgwl)
Definition global_worklist.c:214
global_worklist_get
const struct worklist * global_worklist_get(const struct global_worklist *pgwl)
Definition global_worklist.c:276
global_worklist_new
struct global_worklist * global_worklist_new(const char *name)
Definition global_worklist.c:244
global_worklist_set_name
void global_worklist_set_name(struct global_worklist *pgwl, const char *name)
Definition global_worklist.c:312
global_worklist.h
global_worklists_iterate
#define global_worklists_iterate(pgwl)
Definition global_worklist.h:65
global_worklists_iterate_end
#define global_worklists_iterate_end
Definition global_worklist.h:68
pos
static struct tile * pos
Definition finddlg.c:53
toplevel
GtkWidget * toplevel
Definition gui_main.c:124
GUI_GTK_OPTION
#define GUI_GTK_OPTION(optname)
Definition gui_main.h:25
gtk_aux_menu_bar_new
GtkWidget * gtk_aux_menu_bar_new(void)
Definition gui_stuff.c:249
setup_dialog
void setup_dialog(GtkWidget *shell, GtkWidget *parent)
Definition gui_stuff.c:281
intl_slist
void intl_slist(int n, const char **s, bool *done)
Definition gui_stuff.c:105
popup_help_dialog_string
void popup_help_dialog_string(const char *item)
Definition helpdlg.c:211
popup_help_dialog_typed
void popup_help_dialog_typed(const char *item, enum help_page_type htype)
Definition helpdlg.c:195
shell
static struct gui_dialog * shell
Definition messagedlg.c:39
free_sprite
void free_sprite(struct sprite *s)
Definition sprite.c:278
sprite_scale
struct sprite * sprite_scale(struct sprite *src, int new_w, int new_h)
Definition sprite.c:291
sprite_get_pixbuf
GdkPixbuf * sprite_get_pixbuf(struct sprite *sprite)
Definition sprite.c:402
sprite_get_bounding_box
void sprite_get_bounding_box(struct sprite *sprite, int *start_x, int *start_y, int *end_x, int *end_y)
Definition sprite.c:321
hash
static GHashTable * hash
Definition wldlg.c:320
dst_dnd_callback
static gboolean dst_dnd_callback(GtkWidget *w, GdkDragContext *context, struct worklist_data *ptr)
Definition wldlg.c:922
dst_selection_callback
static void dst_selection_callback(GtkTreeSelection *selection, gpointer data)
Definition wldlg.c:889
TARGET_GTK_TREE_MODEL_ROW
@ TARGET_GTK_TREE_MODEL_ROW
Definition wldlg.c:326
worklists_response
static void worklists_response(GtkWidget *w, gint response)
Definition wldlg.c:133
update_worklist_report_dialog
void update_worklist_report_dialog(void)
Definition wldlg.c:115
queue_remove
static void queue_remove(struct worklist_data *ptr)
Definition wldlg.c:622
get_worklist
static GtkWidget * get_worklist(int global_worklist_id)
Definition wldlg.c:347
reset_global_worklist
static void reset_global_worklist(GtkWidget *editor, struct global_worklist *pgwl)
Definition wldlg.c:1306
future_callback
static void future_callback(GtkToggleButton *toggle, gpointer data)
Definition wldlg.c:577
blank_max_unit_size
void blank_max_unit_size(void)
Definition wldlg.c:79
src_selection_callback
static void src_selection_callback(GtkTreeSelection *selection, gpointer data)
Definition wldlg.c:858
help_callback
static void help_callback(GtkWidget *w, gpointer data)
Definition wldlg.c:519
wl_dnd_targets
static GtkTargetEntry wl_dnd_targets[]
Definition wldlg.c:329
src_row_callback
static void src_row_callback(GtkTreeView *view, GtkTreePath *path, GtkTreeViewColumn *col, gpointer data)
Definition wldlg.c:730
dst_row_callback
static void dst_row_callback(GtkTreeView *view, GtkTreePath *path, GtkTreeViewColumn *col, gpointer data)
Definition wldlg.c:764
delete_worklist
static void delete_worklist(int global_worklist_id)
Definition wldlg.c:373
refresh_worklist
void refresh_worklist(GtkWidget *editor)
Definition wldlg.c:1329
add_worklist_dnd_target
void add_worklist_dnd_target(GtkWidget *w)
Definition wldlg.c:337
src_key_press_callback
static gboolean src_key_press_callback(GtkWidget *w, GdkEventKey *ev, gpointer data)
Definition wldlg.c:783
popdown_worklist
static void popdown_worklist(struct global_worklist *pgwl)
Definition wldlg.c:417
worklists_shell
static GtkWidget * worklists_shell
Definition wldlg.c:55
popup_worklist
static void popup_worklist(struct global_worklist *pgwl)
Definition wldlg.c:383
worklists_list
static GtkWidget * worklists_list
Definition wldlg.c:56
queue_bubble_up
static void queue_bubble_up(struct worklist_data *ptr)
Definition wldlg.c:590
create_worklists_report
static GtkWidget * create_worklists_report(void)
Definition wldlg.c:212
popup_add_menu
static void popup_add_menu(GtkMenuShell *menu, gpointer data)
Definition wldlg.c:485
cell_edited
static void cell_edited(GtkCellRendererText *cell, const gchar *spath, const gchar *text, gpointer data)
Definition wldlg.c:184
cell_render_func
static void cell_render_func(GtkTreeViewColumn *col, GtkCellRenderer *rend, GtkTreeModel *model, GtkTreeIter *it, gpointer data)
Definition wldlg.c:932
dst_key_press_callback
static gboolean dst_key_press_callback(GtkWidget *w, GdkEventKey *ev, gpointer data)
Definition wldlg.c:808
worklist_destroy
static void worklist_destroy(GtkWidget *editor, gpointer data)
Definition wldlg.c:432
worklists_destroy_callback
static void worklists_destroy_callback(GtkWidget *w, gpointer data)
Definition wldlg.c:107
change_callback
static void change_callback(GtkWidget *w, gpointer data)
Definition wldlg.c:554
WORKLISTS_NEW
@ WORKLISTS_NEW
Definition wldlg.c:59
WORKLISTS_CLOSE
@ WORKLISTS_CLOSE
Definition wldlg.c:62
WORKLISTS_DELETE
@ WORKLISTS_DELETE
Definition wldlg.c:60
WORKLISTS_PROPERTIES
@ WORKLISTS_PROPERTIES
Definition wldlg.c:61
reset_city_worklist
void reset_city_worklist(GtkWidget *editor, struct city *pcity)
Definition wldlg.c:1281
queue_insert
static void queue_insert(struct worklist_data *ptr, bool prepend)
Definition wldlg.c:668
menu_item_callback
static void menu_item_callback(GtkMenuItem *item, struct worklist_data *ptr)
Definition wldlg.c:448
populate_view
static void populate_view(GtkTreeView *view, struct city **ppcity, GtkTreeViewColumn **pcol)
Definition wldlg.c:991
insert_worklist
static void insert_worklist(int global_worklist_id, GtkWidget *editor)
Definition wldlg.c:362
queue_append
static void queue_append(struct worklist_data *ptr)
Definition wldlg.c:722
create_worklist
GtkWidget * create_worklist(void)
Definition wldlg.c:1054
commit_worklist
static void commit_worklist(struct worklist_data *ptr)
Definition wldlg.c:1472
queue_bubble_down
static void queue_bubble_down(struct worklist_data *ptr)
Definition wldlg.c:637
max_unit_width
static int max_unit_width
Definition wldlg.c:67
max_unit_height
static int max_unit_height
Definition wldlg.c:67
update_max_unit_size
static void update_max_unit_size(void)
Definition wldlg.c:88
queue_prepend
static void queue_prepend(struct worklist_data *ptr)
Definition wldlg.c:714
worklists_store
static GtkListStore * worklists_store
Definition wldlg.c:65
popup_worklists_report
void popup_worklists_report(void)
Definition wldlg.c:286
icon_label_button_new
GtkWidget * icon_label_button_new(const gchar *icon_name, const gchar *label_text)
Definition gui_stuff.c:76
gui_stuff.h
inputdlg.h
canvas.h
citydlg.h
graphics.h
gui_main.h
helpdlg.h
wldlg.h
HELP_WORKLIST_EDITOR_ITEM
#define HELP_WORKLIST_EDITOR_ITEM
HELP_IMPROVEMENT
@ HELP_IMPROVEMENT
Definition helpdlg_g.h:20
HELP_UNIT
@ HELP_UNIT
Definition helpdlg_g.h:20
HELP_WONDER
@ HELP_WONDER
Definition helpdlg_g.h:21
is_improvement_redundant
bool is_improvement_redundant(const struct city *pcity, const struct impr_type *pimprove)
Definition improvement.c:636
is_great_wonder
bool is_great_wonder(const struct impr_type *pimprove)
Definition improvement.c:767
improvement_name_translation
const char * improvement_name_translation(const struct impr_type *pimprove)
Definition improvement.c:241
log.h
fc_assert
#define fc_assert(condition)
Definition log.h:176
mem.h
fc_malloc
#define fc_malloc(sz)
Definition mem.h:34
options.h
packets.h
ARRAY_SIZE
#define ARRAY_SIZE(x)
Definition shared.h:85
MAX
#define MAX(x, y)
Definition shared.h:54
city
Definition city.h:309
civclient::conn
struct connection conn
Definition client_main.h:96
connection::playing
struct player * playing
Definition connection.h:156
global_worklist
Definition global_worklist.c:49
item
Definition climisc.h:80
sprite
Definition sprite.h:22
tileset
Definition tilespec.c:459
universal
Definition fc_types.h:756
universal::kind
enum universals_n kind
Definition fc_types.h:758
universal::value
universals_u value
Definition fc_types.h:757
view
Definition mapview_common.h:36
worklist_data
Definition wldlg.c:302
worklist_data::prepend_cmd
GtkWidget * prepend_cmd
Definition wldlg.c:315
worklist_data::group
GActionGroup * group
Definition wldlg.c:313
worklist_data::dst_view
GtkWidget * dst_view
Definition wldlg.c:309
worklist_data::dst_col
GtkTreeViewColumn * dst_col
Definition wldlg.c:312
worklist_data::dst_selection
GtkTreeSelection * dst_selection
Definition wldlg.c:310
worklist_data::src_view
GtkWidget * src_view
Definition wldlg.c:309
worklist_data::up_cmd
GtkWidget * up_cmd
Definition wldlg.c:315
worklist_data::future
bool future
Definition wldlg.c:317
worklist_data::src_selection
GtkTreeSelection * src_selection
Definition wldlg.c:310
worklist_data::src
GtkListStore * src
Definition wldlg.c:308
worklist_data::src_col
GtkTreeViewColumn * src_col
Definition wldlg.c:312
worklist_data::remove_cmd
GtkWidget * remove_cmd
Definition wldlg.c:315
worklist_data::dst
GtkListStore * dst
Definition wldlg.c:308
worklist_data::editor
GtkWidget * editor
Definition wldlg.c:306
worklist_data::global_worklist_id
int global_worklist_id
Definition wldlg.c:303
worklist_data::menu
GMenu * menu
Definition wldlg.c:311
worklist_data::append_cmd
GtkWidget * append_cmd
Definition wldlg.c:315
worklist_data::help_cmd
GtkWidget * help_cmd
Definition wldlg.c:314
worklist_data::pcity
struct city * pcity
Definition wldlg.c:304
worklist_data::down_cmd
GtkWidget * down_cmd
Definition wldlg.c:315
worklist_data::add_cmd
GtkWidget * add_cmd
Definition wldlg.c:314
worklist_data::change_cmd
GtkWidget * change_cmd
Definition wldlg.c:314
worklist
Definition worklist.h:28
worklist::entries
struct universal entries[MAX_LEN_WORKLIST]
Definition worklist.h:30
support.h
TRUE
#define TRUE
Definition support.h:46
FALSE
#define FALSE
Definition support.h:47
production_help
const char * production_help(const struct universal *uni, char *buf, size_t bufsize)
Definition text.c:2120
text.h
get_building_sprite
struct sprite * get_building_sprite(const struct tileset *t, const struct impr_type *pimprove)
Definition tilespec.c:6498
get_unittype_sprite
struct sprite * get_unittype_sprite(const struct tileset *t, const struct unit_type *punittype, enum direction8 facing)
Definition tilespec.c:6520
tilespec.h
universals_u::utype
const struct unit_type * utype
Definition fc_types.h:604
universals_u::building
const struct impr_type * building
Definition fc_types.h:598
utype_name_translation
const char * utype_name_translation(const struct unit_type *punittype)
Definition unittype.c:1612
unit_type_iterate
#define unit_type_iterate(_p)
Definition unittype.h:838
unit_type_iterate_end
#define unit_type_iterate_end
Definition unittype.h:845
worklist_copy
void worklist_copy(struct worklist *dst, const struct worklist *src)
Definition worklist.c:112
worklist_init
void worklist_init(struct worklist *pwl)
Definition worklist.c:38
worklist_append
bool worklist_append(struct worklist *pwl, const struct universal *prod)
Definition worklist.c:147
worklist_length
int worklist_length(const struct worklist *pwl)
Definition worklist.c:57
worklist.h
MAX_LEN_WORKLIST
#define MAX_LEN_WORKLIST
Definition worklist.h:24