1 /*
2 * gtkatlantic - the gtk+ monopd client, enjoy network monopoly games
3 *
4 *
5 * Copyright © 2002-2015 Sylvain Rochet
6 *
7 * gtkatlantic is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; see the file COPYING. If not, see
19 * <http://www.gnu.org/licenses/>.
20 */
21
22 #include "config.h"
23
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <unistd.h>
27 #include <string.h>
28
29 #include <gtk/gtk.h>
30
31 #include "global.h"
32 #include "trade.h"
33 #include "game.h"
34 #include "client.h"
35 #include "interface.h"
36 #include "callback.h"
37
38
trade_initnew(gint32 tradeid)39 void trade_initnew(gint32 tradeid) {
40
41 gint32 tradeslot;
42 gchar *sendstr;
43
44 /* already created */
45 if(get_trade_slot_with_tradeid(tradeid) >= 0) return;
46
47 if(! game_get_valid_trade_slot(&tradeslot) ) {
48
49 /* no trade slot valid -> reject trade */
50 sendstr = g_strdup_printf(".Tr%d\n", tradeid);
51 client_send(global->game_connect, sendstr);
52 g_free(sendstr);
53 return;
54 }
55
56 currentgame->trade[tradeslot].open = TRUE;
57 currentgame->trade[tradeslot].tradeid = tradeid;
58
59 trade_create_panel(tradeslot);
60 }
61
62
trade_destroy(gint32 tradeid)63 void trade_destroy(gint32 tradeid) {
64
65 gint32 tradeslot;
66
67 tradeslot = get_trade_slot_with_tradeid(tradeid);
68 if(tradeslot < 0) return;
69
70 trade_destroy_slot(tradeslot);
71 }
72
73
trade_destroy_slot(gint32 tradeslot)74 void trade_destroy_slot(gint32 tradeslot) {
75
76 if(!currentgame->trade[tradeslot].open) return;
77
78 gtk_widget_destroy(currentgame->trade[tradeslot].TradeWin);
79 memset(¤tgame->trade[tradeslot], 0, sizeof(_trade) );
80 }
81
82
trade_create_panel(gint32 tradeslot)83 void trade_create_panel(gint32 tradeslot) {
84
85 GtkWidget *TradeWin;
86 GtkWidget *VBox;
87 //components
88 GtkWidget *HBox;
89 GtkWidget *ScrollWinPlayer;
90 GtkWidget *PlayerList;
91 GtkWidget *VboxProposalButtons;
92 GtkWidget *ScrollWinProposal;
93 GtkWidget *ProposalList;
94 GtkWidget *HBox_buttons;
95
96 GtkWidget *Button;
97 GtkTreeSelection *select;
98 GtkCellRenderer *renderer;
99 GtkTreeViewColumn *column;
100 GtkListStore *store;
101
102 TradeWin = currentgame->trade[tradeslot].TradeWin = gtk_window_new(GTK_WINDOW_TOPLEVEL);
103 gtk_widget_set_size_request(TradeWin, 600, 220);
104 gtk_window_set_title(GTK_WINDOW(TradeWin), "GtkAtlantic: Trade");
105 g_object_set_data(G_OBJECT(TradeWin), "command", GINT_TO_POINTER(TRADE_ACTION_REJECT));
106 g_object_set_data(G_OBJECT(TradeWin), "tradeid", GINT_TO_POINTER(currentgame->trade[tradeslot].tradeid));
107 g_signal_connect(G_OBJECT(TradeWin), "delete_event", G_CALLBACK(CallBack_trade_button), NULL);
108
109 /* component / hbox / buttons */
110 VBox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
111 gtk_container_add(GTK_CONTAINER(TradeWin), VBox);
112
113 /* component */
114 currentgame->trade[tradeslot].FrameComponent = gtk_frame_new("Add Component");
115 gtk_container_set_border_width(GTK_CONTAINER(currentgame->trade[tradeslot].FrameComponent), BORDER);
116 gtk_box_pack_start(GTK_BOX(VBox), currentgame->trade[tradeslot].FrameComponent, FALSE, FALSE, 0);
117
118 trade_rebuild_component(tradeslot);
119 trade_rebuild_subcomponent(tradeslot);
120
121 /* player / current proposal */
122 HBox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, BORDER);
123 gtk_container_set_border_width(GTK_CONTAINER(HBox), BORDER);
124 gtk_box_pack_start(GTK_BOX(VBox), HBox, TRUE, TRUE, 0);
125
126 /* player list */
127 ScrollWinPlayer = gtk_scrolled_window_new(NULL, NULL);
128 gtk_widget_set_size_request(ScrollWinPlayer, 130, -1);
129 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(ScrollWinPlayer), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
130 gtk_box_pack_start(GTK_BOX(HBox), ScrollWinPlayer, FALSE, FALSE, 0);
131
132 PlayerList = currentgame->trade[tradeslot].PlayerList = gtk_tree_view_new();
133 gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(PlayerList), FALSE);
134 gtk_container_add(GTK_CONTAINER(ScrollWinPlayer), PlayerList);
135 select = gtk_tree_view_get_selection(GTK_TREE_VIEW(PlayerList));
136 gtk_tree_selection_set_mode(select, GTK_SELECTION_NONE);
137
138 renderer = gtk_cell_renderer_text_new();
139 column = gtk_tree_view_column_new_with_attributes("Player", renderer, "text", TRADEPLAYERLIST_COLUMN_NAME, "cell-background", TRADEPLAYERLIST_BGCOLOR_NAME, NULL);
140 gtk_tree_view_append_column(GTK_TREE_VIEW(PlayerList), column);
141
142 store = gtk_list_store_new(TRADEPLAYERLIST_COLUMN_NUM, G_TYPE_STRING, G_TYPE_STRING);
143 gtk_tree_view_set_model(GTK_TREE_VIEW(PlayerList), GTK_TREE_MODEL(store));
144 g_object_unref(store);
145
146
147 trade_rebuild_playerlist(tradeslot);
148 trade_rebuild_subcomponent(tradeslot);
149
150
151 /* vbox for proposal & buttons */
152 VboxProposalButtons = gtk_box_new(GTK_ORIENTATION_VERTICAL, BORDER);
153 gtk_box_pack_start(GTK_BOX(HBox), VboxProposalButtons, TRUE, TRUE, 0);
154
155 /* current proposal */
156 ScrollWinProposal = gtk_scrolled_window_new(NULL, NULL);
157 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(ScrollWinProposal), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
158 gtk_box_pack_start(GTK_BOX(VboxProposalButtons), ScrollWinProposal, TRUE, TRUE, 0);
159
160 ProposalList = currentgame->trade[tradeslot].ProposalList = gtk_tree_view_new();
161 gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(ProposalList), FALSE);
162 gtk_container_add(GTK_CONTAINER(ScrollWinProposal), ProposalList);
163 select = gtk_tree_view_get_selection(GTK_TREE_VIEW(ProposalList));
164 g_object_set_data(G_OBJECT(select), "tradeid", GINT_TO_POINTER(currentgame->trade[tradeslot].tradeid));
165 gtk_tree_selection_set_mode(select, GTK_SELECTION_SINGLE);
166 g_signal_connect(G_OBJECT(select), "changed", G_CALLBACK(Callback_ProposalList_Select), NULL);
167
168 renderer = gtk_cell_renderer_text_new();
169 column = gtk_tree_view_column_new_with_attributes("Type", renderer, "text", TRADEPROPOSALLIST_COLUMN_TYPE, NULL);
170 gtk_tree_view_append_column(GTK_TREE_VIEW(ProposalList), column);
171 column = gtk_tree_view_column_new_with_attributes("From", renderer, "text", TRADEPROPOSALLIST_COLUMN_FROM, NULL);
172 gtk_tree_view_append_column(GTK_TREE_VIEW(ProposalList), column);
173 column = gtk_tree_view_column_new_with_attributes("Gives", renderer, "text", TRADEPROPOSALLIST_COLUMN_GIVES, NULL);
174 gtk_tree_view_append_column(GTK_TREE_VIEW(ProposalList), column);
175 column = gtk_tree_view_column_new_with_attributes("To", renderer, "text", TRADEPROPOSALLIST_COLUMN_TO, NULL);
176 gtk_tree_view_append_column(GTK_TREE_VIEW(ProposalList), column);
177 column = gtk_tree_view_column_new_with_attributes("What", renderer, "text", TRADEPROPOSALLIST_COLUMN_WHAT, NULL);
178 gtk_tree_view_append_column(GTK_TREE_VIEW(ProposalList), column);
179
180
181 store = gtk_list_store_new(TRADEPROPOSALLIST_COLUMN_NUM, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_INT, G_TYPE_INT, G_TYPE_INT, G_TYPE_INT);
182 gtk_tree_view_set_model(GTK_TREE_VIEW(ProposalList), GTK_TREE_MODEL(store));
183 g_object_unref(store);
184
185 /* buttons */
186 HBox_buttons = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 10);
187 gtk_box_pack_end(GTK_BOX(VboxProposalButtons), HBox_buttons, FALSE, FALSE, 0);
188
189 /* remove button */
190 Button = gtk_button_new_with_label("Remove");
191 g_object_set_data(G_OBJECT(Button), "command", GINT_TO_POINTER(TRADE_ACTION_REMOVE));
192 g_object_set_data(G_OBJECT(Button), "tradeid", GINT_TO_POINTER(currentgame->trade[tradeslot].tradeid));
193 g_signal_connect(G_OBJECT(Button), "clicked", G_CALLBACK(CallBack_trade_button), NULL);
194 gtk_box_pack_start(GTK_BOX(HBox_buttons), Button, FALSE, FALSE, 0);
195
196 /* accept button */
197 Button = gtk_button_new_with_label("Accept");
198 g_object_set_data(G_OBJECT(Button), "command", GINT_TO_POINTER(TRADE_ACTION_ACCEPT));
199 g_object_set_data(G_OBJECT(Button), "tradeid", GINT_TO_POINTER(currentgame->trade[tradeslot].tradeid));
200 g_signal_connect(G_OBJECT(Button), "clicked", G_CALLBACK(CallBack_trade_button), NULL);
201 gtk_box_pack_end(GTK_BOX(HBox_buttons), Button, FALSE, FALSE, 0);
202
203 /* reject button */
204 Button = gtk_button_new_with_label("Reject");
205 g_object_set_data(G_OBJECT(Button), "command", GINT_TO_POINTER(TRADE_ACTION_REJECT));
206 g_object_set_data(G_OBJECT(Button), "tradeid", GINT_TO_POINTER(currentgame->trade[tradeslot].tradeid));
207 g_signal_connect(G_OBJECT(Button), "clicked", G_CALLBACK(CallBack_trade_button), NULL);
208 gtk_box_pack_end(GTK_BOX(HBox_buttons), Button, FALSE, FALSE, 0);
209
210 gtk_widget_show_all(TradeWin);
211 }
212
213
trade_rebuild_playerlist(gint32 tradeslot)214 void trade_rebuild_playerlist(gint32 tradeslot) {
215
216 GtkWidget *PlayerList;
217 gint32 i;
218 GtkListStore *store;
219
220 if(!currentgame->trade[tradeslot].open) return;
221
222 PlayerList = currentgame->trade[tradeslot].PlayerList;
223 if(!PlayerList) return;
224
225 store = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(PlayerList)));
226 gtk_list_store_clear(store);
227
228 for (i = 0; i < TRADE_MAX_PLAYER; i++) {
229 trade_player *p = ¤tgame->trade[tradeslot].player[i];
230 GtkTreeIter iter;
231 if (!p->player) continue;
232
233 gtk_list_store_append(store, &iter);
234 gtk_list_store_set(store, &iter,
235 TRADEPLAYERLIST_COLUMN_NAME, p->player->name,
236 TRADEPLAYERLIST_BGCOLOR_NAME, p->accept ? global->bg_green : global->bg_red,
237 -1);
238 }
239 }
240
241
trade_rebuild_component(gint32 tradeslot)242 void trade_rebuild_component(gint32 tradeslot) {
243
244 GtkWidget *box;
245 GtkWidget *Combo;
246
247 guint32 i;
248
249 currentgame->trade[tradeslot].current_component = TRADE_TYPE_MONEY;
250
251 if(currentgame->trade[tradeslot].ComponentBox) {
252 gtk_widget_destroy(currentgame->trade[tradeslot].ComponentBox);
253 currentgame->trade[tradeslot].ComponentBox = 0;
254 currentgame->trade[tradeslot].SubComponentBox = 0;
255 }
256
257 box = currentgame->trade[tradeslot].ComponentBox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 5);
258 gtk_container_set_border_width(GTK_CONTAINER(box), 5);
259 gtk_container_add(GTK_CONTAINER(currentgame->trade[tradeslot].FrameComponent), currentgame->trade[tradeslot].ComponentBox);
260
261 /* Choice component: Estate/Money/Card */
262 Combo = gtk_combo_box_text_new();
263 g_object_set_data(G_OBJECT(Combo), "tradeid", GINT_TO_POINTER(currentgame->trade[tradeslot].tradeid));
264 g_signal_connect(G_OBJECT(Combo), "changed", G_CALLBACK(CallBack_trade_sub_component), NULL);
265 gtk_box_pack_start(GTK_BOX(box), Combo, FALSE, FALSE, 0);
266
267 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(Combo), "Money");
268 gtk_combo_box_set_active(GTK_COMBO_BOX(Combo), 0);
269
270 for(i = 0 ; i < data->number_estates ; i++) {
271 if(currentgame->estate[i].owner <= 0) continue;
272
273 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(Combo), "Estate");
274 break;
275 }
276
277 for(i = 0 ; i < MAX_CARDS ; i++) {
278 if(!currentgame->card[i].owner) continue;
279
280 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(Combo), "Card");
281 break;
282 }
283
284 gtk_widget_show_all(currentgame->trade[tradeslot].ComponentBox);
285 }
286
287
trade_rebuild_subcomponent(gint32 tradeslot)288 void trade_rebuild_subcomponent(gint32 tradeslot) {
289
290 GtkWidget *box;
291 GtkWidget *Label;
292 GtkWidget *Entry;
293 GtkWidget *Combo;
294 GtkWidget *Button;
295
296 guint32 i;
297 player *p;
298
299 if(!currentgame->trade[tradeslot].ComponentBox) return;
300
301 if(currentgame->trade[tradeslot].SubComponentBox) {
302 gtk_widget_destroy(currentgame->trade[tradeslot].SubComponentBox);
303 currentgame->trade[tradeslot].SubComponentBox = 0;
304 }
305
306 box = currentgame->trade[tradeslot].SubComponentBox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, BORDER);
307 gtk_box_pack_start(GTK_BOX(currentgame->trade[tradeslot].ComponentBox), box, TRUE, TRUE, 0);
308
309 switch(currentgame->trade[tradeslot].current_component) {
310
311 case TRADE_TYPE_ESTATE:
312
313 /* update button */
314 Button = gtk_button_new_with_label("Update");
315 g_object_set_data(G_OBJECT(Button), "tradeid", GINT_TO_POINTER(currentgame->trade[tradeslot].tradeid));
316 g_signal_connect(G_OBJECT(Button), "clicked", G_CALLBACK(CallBack_trade_update_component), NULL);
317 gtk_widget_set_halign(Button, GTK_ALIGN_CENTER);
318 gtk_widget_set_valign(Button, GTK_ALIGN_CENTER);
319 gtk_box_pack_end(GTK_BOX(box), Button, FALSE, FALSE, 0);
320
321 /* valid estates */
322 Combo = gtk_combo_box_text_new();
323 g_object_set_data(G_OBJECT(Button), "name_estate", Combo);
324 gtk_widget_set_hexpand(Combo, TRUE);
325 gtk_box_pack_start(GTK_BOX(box), Combo, TRUE, TRUE, 0);
326
327 for(i = 0 ; i < data->number_estates ; i++) {
328
329 if(currentgame->estate[i].owner <= 0) continue;
330 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(Combo), currentgame->estate[i].name);
331 }
332
333 gtk_combo_box_set_active(GTK_COMBO_BOX(Combo), 0);
334
335 /* target label */
336 Label = gtk_label_new("Target");
337 gtk_box_pack_start(GTK_BOX(box), Label, FALSE, FALSE, 0);
338
339 /* valid target players */
340 Combo = gtk_combo_box_text_new();
341 g_object_set_data(G_OBJECT(Button), "name_target_player", Combo);
342 gtk_box_pack_start(GTK_BOX(box), Combo, FALSE, FALSE, 0);
343
344 for (p = player_h; p; p = p->next) {
345 if (p->spectator) continue;
346 if (p->game != currentgame->gameid) continue;
347 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(Combo), p->name);
348 }
349
350 gtk_combo_box_set_active(GTK_COMBO_BOX(Combo), 0);
351
352 break;
353
354
355 case TRADE_TYPE_MONEY:
356
357 /* update button */
358 Button = gtk_button_new_with_label("Update");
359 g_object_set_data(G_OBJECT(Button), "tradeid", GINT_TO_POINTER(currentgame->trade[tradeslot].tradeid));
360 g_signal_connect(G_OBJECT(Button), "clicked", G_CALLBACK(CallBack_trade_update_component), NULL);
361 gtk_widget_set_halign(Button, GTK_ALIGN_CENTER);
362 gtk_widget_set_valign(Button, GTK_ALIGN_CENTER);
363 gtk_box_pack_end(GTK_BOX(box), Button, FALSE, FALSE, 0);
364
365 /* amount of money */
366 Entry = gtk_entry_new();
367 gtk_widget_set_hexpand(Entry, TRUE);
368 g_object_set_data(G_OBJECT(Button), "amount_money", Entry);
369 gtk_box_pack_start(GTK_BOX(box), Entry, TRUE, TRUE, 0);
370
371 /* from label */
372 Label = gtk_label_new("From");
373 gtk_box_pack_start(GTK_BOX(box), Label, FALSE, FALSE, 0);
374
375 /* valid from players */
376 Combo = gtk_combo_box_text_new();
377 g_object_set_data(G_OBJECT(Button), "name_from_player", Combo);
378 gtk_box_pack_start(GTK_BOX(box), Combo, FALSE, FALSE, 0);
379
380 for (p = player_h; p; p = p->next) {
381 if (p->spectator) continue;
382 if (p->game != currentgame->gameid) continue;
383 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(Combo), p->name);
384
385 }
386
387 gtk_combo_box_set_active(GTK_COMBO_BOX(Combo), 0);
388
389 /* to label */
390 Label = gtk_label_new("To");
391 gtk_box_pack_start(GTK_BOX(box), Label, FALSE, FALSE, 0);
392
393 /* valid to players */
394 Combo = gtk_combo_box_text_new();
395 g_object_set_data(G_OBJECT(Button), "name_to_player", Combo);
396 gtk_box_pack_start(GTK_BOX(box), Combo, FALSE, FALSE, 0);
397
398 for (p = player_h; p; p = p->next) {
399 if (p->spectator) continue;
400 if (p->game != currentgame->gameid) continue;
401 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(Combo), p->name);
402 }
403 gtk_combo_box_set_active(GTK_COMBO_BOX(Combo), 0);
404
405 break;
406
407
408 case TRADE_TYPE_CARD:
409
410 /* update button */
411 Button = gtk_button_new_with_label("Update");
412 g_object_set_data(G_OBJECT(Button), "tradeid", GINT_TO_POINTER(currentgame->trade[tradeslot].tradeid));
413 g_signal_connect(G_OBJECT(Button), "clicked", G_CALLBACK(CallBack_trade_update_component), NULL);
414 gtk_widget_set_halign(Button, GTK_ALIGN_CENTER);
415 gtk_widget_set_valign(Button, GTK_ALIGN_CENTER);
416 gtk_box_pack_end(GTK_BOX(box), Button, FALSE, FALSE, 0);
417
418 /* valid cards */
419 Combo = gtk_combo_box_text_new();
420 g_object_set_data(G_OBJECT(Button), "name_card", Combo);
421 gtk_widget_set_hexpand(Combo, TRUE);
422 gtk_box_pack_start(GTK_BOX(box), Combo, TRUE, TRUE, 0);
423 for(i = 0 ; i < MAX_CARDS ; i++) {
424 gchar *tmp;
425
426 if(!currentgame->card[i].owner) continue;
427 tmp = g_strdup_printf("%d: %s", currentgame->card[i].cardid, currentgame->card[i].title);
428 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(Combo), tmp);
429 g_free(tmp);
430 }
431 gtk_combo_box_set_active(GTK_COMBO_BOX(Combo), 0);
432
433 /* target label */
434 Label = gtk_label_new("Target");
435 gtk_box_pack_start(GTK_BOX(box), Label, FALSE, FALSE, 0);
436
437 /* valid target players */
438 Combo = gtk_combo_box_text_new();
439 g_object_set_data(G_OBJECT(Button), "name_target_player", Combo);
440 gtk_box_pack_start(GTK_BOX(box), Combo, FALSE, FALSE, 0);
441
442 for (p = player_h; p; p = p->next) {
443 if (p->spectator) continue;
444 if (p->game != currentgame->gameid) continue;
445 gtk_combo_box_text_append_text(GTK_COMBO_BOX_TEXT(Combo), p->name);
446 }
447 gtk_combo_box_set_active(GTK_COMBO_BOX(Combo), 0);
448
449 break;
450 }
451
452 gtk_widget_show_all(currentgame->trade[tradeslot].SubComponentBox);
453 }
454
455
trade_update_revision(gint32 tradeid,gint32 revision)456 void trade_update_revision(gint32 tradeid, gint32 revision) {
457 gint32 tradeslot;
458
459 tradeslot = get_trade_slot_with_tradeid(tradeid);
460 if (tradeslot < 0) return;
461
462 currentgame->trade[tradeslot].revision = revision;
463 }
464
465
trade_update_player(gint32 tradeid,gint32 playerid,gboolean accept)466 void trade_update_player(gint32 tradeid, gint32 playerid, gboolean accept) {
467
468 gint32 tradeslot;
469 gint32 i;
470
471 tradeslot = get_trade_slot_with_tradeid(tradeid);
472 if (tradeslot < 0) return;
473
474 for (i = 0; i < TRADE_MAX_PLAYER; i++) {
475 trade_player *p = ¤tgame->trade[tradeslot].player[i];
476 if (!p->player) continue;
477 if ((gint32)p->player->playerid != playerid) continue;
478 p->accept = accept;
479 trade_rebuild_playerlist(tradeslot);
480 return;
481 }
482
483 /* new participating player */
484 for (i = 0; i < TRADE_MAX_PLAYER; i++) {
485 trade_player *p = ¤tgame->trade[tradeslot].player[i];
486 if (p->player) continue;
487 p->player = player_from_id(playerid);
488 p->accept = accept;
489 trade_rebuild_playerlist(tradeslot);
490 return;
491 }
492 }
493
494
trade_update_card(gint32 tradeid,gint32 cardid,gint32 targetplayer)495 void trade_update_card(gint32 tradeid, gint32 cardid, gint32 targetplayer) {
496
497 gint32 tradeslot;
498 GtkWidget *ProposalList;
499 player *from, *to;
500 gchar *cardname;
501 GtkListStore *store;
502 GtkTreeIter iter;
503 gboolean valid;
504
505 tradeslot = get_trade_slot_with_tradeid(tradeid);
506 if (tradeslot < 0) return;
507
508 ProposalList = currentgame->trade[tradeslot].ProposalList;
509 store = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(ProposalList)));
510
511 /* remove previous cardid */
512 valid = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(store), &iter);
513 while (valid) {
514 gint32 typeid, card;
515 GtkTreeIter curiter = iter;
516
517 valid = gtk_tree_model_iter_next(GTK_TREE_MODEL(store), &iter); /* get next iter so we can remove the current entry safely */
518 gtk_tree_model_get(GTK_TREE_MODEL(store), &curiter,
519 TRADEPROPOSALLIST_COLUMN_TYPE_ID, &typeid,
520 TRADEPROPOSALLIST_COLUMN_AUX_ID, &card,
521 -1);
522
523 if ( typeid == TRADE_TYPE_CARD && card == cardid ) {
524 gtk_list_store_remove(store, &curiter);
525 }
526 }
527
528 if (targetplayer < 0) {
529 return;
530 }
531
532 from = player_from_id(currentgame->card[get_card_slot_with_cardid(cardid)].owner);
533 if (!from) {
534 return;
535 }
536
537 to = player_from_id(targetplayer);
538 if (!to) {
539 return;
540 }
541
542 cardname = g_strdup_printf("card %d: %s", cardid, currentgame->card[ get_card_slot_with_cardid(cardid) ].title);
543
544 gtk_list_store_append(store, &iter);
545 gtk_list_store_set(store, &iter,
546 TRADEPROPOSALLIST_COLUMN_TYPE,"CARD:",
547 TRADEPROPOSALLIST_COLUMN_FROM, from->name,
548 TRADEPROPOSALLIST_COLUMN_GIVES, "gives",
549 TRADEPROPOSALLIST_COLUMN_TO, to->name,
550 TRADEPROPOSALLIST_COLUMN_WHAT, cardname,
551 TRADEPROPOSALLIST_COLUMN_TYPE_ID, TRADE_TYPE_CARD,
552 TRADEPROPOSALLIST_COLUMN_FROM_ID, currentgame->card[ get_card_slot_with_cardid(cardid) ].owner,
553 TRADEPROPOSALLIST_COLUMN_TO_ID, targetplayer,
554 TRADEPROPOSALLIST_COLUMN_AUX_ID, cardid,
555 -1);
556
557 g_free(cardname);
558 }
559
560
trade_update_estate(gint32 tradeid,gint32 estateid,gint32 targetplayer)561 void trade_update_estate(gint32 tradeid, gint32 estateid, gint32 targetplayer) {
562
563 gint32 tradeslot;
564 GtkWidget *ProposalList;
565 player *from, *to;
566 gchar *estatename;
567 GtkListStore *store;
568 GtkTreeIter iter;
569 gboolean valid;
570
571 tradeslot = get_trade_slot_with_tradeid(tradeid);
572 if (tradeslot < 0) return;
573
574 ProposalList = currentgame->trade[tradeslot].ProposalList;
575 estatename = currentgame->estate[estateid].name;
576 store = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(ProposalList)));
577
578 /* remove previous estate */
579 valid = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(store), &iter);
580 while (valid) {
581 gint32 typeid, estate;
582 GtkTreeIter curiter = iter;
583
584 valid = gtk_tree_model_iter_next(GTK_TREE_MODEL(store), &iter); /* get next iter so we can remove the current entry safely */
585 gtk_tree_model_get(GTK_TREE_MODEL(store), &curiter,
586 TRADEPROPOSALLIST_COLUMN_TYPE_ID, &typeid,
587 TRADEPROPOSALLIST_COLUMN_AUX_ID, &estate,
588 -1);
589
590 if ( typeid == TRADE_TYPE_ESTATE && estate == estateid ) {
591 gtk_list_store_remove(store, &curiter);
592 }
593 }
594
595 if (targetplayer < 0) {
596 return;
597 }
598
599 from = player_from_id(currentgame->estate[estateid].owner);
600 if (!from) {
601 return;
602 }
603
604 to = player_from_id(targetplayer);
605 if (!to) {
606 return;
607 }
608
609 gtk_list_store_append(store, &iter);
610 gtk_list_store_set(store, &iter,
611 TRADEPROPOSALLIST_COLUMN_TYPE,"ESTATE:",
612 TRADEPROPOSALLIST_COLUMN_FROM, from->name,
613 TRADEPROPOSALLIST_COLUMN_GIVES, "gives",
614 TRADEPROPOSALLIST_COLUMN_TO, to->name,
615 TRADEPROPOSALLIST_COLUMN_WHAT, estatename,
616 TRADEPROPOSALLIST_COLUMN_TYPE_ID, TRADE_TYPE_ESTATE,
617 TRADEPROPOSALLIST_COLUMN_FROM_ID, currentgame->estate[estateid].owner,
618 TRADEPROPOSALLIST_COLUMN_TO_ID, targetplayer,
619 TRADEPROPOSALLIST_COLUMN_AUX_ID, estateid,
620 -1);
621 }
622
623
trade_update_money(gint32 tradeid,gint32 playerfrom,gint32 playerto,gint32 money)624 void trade_update_money(gint32 tradeid, gint32 playerfrom, gint32 playerto, gint32 money) {
625
626 gint32 tradeslot;
627 GtkWidget *ProposalList;
628 player *from, *to;
629 gchar *moneystr;
630 GtkListStore *store;
631 GtkTreeIter iter;
632 gboolean valid;
633
634 tradeslot = get_trade_slot_with_tradeid(tradeid);
635 if (tradeslot < 0) return;
636
637 ProposalList = currentgame->trade[tradeslot].ProposalList;
638 store = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(ProposalList)));
639
640 /* remove all money proposal if same playerfrom and same playerto */
641 valid = gtk_tree_model_get_iter_first(GTK_TREE_MODEL(store), &iter);
642 while (valid) {
643 gint32 typeid, fromid, toid;
644 GtkTreeIter curiter = iter;
645
646 valid = gtk_tree_model_iter_next(GTK_TREE_MODEL(store), &iter); /* get next iter so we can remove the current entry safely */
647 gtk_tree_model_get(GTK_TREE_MODEL(store), &curiter,
648 TRADEPROPOSALLIST_COLUMN_TYPE_ID, &typeid,
649 TRADEPROPOSALLIST_COLUMN_FROM_ID, &fromid,
650 TRADEPROPOSALLIST_COLUMN_TO_ID, &toid,
651 -1);
652
653 if ( typeid == TRADE_TYPE_MONEY && fromid == playerfrom && toid == playerto ) {
654 gtk_list_store_remove(store, &curiter);
655 }
656 }
657
658 if (money <= 0) {
659 return;
660 }
661
662 from = player_from_id(playerfrom);
663 if (!from) {
664 return;
665 }
666
667 to = player_from_id(playerto);
668 if (!to) {
669 return;
670 }
671
672 moneystr = g_strdup_printf("%d money", money);
673
674 gtk_list_store_append(store, &iter);
675 gtk_list_store_set(store, &iter,
676 TRADEPROPOSALLIST_COLUMN_TYPE,"MONEY:",
677 TRADEPROPOSALLIST_COLUMN_FROM, from->name,
678 TRADEPROPOSALLIST_COLUMN_GIVES, "gives",
679 TRADEPROPOSALLIST_COLUMN_TO, to->name,
680 TRADEPROPOSALLIST_COLUMN_WHAT, moneystr,
681 TRADEPROPOSALLIST_COLUMN_TYPE_ID, TRADE_TYPE_MONEY,
682 TRADEPROPOSALLIST_COLUMN_FROM_ID, playerfrom,
683 TRADEPROPOSALLIST_COLUMN_TO_ID, playerto,
684 TRADEPROPOSALLIST_COLUMN_AUX_ID, 0,
685 -1);
686
687 g_free(moneystr);
688 }
689