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 // Qt
19 #include <QApplication>
20 #include <QCloseEvent>
21 #include <QGridLayout>
22 #include <QHeaderView>
23 #include <QLabel>
24 #include <QMenu>
25 #include <QSpinBox>
26 #include <QPainter>
27 #include <QPushButton>
28
29 // common
30 #include "government.h"
31 #include "player.h"
32
33 // client
34 #include "client_main.h"
35
36 // gui-qt
37 #include "colors.h"
38 #include "diplodlg.h"
39 #include "fc_client.h"
40 #include "sidebar.h"
41
42 extern "C" {
43 int client_player_number(void);
44 struct player *player_by_number(const int player_id);
45 }
46
47 typedef advance *p_advance;
48 typedef city *p_city;
49 extern QApplication *qapp;
50 /****************************************************************************
51 Constructor for diplomacy widget
52 ****************************************************************************/
diplo_wdg(int counterpart,int initiated_from)53 diplo_wdg::diplo_wdg(int counterpart, int initiated_from): QWidget()
54 {
55 color *colr;
56 QString text;
57 QString text2;
58 QString text_tooltip;
59 QLabel *plr1_label;
60 QLabel *plr2_label;
61 QLabel *label;
62 QLabel *label2;
63 QLabel *label3;
64 QLabel *label4;
65 QLabel *goldlab1;
66 QLabel *goldlab2;
67 QPushButton *add_clause1;
68 QPushButton *add_clause2;
69 QPixmap *pix = NULL;
70 QPalette palette;
71 struct sprite *sprite, *sprite2;
72 char plr_buf[4 * MAX_LEN_NAME];
73 const struct player_diplstate *state;
74 QHeaderView *header;
75 struct color *textcolors[2] = {
76 get_color(tileset, COLOR_MAPVIEW_CITYTEXT),
77 get_color(tileset, COLOR_MAPVIEW_CITYTEXT_DARK)
78 };
79 if (counterpart == initiated_from) {
80 initiated_from = client_player_number();
81 }
82 p1_accept = false;
83 p2_accept = false;
84 player1 = initiated_from;
85 player2 = counterpart;
86 layout = new QGridLayout;
87
88 init_treaty(&treaty, player_by_number(counterpart),
89 player_by_number(initiated_from));
90 state = player_diplstate_get(player_by_number(player1),
91 player_by_number(player2));
92 text_tooltip = QString(diplstate_type_translated_name(state->type));
93 if (state->turns_left > 0) {
94 text_tooltip = text_tooltip + " (";
95 text_tooltip = text_tooltip + QString(PL_("%1 turn left",
96 "%1 turns left",
97 state->turns_left))
98 .arg(state->turns_left);
99 text_tooltip = text_tooltip + ")";
100 }
101 label3 = new QLabel;
102 text = "<b><h3><center>"
103 + QString(nation_plural_for_player(player_by_number(initiated_from)))
104 .toHtmlEscaped()
105 + "</center></h3></b>";
106 colr = get_player_color(tileset, player_by_number(initiated_from));
107 text = "<style>h3{background-color: "
108 + colr->qcolor.name() + ";" + "color: " + color_best_contrast(colr,
109 textcolors, ARRAY_SIZE(textcolors))->qcolor.name()
110 + "}</style>" + text;
111 label3->setText(text);
112 label3->setMinimumWidth(300);
113 label4 = new QLabel;
114 text = "<b><h3><center>"
115 + QString(nation_plural_for_player(player_by_number(counterpart)))
116 .toHtmlEscaped()
117 + "</center></h3></b></body>";
118 colr = get_player_color(tileset, player_by_number(counterpart));
119 text = "<style>h3{background-color: "
120 + colr->qcolor.name() + ";" + "color: " + color_best_contrast(colr,
121 textcolors, ARRAY_SIZE(textcolors))->qcolor.name()
122 + "}</style>" + text;
123 label4->setMinimumWidth(300);
124 label4->setText(text);
125 layout->addWidget(label3, 0, 5);
126 layout->addWidget(label4, 5, 5);
127 plr1_label = new QLabel;
128 label = new QLabel;
129 sprite = get_nation_flag_sprite(tileset,
130 nation_of_player(player_by_number
131 (initiated_from)));
132 if (sprite != NULL) {
133 pix = sprite->pm;
134 plr1_label->setPixmap(*pix);
135 } else {
136 plr1_label->setText("FLAG MISSING");
137 }
138 text = ruler_title_for_player(player_by_number(initiated_from),
139 plr_buf, sizeof(plr_buf));
140 text = "<b><center>" + text.toHtmlEscaped() + "</center></b>";
141 label->setText(text);
142 plr1_accept = new QLabel;
143 layout->addWidget(plr1_label, 1, 0);
144 layout->addWidget(label, 1, 5);
145 layout->addWidget(plr1_accept, 1, 10);
146 label2 = new QLabel;
147 sprite2 = get_nation_flag_sprite(tileset,
148 nation_of_player(player_by_number
149 (counterpart)));
150 plr2_label = new QLabel;
151 if (sprite2 != NULL) {
152 pix = sprite2->pm;
153 plr2_label->setPixmap(*pix);
154 } else {
155 plr2_label->setText("FLAG MISSING");
156 }
157 text2 = ruler_title_for_player(player_by_number(counterpart),
158 plr_buf, sizeof(plr_buf));
159 text2 = "<b><center>" + text2.toHtmlEscaped() + "</center></b>";
160 label2->setText(text2);
161 plr2_accept = new QLabel;
162 layout->addWidget(plr2_label, 6, 0);
163 layout->addWidget(label2, 6, 5);
164 layout->addWidget(plr2_accept, 6, 10);
165 goldlab1 = new QLabel(_("Gold:"));
166 goldlab1->setAlignment(Qt::AlignRight);
167 goldlab2 = new QLabel(_("Gold:"));
168 goldlab2->setAlignment(Qt::AlignRight);
169 gold_edit1 = new QSpinBox;
170 gold_edit2 = new QSpinBox;
171 gold_edit1->setMinimum(0);
172 gold_edit2->setMinimum(0);
173 gold_edit1->setFocusPolicy(Qt::ClickFocus);
174 gold_edit2->setFocusPolicy(Qt::ClickFocus);
175 if (game.info.trading_gold) {
176 gold_edit2->setMaximum(player_by_number(player1)->economic.gold);
177 gold_edit1->setMaximum(player_by_number(player2)->economic.gold);
178 }
179 connect(gold_edit1, SIGNAL(valueChanged(int)), SLOT(gold_changed1(int)));
180 connect(gold_edit2, SIGNAL(valueChanged(int)), SLOT(gold_changed2(int)));
181 add_clause1 = new QPushButton(style()->standardIcon(QStyle::SP_ArrowRight),
182 _("Add Clause..."));
183 add_clause2 = new QPushButton(style()->standardIcon(QStyle::SP_ArrowRight),
184 _("Add Clause..."));
185 add_clause1->setFocusPolicy(Qt::ClickFocus);
186 add_clause2->setFocusPolicy(Qt::ClickFocus);
187 connect(add_clause1, &QAbstractButton::clicked, this, &diplo_wdg::show_menu_p2);
188 connect(add_clause2, &QAbstractButton::clicked, this, &diplo_wdg::show_menu_p1);
189 layout->addWidget(goldlab1, 7, 4);
190 layout->addWidget(goldlab2, 3, 4);
191 layout->addWidget(gold_edit1, 7, 5);
192 layout->addWidget(gold_edit2, 3, 5);
193 layout->addWidget(add_clause1, 7, 6);
194 layout->addWidget(add_clause2, 3, 6);
195
196 text_edit = new QTableWidget();
197 text_edit->setColumnCount(1);
198 text_edit->setProperty("showGrid", "false");
199 text_edit->setProperty("selectionBehavior", "SelectRows");
200 text_edit->setEditTriggers(QAbstractItemView::NoEditTriggers);
201 text_edit->verticalHeader()->setVisible(false);
202 text_edit->horizontalHeader()->setVisible(false);
203 text_edit->setSelectionMode(QAbstractItemView::SingleSelection);
204 text_edit->setFocusPolicy(Qt::NoFocus);
205 header = text_edit->horizontalHeader();
206 header->setStretchLastSection(true);
207 connect(text_edit, &QTableWidget::itemDoubleClicked,
208 this, &diplo_wdg::dbl_click);
209 text_edit->clearContents();
210 text_edit->setRowCount(0);
211 layout->addWidget(text_edit, 9, 0, 8, 11);
212 accept_treaty =
213 new QPushButton(style()->standardIcon(QStyle::SP_DialogYesButton),
214 _("Accept treaty"));
215 cancel_treaty =
216 new QPushButton(style()->standardIcon(QStyle::SP_DialogNoButton),
217 _("Cancel meeting"));
218 connect(accept_treaty, &QAbstractButton::clicked, this, &diplo_wdg::response_accept);
219 connect(cancel_treaty, &QAbstractButton::clicked, this, &diplo_wdg::response_cancel);
220 layout->addWidget(accept_treaty, 17, 5);
221 layout->addWidget(cancel_treaty, 17, 6);
222
223 if (client_player_number() != counterpart) {
224 label4->setToolTip(text_tooltip);
225 plr2_label->setToolTip(text_tooltip);
226 }
227 if (client_player_number() != initiated_from) {
228 label3->setToolTip(text_tooltip);
229 plr1_label->setToolTip(text_tooltip);
230 }
231
232 accept_treaty->setAutoDefault(true);
233 accept_treaty->setDefault(true);
234 cancel_treaty->setAutoDefault(true);
235 setLayout(layout);
236 update_wdg();
237
238 }
239
240 /****************************************************************************
241 Destructor for diplomacy widget
242 ****************************************************************************/
~diplo_wdg()243 diplo_wdg::~diplo_wdg()
244 {
245 }
246
247 /****************************************************************************
248 Double click on treaty list - it removes clicked clause from list
249 ****************************************************************************/
dbl_click(QTableWidgetItem * item)250 void diplo_wdg::dbl_click(QTableWidgetItem *item)
251 {
252 int i, r;
253
254 r = item->row();
255 i = 0;
256 clause_list_iterate(treaty.clauses, pclause) {
257 if (i == r) {
258 dsend_packet_diplomacy_remove_clause_req(&client.conn,
259 player_number(treaty.plr0),
260 player_number(pclause->from),
261 pclause->type,
262 pclause->value);
263 return;
264 }
265 i++;
266 } clause_list_iterate_end;
267 }
268
269 /****************************************************************************
270 Received event about diplomacy widget being closed
271 ****************************************************************************/
closeEvent(QCloseEvent * event)272 void diplo_wdg::closeEvent(QCloseEvent *event)
273 {
274 if (C_S_RUNNING == client_state()) {
275 response_cancel();
276 }
277 event->accept();
278 }
279
280 /****************************************************************************
281 Gold changed on first spinner
282 ****************************************************************************/
gold_changed1(int val)283 void diplo_wdg::gold_changed1(int val)
284 {
285 dsend_packet_diplomacy_create_clause_req(&client.conn,
286 player2, player2,
287 CLAUSE_GOLD, val);
288 }
289
290 /****************************************************************************
291 Gold changed on second spinner
292 ****************************************************************************/
gold_changed2(int val)293 void diplo_wdg::gold_changed2(int val)
294 {
295 dsend_packet_diplomacy_create_clause_req(&client.conn,
296 player2, player1,
297 CLAUSE_GOLD, val);
298 }
299
300 /****************************************************************************
301 Shows popup menu with available clauses to create
302 ****************************************************************************/
show_menu(int player)303 void diplo_wdg::show_menu(int player)
304 {
305 int city_num;
306 int other_player;
307 struct player *pgiver, *pother;
308 const struct advance *padv;
309 enum diplstate_type ds;
310 QAction *action_menu;
311 QAction *all_advancs;
312 QAction *some_action;
313 QAction *world_map, *sea_map;
314 QMap <QString, int>city_list;
315 QMap <QString, int>::const_iterator city_iter;
316 QMap <QString, p_advance> adv_list;
317 QMap <QString, p_advance>::const_iterator adv_iter;
318 QMenu *map_menu, *adv_menu, *city_menu, *pacts_menu;
319 QMenu menu(this);
320 QVariant qvar, tech_var, city_var;
321
322 curr_player = player;
323 if (curr_player == player1) {
324 other_player = player2;
325 } else {
326 other_player = player1;
327 }
328 pgiver = player_by_number(player);
329 pother = player_by_number(other_player);
330
331 /* Maps */
332 map_menu = menu.addMenu(_("Maps"));
333 world_map = new QAction(_("World-map"), this);
334 connect(world_map, &QAction::triggered, this, &diplo_wdg::world_map_clause);
335 map_menu->addAction(world_map);
336 sea_map = new QAction(_("Sea-map"), this);
337 connect(sea_map, &QAction::triggered, this, &diplo_wdg::sea_map_clause);
338 map_menu->addAction(sea_map);
339
340 /* Trading: advances */
341 if (game.info.trading_tech) {
342 const struct research *gresearch = research_get(pgiver);
343 const struct research *oresearch = research_get(pother);
344 adv_menu = menu.addMenu(_("Advances"));
345 advance_iterate(A_FIRST, padvance) {
346 Tech_type_id i = advance_number(padvance);
347
348 if (research_invention_state(gresearch, i) == TECH_KNOWN
349 && research_invention_gettable(oresearch, i,
350 game.info.tech_trade_allow_holes)
351 && (research_invention_state(oresearch, i) == TECH_UNKNOWN
352 || research_invention_state(oresearch, i)
353 == TECH_PREREQS_KNOWN)) {
354 adv_list.insert(advance_name_translation(padvance), padvance);
355 }
356 } advance_iterate_end;
357
358 /* All advances */
359 all_advancs = new QAction(_("All advances"), this);
360 connect(all_advancs, &QAction::triggered, this, &diplo_wdg::all_advances);
361 adv_menu->addAction(all_advancs);
362 adv_menu->addSeparator();
363
364 /* QMap is sorted by default when iterating */
365 adv_iter = adv_list.constBegin();
366 if (adv_list.count() > 0) {
367 while (adv_iter != adv_list.constEnd()) {
368 some_action = adv_menu->addAction(adv_iter.key());
369 qvar = QVariant::fromValue((void *) adv_iter.value());
370 some_action->setData(qvar);
371 some_action->setProperty("TECH", 1);
372 some_action->setProperty("CITY", 0);
373 adv_iter++;
374 }
375 } else {
376 adv_menu->setDisabled(true);
377 }
378
379 }
380
381 /* Trading: cities. */
382 if (game.info.trading_city) {
383 city_menu = menu.addMenu(_("Cities"));
384
385 city_list_iterate(pgiver->cities, pcity) {
386 if (!is_capital(pcity)) {
387 city_list.insert(pcity->name, pcity->id);
388 }
389 } city_list_iterate_end;
390 city_iter = city_list.constBegin();
391 if (city_list.count() > 0) {
392 while (city_iter != city_list.constEnd()) {
393 some_action = city_menu->addAction(city_iter.key());
394 some_action->setData(city_iter.value());
395 some_action->setProperty("TECH", 0);
396 some_action->setProperty("CITY", 1);
397 city_iter++;
398 }
399 } else {
400 city_menu->setDisabled(true);
401 }
402 }
403 some_action = new QAction(_("Give shared vision"), this);
404 connect(some_action, &QAction::triggered, this,
405 &diplo_wdg::give_shared_vision);
406 menu.addAction(some_action);
407 if (gives_shared_vision(pgiver, pother)) {
408 some_action->setDisabled(true);
409 }
410 some_action = new QAction(_("Give embassy"), this);
411 connect(some_action, &QAction::triggered, this, &diplo_wdg::give_embassy);
412 menu.addAction(some_action);
413 if (player_has_real_embassy(pother, pgiver)) {
414 some_action->setDisabled(true);
415 }
416
417 /* Pacts */
418 if (player_by_number(curr_player) == client_player()) {
419 pacts_menu = menu.addMenu(_("Pacts"));
420 ds = player_diplstate_get(pgiver, pother)->type;
421 some_action = new QAction(Q_("?diplomatic_state:Cease-fire"), this);
422 connect(some_action, &QAction::triggered, this, &diplo_wdg::pact_ceasfire);
423 pacts_menu->addAction(some_action);
424 if (ds == DS_CEASEFIRE || ds == DS_TEAM) {
425 some_action->setDisabled(true);
426 }
427 some_action = new QAction(Q_("?diplomatic_state:Peace"), this);
428 connect(some_action, &QAction::triggered, this, &diplo_wdg::pact_peace);
429 pacts_menu->addAction(some_action);
430 if (ds == DS_PEACE || ds == DS_TEAM) {
431 some_action->setDisabled(true);
432 }
433 some_action = new QAction(Q_("?diplomatic_state:Alliance"), this);
434 connect(some_action, &QAction::triggered, this, &diplo_wdg::pact_allianze);
435 pacts_menu->addAction(some_action);
436 if (ds == DS_ALLIANCE || ds == DS_TEAM) {
437 some_action->setDisabled(true);
438 }
439 }
440
441 /* Check user response for not defined responses in slots */
442 action_menu = 0;
443 action_menu = menu.exec(QCursor::pos());
444 if (action_menu) {
445 qvar = action_menu->data();
446 tech_var = action_menu->property("TECH");
447 city_var = action_menu->property("CITY");
448 if (tech_var.toInt() == 1 && city_var.toInt() == 0) {
449 padv = (advance *) qvar.value < void *>();
450 give_advance(advance_number(padv));
451 }
452 if (tech_var.toInt() == 0 && city_var.toInt() == 1) {
453 city_num = qvar.toInt();
454 give_city(city_num);
455 }
456 }
457 }
458
459 /****************************************************************************
460 Give embassy menu activated
461 ****************************************************************************/
give_embassy()462 void diplo_wdg::give_embassy()
463 {
464 dsend_packet_diplomacy_create_clause_req(&client.conn,
465 player_number(treaty.plr0),
466 curr_player, CLAUSE_EMBASSY, 0);
467 }
468
469 /****************************************************************************
470 Give shared vision menu activated
471 ****************************************************************************/
give_shared_vision()472 void diplo_wdg::give_shared_vision()
473 {
474 dsend_packet_diplomacy_create_clause_req(&client.conn,
475 player_number(treaty.plr0),
476 curr_player, CLAUSE_VISION, 0);
477 }
478
479 /****************************************************************************
480 Create alliance menu activated
481 ****************************************************************************/
pact_allianze()482 void diplo_wdg::pact_allianze()
483 {
484 dsend_packet_diplomacy_create_clause_req(&client.conn,
485 player_number(treaty.plr0),
486 curr_player, CLAUSE_ALLIANCE, 0);
487 }
488
489 /****************************************************************************
490 Ceasfire pact menu activated
491 ****************************************************************************/
pact_ceasfire()492 void diplo_wdg::pact_ceasfire()
493 {
494 dsend_packet_diplomacy_create_clause_req(&client.conn,
495 player_number(treaty.plr0),
496 curr_player, CLAUSE_CEASEFIRE, 0);
497 }
498
499 /****************************************************************************
500 Peace pact menu activated
501 ****************************************************************************/
pact_peace()502 void diplo_wdg::pact_peace()
503 {
504 dsend_packet_diplomacy_create_clause_req(&client.conn,
505 player_number(treaty.plr0),
506 curr_player, CLAUSE_PEACE, 0);
507 }
508
509 /****************************************************************************
510 Sea map menu activated
511 ****************************************************************************/
sea_map_clause()512 void diplo_wdg::sea_map_clause()
513 {
514 dsend_packet_diplomacy_create_clause_req(&client.conn,
515 player_number(treaty.plr0),
516 curr_player, CLAUSE_SEAMAP, 0);
517 }
518
519 /****************************************************************************
520 World map menu activated
521 ****************************************************************************/
world_map_clause()522 void diplo_wdg::world_map_clause()
523 {
524 dsend_packet_diplomacy_create_clause_req(&client.conn,
525 player_number(treaty.plr0),
526 curr_player, CLAUSE_MAP, 0);
527 }
528
529 /****************************************************************************
530 Give city menu activated
531 ****************************************************************************/
give_city(int city_num)532 void diplo_wdg::give_city(int city_num)
533 {
534 int giver, dest, other;
535
536 giver = curr_player;
537 if (curr_player == player1) {
538 dest = player2;
539 } else {
540 dest = player1;
541 }
542
543 if (player_by_number(giver) == client_player()) {
544 other = dest;
545 } else {
546 other = giver;
547 }
548
549 dsend_packet_diplomacy_create_clause_req(&client.conn, other, giver,
550 CLAUSE_CITY, city_num);
551 }
552
553 /****************************************************************************
554 Give advance menu activated
555 ****************************************************************************/
give_advance(int tech)556 void diplo_wdg::give_advance(int tech)
557 {
558 int giver, dest, other;
559
560 giver = curr_player;
561 if (curr_player == player1) {
562 dest = player2;
563 } else {
564 dest = player1;
565 }
566
567 if (player_by_number(giver) == client_player()) {
568 other = dest;
569 } else {
570 other = giver;
571 }
572
573 dsend_packet_diplomacy_create_clause_req(&client.conn, other, giver,
574 CLAUSE_ADVANCE, tech);
575 }
576
577 /****************************************************************************
578 Give all advances menu activated
579 ****************************************************************************/
all_advances()580 void diplo_wdg::all_advances()
581 {
582 int giver, dest, other;
583 const struct research *dresearch, *gresearch;
584
585 giver = curr_player;
586 if (curr_player == player1) {
587 dest = player2;
588 } else {
589 dest = player1;
590 }
591
592 if (player_by_number(giver) == client_player()) {
593 other = dest;
594 } else {
595 other = giver;
596 }
597
598 /* All techs. */
599 struct player *pgiver = player_by_number(giver);
600 struct player *pdest = player_by_number(dest);
601
602 fc_assert_ret(NULL != pgiver);
603 fc_assert_ret(NULL != pdest);
604
605 dresearch = research_get(pdest);
606 gresearch = research_get(pgiver);
607
608 advance_iterate(A_FIRST, padvance) {
609 Tech_type_id i = advance_number(padvance);
610
611 if (research_invention_state(gresearch, i) == TECH_KNOWN
612 && research_invention_gettable(dresearch, i,
613 game.info.tech_trade_allow_holes)
614 && (research_invention_state(dresearch, i) == TECH_UNKNOWN
615 || research_invention_state(dresearch, i)
616 == TECH_PREREQS_KNOWN)) {
617 dsend_packet_diplomacy_create_clause_req(&client.conn, other, giver,
618 CLAUSE_ADVANCE, i);
619 }
620 } advance_iterate_end;
621 }
622
623 /****************************************************************************
624 Show menu for second player
625 ****************************************************************************/
show_menu_p2()626 void diplo_wdg::show_menu_p2()
627 {
628 show_menu(player2);
629 }
630
631 /****************************************************************************
632 Show menu for first player
633 ****************************************************************************/
show_menu_p1()634 void diplo_wdg::show_menu_p1()
635 {
636 show_menu(player1);
637 }
638
639 /****************************************************************************
640 Sets index in QTabWidget
641 ****************************************************************************/
set_index(int ind)642 void diplo_wdg::set_index(int ind)
643 {
644 index = ind;
645 }
646
647 /****************************************************************************
648 Sets index in QTabWidget
649 ****************************************************************************/
get_index()650 int diplo_wdg::get_index()
651 {
652 return index;
653 }
654
655 /****************************************************************************
656 Updates diplomacy widget - updates clauses and redraws pixmaps
657 ****************************************************************************/
update_wdg()658 void diplo_wdg::update_wdg()
659 {
660 bool blank;
661 int i;
662 struct sprite *sprite;
663 QPixmap *pix = NULL;
664 QTableWidgetItem *qitem;
665
666 blank = true;
667 text_edit->clearContents();
668 text_edit->setRowCount(0);
669 i = 0;
670 clause_list_iterate(treaty.clauses, pclause) {
671 char buf[128];
672 client_diplomacy_clause_string(buf, sizeof(buf), pclause);
673 text_edit->insertRow(i);
674 qitem = new QTableWidgetItem();
675 qitem->setText(buf);
676 qitem->setTextAlignment(Qt::AlignLeft);
677 text_edit->setItem(i, 0, qitem);
678 blank = false;
679 i++;
680 } clause_list_iterate_end;
681
682 if (blank) {
683 text_edit->insertRow(0);
684 qitem = new QTableWidgetItem();
685 qitem->setText(_("--- This treaty is blank. "
686 "Please add some clauses. ---"));
687 qitem->setTextAlignment(Qt::AlignLeft);
688 text_edit->setItem(0, 0, qitem);
689 }
690
691 sprite = get_treaty_thumb_sprite(tileset, treaty.accept0);
692 if (sprite != NULL) {
693 pix = sprite->pm;
694 plr1_accept->setPixmap(*pix);
695 } else {
696 plr1_accept->setText("PIXMAP MISSING");
697 }
698
699 sprite = get_treaty_thumb_sprite(tileset, treaty.accept1);
700 if (sprite != NULL) {
701 pix = sprite->pm;
702 plr2_accept->setPixmap(*pix);
703 } else {
704 plr2_accept->setText("PIXMAP MISSING");
705 }
706 }
707
708 /****************************************************************************
709 Restores original nations pixmap
710 ****************************************************************************/
restore_pixmap()711 void diplo_wdg::restore_pixmap()
712 {
713 gui()->sw_diplo->set_pixmap(fc_icons::instance()->get_pixmap("nations"));
714 gui()->sw_diplo->resize_pixmap(gui()->sw_diplo->width(),
715 gui()->sw_diplo->height());
716 gui()->sw_diplo->set_custom_labels(QString());
717 gui()->sw_diplo->update_final_pixmap();
718 }
719
720 /****************************************************************************
721 Button 'Accept treaty' has been clicked
722 ****************************************************************************/
response_accept()723 void diplo_wdg::response_accept()
724 {
725 restore_pixmap();
726 dsend_packet_diplomacy_accept_treaty_req(&client.conn,
727 player_number(treaty.plr0));
728 }
729
730 /****************************************************************************
731 Button 'Cancel treaty' has been clicked
732 ****************************************************************************/
response_cancel()733 void diplo_wdg::response_cancel()
734 {
735 restore_pixmap();
736 dsend_packet_diplomacy_cancel_meeting_req(&client.conn,
737 player_number(treaty.plr0));
738 }
739
740 /****************************************************************************
741 Constructor for diplomacy dialog
742 ****************************************************************************/
diplo_dlg(int counterpart,int initiated_from)743 diplo_dlg::diplo_dlg(int counterpart, int initiated_from): QTabWidget()
744 {
745 add_widget(counterpart, initiated_from);
746 setFocusPolicy(Qt::ClickFocus);
747 }
748
749 /****************************************************************************
750 Creates new diplomacy widget and adds to diplomacy dialog
751 ****************************************************************************/
add_widget(int counterpart,int initiated_from)752 void diplo_dlg::add_widget(int counterpart, int initiated_from)
753 {
754
755 diplo_wdg *dw;
756 struct sprite *sprite;
757 QPixmap *pix;
758 int i;
759
760 pix = NULL;
761 dw = new diplo_wdg(counterpart, initiated_from);
762 treaty_list.insert(counterpart, dw);
763 i = addTab(dw, nation_plural_for_player(player_by_number(counterpart)));
764 dw->set_index(i);
765 sprite = get_nation_flag_sprite(tileset,
766 nation_of_player(player_by_number
767 (counterpart)));
768 if (sprite != NULL) {
769 pix = sprite->pm;
770 }
771 if (pix != NULL) {
772 setTabIcon(i, QIcon(*pix));
773 }
774 }
775
776 /****************************************************************************
777 Sets given widget as active in current dialog
778 ****************************************************************************/
make_active(int party)779 void diplo_dlg::make_active(int party)
780 {
781 QWidget *w;
782
783 w = find_widget(party);
784 if (w == NULL){
785 return;
786 }
787 setCurrentWidget(w);
788 }
789
790 /****************************************************************************
791 Initializes some data for diplomacy dialog
792 ****************************************************************************/
init(bool raise)793 bool diplo_dlg::init(bool raise)
794 {
795 if (!can_client_issue_orders()) {
796 return false;
797 }
798 if (client.conn.playing->ai_controlled) {
799 return false;
800 }
801 setAttribute(Qt::WA_DeleteOnClose);
802 gui()->gimme_place(this, "DDI");
803 index = gui()->add_game_tab(this);
804 gui()->game_tab_widget->setCurrentIndex(index);
805
806 return true;
807 }
808 /****************************************************************************
809 Destructor for diplomacy dialog
810 ****************************************************************************/
~diplo_dlg()811 diplo_dlg::~diplo_dlg()
812 {
813 QMapIterator<int, diplo_wdg *>i(treaty_list);
814 diplo_wdg *dw;
815
816 while (i.hasNext()) {
817 i.next();
818 dw = i.value();
819 dw->close();
820 removeTab(dw->get_index());
821 dw->deleteLater();
822 }
823 gui()->remove_repo_dlg("DDI");
824 gui()->game_tab_widget->setCurrentIndex(0);
825 }
826
827 /****************************************************************************
828 Finds diplomacy widget in current dialog
829 ****************************************************************************/
find_widget(int counterpart)830 diplo_wdg *diplo_dlg::find_widget(int counterpart)
831 {
832 return treaty_list.value(counterpart);
833 }
834
835 /****************************************************************************
836 Closes given diplomacy widget
837 ****************************************************************************/
close_widget(int counterpart)838 void diplo_dlg::close_widget(int counterpart)
839 {
840 diplo_wdg *dw;
841
842 dw = treaty_list.take(counterpart);
843 removeTab(dw->get_index());
844 dw->deleteLater();
845 if (treaty_list.isEmpty()) {
846 close();
847 }
848 }
849
850 /****************************************************************************
851 Updates all diplomacy widgets in current dialog
852 ****************************************************************************/
update_dlg()853 void diplo_dlg::update_dlg()
854 {
855 QMapIterator <int, diplo_wdg *>i(treaty_list);
856 diplo_wdg *dw;
857
858 while (i.hasNext()) {
859 i.next();
860 dw = i.value();
861 dw->update_wdg();
862 }
863 }
864
865 /**************************************************************************
866 Update a player's acceptance status of a treaty (traditionally shown
867 with the thumbs-up/thumbs-down sprite).
868 **************************************************************************/
handle_diplomacy_accept_treaty(int counterpart,bool I_accepted,bool other_accepted)869 void handle_diplomacy_accept_treaty(int counterpart, bool I_accepted,
870 bool other_accepted)
871 {
872 int i;
873 diplo_dlg *dd;
874 diplo_wdg *dw;
875 QWidget *w;
876
877 if (!gui()->is_repo_dlg_open("DDI")) {
878 return;
879 }
880 i = gui()->gimme_index_of("DDI");
881 fc_assert(i != -1);
882 w = gui()->game_tab_widget->widget(i);
883 dd = qobject_cast<diplo_dlg *>(w);
884 dw = dd->find_widget(counterpart);
885 dw->treaty.accept0 = I_accepted;
886 dw->treaty.accept1 = other_accepted;
887 dw->update_wdg();
888
889 }
890
891 /**************************************************************************
892 Handle the start of a diplomacy meeting - usually by poping up a
893 diplomacy dialog.
894 **************************************************************************/
handle_diplomacy_init_meeting(int counterpart,int initiated_from)895 void handle_diplomacy_init_meeting(int counterpart, int initiated_from)
896 {
897
898 int i;
899 diplo_dlg *dd;
900 QPainter p;
901 QPixmap *pix, *def_pix, *pix2, *pix3, *def_pix_del;
902 QWidget *w;
903 QWidget *fw;
904
905 if (client_is_observer()) {
906 return;
907 }
908
909 if (gui()->current_page() != PAGE_GAME) {
910 gui()->switch_page(PAGE_GAME);
911 }
912
913 pix2 = new QPixmap();
914 def_pix_del = new QPixmap();
915 pix = get_nation_flag_sprite(tileset,
916 nation_of_player(player_by_number
917 (counterpart)))->pm;
918 *pix2 = pix->scaledToWidth(gui()->sw_diplo->width() - 2,
919 Qt::SmoothTransformation);
920 if (pix2->height() > gui()->sw_diplo->height()) {
921 *pix2 = pix->scaledToHeight(gui()->sw_diplo->height(),
922 Qt::SmoothTransformation);
923 }
924 pix3 = new QPixmap(gui()->sw_diplo->width(), gui()->sw_diplo->height());
925 pix3->fill(Qt::transparent);
926 def_pix = fc_icons::instance()->get_pixmap("nations");
927 *def_pix_del = def_pix->scaled(gui()->sw_diplo->width(),
928 gui()->sw_diplo->height(),
929 Qt::IgnoreAspectRatio,
930 Qt::SmoothTransformation);
931 p.begin(pix3);
932 p.drawPixmap(1, 1, *pix2);
933 p.drawPixmap(0, 0, *def_pix_del);
934 p.end();
935 gui()->sw_diplo->set_pixmap(pix3);
936 gui()->sw_diplo->resize_pixmap(gui()->sw_diplo->width(),
937 gui()->sw_diplo->height());
938 gui()->sw_diplo->set_custom_labels(QString(nation_plural_for_player(
939 player_by_number(counterpart))));
940 gui()->sw_diplo->update_final_pixmap();
941 delete pix2;
942 delete def_pix_del;
943
944 if (!gui()->is_repo_dlg_open("DDI")) {
945 dd = new diplo_dlg(counterpart, initiated_from);
946
947 if (!dd->init(false)) {
948 delete dd;
949 return;
950 }
951 dd->update_dlg();
952 dd->make_active(counterpart);
953 }
954 i = gui()->gimme_index_of("DDI");
955 fc_assert(i != -1);
956 w = gui()->game_tab_widget->widget(i);
957 dd = qobject_cast<diplo_dlg *>(w);
958 fw = dd->find_widget(counterpart);
959 if (fw == NULL) {
960 dd->add_widget(counterpart, initiated_from);
961 gui()->game_tab_widget->setCurrentIndex(i);
962 }
963 dd->make_active(counterpart);
964
965 /* Bring it to front if user requested meeting */
966 if (player_by_number(initiated_from) == client.conn.playing) {
967 gui()->game_tab_widget->setCurrentIndex(i);
968 }
969 }
970
971 /**************************************************************************
972 Update the diplomacy dialog by adding a clause.
973 **************************************************************************/
handle_diplomacy_create_clause(int counterpart,int giver,enum clause_type type,int value)974 void handle_diplomacy_create_clause(int counterpart, int giver,
975 enum clause_type type, int value)
976 {
977 int i;
978 diplo_dlg *dd;
979 diplo_wdg *dw;
980 QWidget *w;
981
982 if (!gui()->is_repo_dlg_open("DDI")) {
983 return;
984 }
985 i = gui()->gimme_index_of("DDI");
986 fc_assert(i != -1);
987 w = gui()->game_tab_widget->widget(i);
988 dd = qobject_cast<diplo_dlg *>(w);
989 dw = dd->find_widget(counterpart);
990 add_clause(&dw->treaty, player_by_number(giver), type, value);
991 dw->update_wdg();
992 }
993
994 /**************************************************************************
995 Update the diplomacy dialog when the meeting is canceled (the dialog
996 should be closed).
997 **************************************************************************/
handle_diplomacy_cancel_meeting(int counterpart,int initiated_from)998 void handle_diplomacy_cancel_meeting(int counterpart, int initiated_from)
999 {
1000 int i;
1001 diplo_dlg *dd;
1002 QWidget *w;
1003
1004 if (!gui()->is_repo_dlg_open("DDI")) {
1005 return;
1006 }
1007 i = gui()->gimme_index_of("DDI");
1008 fc_assert(i != -1);
1009 w = gui()->game_tab_widget->widget(i);
1010 dd = qobject_cast<diplo_dlg *>(w);
1011 dd->close_widget(counterpart);
1012
1013 }
1014
1015 /**************************************************************************
1016 Update the diplomacy dialog by removing a clause.
1017 **************************************************************************/
handle_diplomacy_remove_clause(int counterpart,int giver,enum clause_type type,int value)1018 void handle_diplomacy_remove_clause(int counterpart, int giver,
1019 enum clause_type type, int value)
1020 {
1021
1022 int i;
1023 diplo_dlg *dd;
1024 diplo_wdg *dw;
1025 QWidget *w;
1026
1027 if (!gui()->is_repo_dlg_open("DDI")) {
1028 return;
1029 }
1030 i = gui()->gimme_index_of("DDI");
1031 fc_assert(i != -1);
1032 w = gui()->game_tab_widget->widget(i);
1033 dd = qobject_cast<diplo_dlg *>(w);
1034 dw = dd->find_widget(counterpart);
1035 remove_clause(&dw->treaty, player_by_number(giver), type, value);
1036 dw->update_wdg();
1037
1038 }
1039
1040 /**************************************************************************
1041 Close all open diplomacy dialogs.
1042
1043 Called when the client disconnects from game.
1044 **************************************************************************/
close_all_diplomacy_dialogs(void)1045 void close_all_diplomacy_dialogs(void)
1046 {
1047 int i;
1048 diplo_dlg *dd;
1049 QWidget *w;
1050
1051 qapp->alert(gui()->central_wdg);
1052 if (!gui()->is_repo_dlg_open("DDI")) {
1053 return;
1054 }
1055 i = gui()->gimme_index_of("DDI");
1056 fc_assert(i != -1);
1057 w = gui()->game_tab_widget->widget(i);
1058 dd = qobject_cast<diplo_dlg *>(w);
1059 dd->close();
1060 delete dd;
1061 }
1062