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