Only reduce fractional movement points to lowest terms for display when
[freeciv.git] / client / gui-qt / dialogs.cpp
blobb7a2403fa4ddd4f5333ca164ee2428d2cb383416
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.
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 ***********************************************************************/
14 #ifdef HAVE_CONFIG_H
15 #include <fc_config.h>
16 #endif
18 // Qt
19 #include <QComboBox>
20 #include <QHeaderView>
21 #include <QMessageBox>
22 #include <QRadioButton>
23 #include <QTableWidgetItem>
24 #include <QTextEdit>
25 #include <QToolBox>
27 // utility
28 #include "astring.h"
30 // common
31 #include "city.h"
32 #include "game.h"
33 #include "government.h"
34 #include "improvement.h"
35 #include "movement.h"
36 #include "nation.h"
38 // client
39 #include "control.h"
40 #include "helpdata.h"
41 #include "text.h"
43 #include "packhand.h"
44 #include "tilespec.h"
46 // gui-qt
47 #include "dialogs.h"
48 #include "qtg_cxxside.h"
49 #include "sprite.h"
51 static void diplomat_keep_moving(QVariant data1, QVariant data2);
52 static void diplomat_incite(QVariant data1, QVariant data2);
53 static void spy_request_sabotage_list(QVariant data1, QVariant data2);
54 static void spy_sabotage(QVariant data1, QVariant data2);
55 static void spy_steal(QVariant data1, QVariant data2);
56 static void spy_steal_something(QVariant data1, QVariant data2);
57 static void diplomat_steal(QVariant data1, QVariant data2);
58 static void spy_poison(QVariant data1, QVariant data2);
59 static void diplomat_embassy(QVariant data1, QVariant data2);
60 static void spy_sabotage_unit(QVariant data1, QVariant data2);
61 static void diplomat_investigate(QVariant data1, QVariant data2);
62 static void diplomat_sabotage(QVariant data1, QVariant data2);
63 static void diplomat_bribe(QVariant data1, QVariant data2);
64 static void caravan_establish_trade(QVariant data1, QVariant data2);
65 static void caravan_help_build(QVariant data1, QVariant data2);
66 static void keep_moving(QVariant data1, QVariant data2);
67 static void caravan_keep_moving(QVariant data1, QVariant data2);
68 static void pillage_something(QVariant data1, QVariant data2);
70 static int caravan_city_id = 0;
71 static int caravan_unit_id = 0;
72 static bool caravan_dialog_open = false;
73 static bool is_showing_pillage_dialog = false;
74 static choice_dialog *caravan_dialog = NULL;
75 static races_dialog* race_dialog;
76 static bool is_race_dialog_open = false;
78 /***************************************************************************
79 Constructor for selecting nations
80 ***************************************************************************/
81 races_dialog::races_dialog(struct player *pplayer, QWidget * parent):QDialog(parent)
83 struct nation_group *group;
84 int i;
85 QGridLayout *qgroupbox_layout;
86 QGroupBox *no_name;
87 QWidget *tab_widget;
88 QTableWidgetItem *item;
89 QPixmap *pix;
90 QHeaderView *header;
91 QSize size;
92 QString title;
94 setAttribute(Qt::WA_DeleteOnClose);
95 is_race_dialog_open = true;
96 main_layout = new QGridLayout;
97 nation_tabs = new QToolBox(parent);
98 selected_nation_tabs = new QTableWidget;
99 city_styles = new QTableWidget;
100 ok_button = new QPushButton;
101 tplayer = pplayer;
103 selected_nation = -1;
104 selected_style = -1;
105 selected_sex = -1;
106 setWindowTitle(_("Select Nation"));
107 selected_nation_tabs->setRowCount(0);
108 selected_nation_tabs->setColumnCount(1);
109 selected_nation_tabs->setSelectionMode(QAbstractItemView::SingleSelection);
110 selected_nation_tabs->verticalHeader()->setVisible(false);
111 selected_nation_tabs->horizontalHeader()->setVisible(false);
112 selected_nation_tabs->setProperty("showGrid", "true");
113 selected_nation_tabs->setEditTriggers(QAbstractItemView::NoEditTriggers);
115 city_styles->setRowCount(0);
116 city_styles->setColumnCount(2);
117 city_styles->setSelectionMode(QAbstractItemView::SingleSelection);
118 city_styles->verticalHeader()->setVisible(false);
119 city_styles->horizontalHeader()->setVisible(false);
120 city_styles->setProperty("showGrid", "false");
121 city_styles->setProperty("selectionBehavior", "SelectRows");
122 city_styles->setEditTriggers(QAbstractItemView::NoEditTriggers);
124 qgroupbox_layout = new QGridLayout;
125 no_name = new QGroupBox(parent);
126 leader_name = new QComboBox(no_name);
127 is_male = new QRadioButton(no_name);
128 is_female = new QRadioButton(no_name);
130 leader_name->setEditable(true);
131 qgroupbox_layout->addWidget(leader_name, 1, 0, 1, 2);
132 qgroupbox_layout->addWidget(is_male, 2, 1);
133 qgroupbox_layout->addWidget(is_female, 2, 0);
134 is_female->setText(_("Female"));
135 is_male->setText(_("Male"));
136 no_name->setLayout(qgroupbox_layout);
138 description = new QTextEdit;
139 description->setReadOnly(true);
140 description->setText(_("Choose nation"));
141 no_name->setTitle(_("Your leader name"));
144 * Fill city styles, no need to update them later
147 for (i = 0; i < game.control.styles_count; i++) {
148 if (city_style_has_requirements(&::city_styles[i])) {
149 continue;
151 item = new QTableWidgetItem;
152 city_styles->insertRow(i);
153 pix = get_sample_city_sprite(tileset, i)->pm;
154 item->setData(Qt::DecorationRole, *pix);
155 item->setData(Qt::UserRole, i);
156 size.setWidth(pix->width());
157 size.setHeight(pix->height());
158 item->setSizeHint(size);
159 city_styles->setItem(i, 0, item);
160 item = new QTableWidgetItem;
161 item->setText(city_style_name_translation(i));
162 city_styles->setItem(i, 1, item);
164 header = city_styles->horizontalHeader();
165 #if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
166 header->setSectionResizeMode(QHeaderView::Stretch);
167 #else
168 header->setResizeMode(QHeaderView::Stretch);
169 #endif
170 header->resizeSections(QHeaderView::ResizeToContents);
171 header = city_styles->verticalHeader();
172 header->resizeSections(QHeaderView::ResizeToContents);
173 tab_widget = new QWidget();
174 nation_tabs->addItem(tab_widget, _("All Nations"));
175 for (i = 0; i < nation_group_count(); i++) {
176 group = nation_group_by_number(i);
177 tab_widget = new QWidget();
178 nation_tabs->addItem(tab_widget, nation_group_name_translation(group));
180 connect(nation_tabs, SIGNAL(currentChanged(int)), SLOT(set_index(int)));
181 connect(city_styles->selectionModel(),
182 SIGNAL(selectionChanged(const QItemSelection &,
183 const QItemSelection &)),
184 SLOT(style_selected(const QItemSelection &,
185 const QItemSelection &)));
186 connect(selected_nation_tabs->selectionModel(),
187 SIGNAL(selectionChanged(const QItemSelection &,
188 const QItemSelection &)),
189 SLOT(nation_selected(const QItemSelection &,
190 const QItemSelection &)));
191 connect(leader_name, SIGNAL(currentIndexChanged(int)),
192 SLOT(leader_selected(int)));
194 ok_button = new QPushButton;
195 ok_button->setText(_("Cancel"));
196 connect(ok_button, SIGNAL(pressed()), SLOT(cancel_pressed()));
197 main_layout->addWidget(ok_button, 8, 1, 1, 1);
198 random_button = new QPushButton;
199 random_button->setText(_("Random"));
200 connect(random_button, SIGNAL(pressed()), SLOT(random_pressed()));
201 main_layout->addWidget(random_button, 8, 0, 1, 1);
202 ok_button = new QPushButton;
203 ok_button->setText(_("Ok"));
204 connect(ok_button, SIGNAL(pressed()), SLOT(ok_pressed()));
205 main_layout->addWidget(ok_button, 8, 2, 1, 1);
206 main_layout->addWidget(no_name, 0, 2, 2, 1);
207 main_layout->addWidget(nation_tabs, 0, 0, 6, 1);
208 main_layout->addWidget(city_styles, 2, 2, 4, 1);
209 main_layout->addWidget(description, 6, 0, 2, 3);
210 main_layout->addWidget(selected_nation_tabs, 0, 1, 6, 1);
212 setLayout(main_layout);
213 set_index(0);
214 update();
216 if (C_S_RUNNING == client_state()) {
217 title = _("Edit Nation");
218 } else if (NULL != pplayer && pplayer == client.conn.playing) {
219 title = _("What Nation Will You Be?");
220 } else {
221 title = _("Pick Nation");
224 setWindowTitle(title);
227 /***************************************************************************
228 Destructor for races dialog
229 ***************************************************************************/
230 races_dialog::~races_dialog()
232 ::is_race_dialog_open = false;
235 /***************************************************************************
236 Sets new nations' group by given index
237 ***************************************************************************/
238 void races_dialog::set_index(int index)
240 QTableWidgetItem *item;
241 QPixmap *pix;
242 struct nation_group *group;
243 int i = 0;
244 struct sprite *s;
245 QHeaderView *header;
247 selected_nation_tabs->clearContents();
248 selected_nation_tabs->setRowCount(0);
250 group = nation_group_by_number(index - 1);
251 nations_iterate(pnation) {
252 if (!is_nation_playable(pnation) || !is_nation_pickable(pnation)) {
253 continue;
255 if (!nation_is_in_group(pnation, group) && index != 0) {
256 continue;
258 item = new QTableWidgetItem;
259 selected_nation_tabs->insertRow(i);
260 s = get_nation_flag_sprite(tileset, pnation);
261 pix = s->pm;
262 item->setData(Qt::DecorationRole, *pix);
263 item->setData(Qt::UserRole, nation_number(pnation));
264 item->setText(nation_adjective_translation(pnation));
265 selected_nation_tabs->setItem(i, 0, item);
266 } nations_iterate_end;
268 selected_nation_tabs->sortByColumn(0, Qt::AscendingOrder);
269 header = selected_nation_tabs->horizontalHeader();
270 header->resizeSections(QHeaderView::Stretch);
271 header = selected_nation_tabs->verticalHeader();
272 header->resizeSections(QHeaderView::ResizeToContents);
275 /***************************************************************************
276 Sets selected nation and updates style and leaders selector
277 ***************************************************************************/
278 void races_dialog::nation_selected(const QItemSelection &selected,
279 const QItemSelection &deselcted)
281 char buf[4096];
282 QModelIndex index ;
283 QVariant qvar,qvar2;
284 QModelIndexList indexes = selected.indexes();
285 QString str;
286 QTableWidgetItem *item;
287 int style, ind;
289 if (indexes.isEmpty()) {
290 return;
293 index = indexes.at(0);
294 if (indexes.isEmpty()){
295 return;
297 qvar = index.data(Qt::UserRole);
298 selected_nation = qvar.toInt();
300 helptext_nation(buf, sizeof(buf), nation_by_number(selected_nation), NULL);
301 description->setText(buf);
302 leader_name->clear();
303 nation_leader_list_iterate(nation_leaders(nation_by_number
304 (selected_nation)), pleader) {
305 str = QString::fromUtf8(nation_leader_name(pleader));
306 leader_name->addItem(str, nation_leader_is_male(pleader));
307 } nation_leader_list_iterate_end;
310 * select style for nation
313 style = city_style_of_nation(nation_by_number(selected_nation));
314 qvar = qvar.fromValue<int>(style);
315 item = new QTableWidgetItem;
317 for (ind = 0; ind < city_styles->rowCount(); ind++) {
318 item = city_styles->item(ind, 0);
320 if (item->data(Qt::UserRole) == qvar) {
321 city_styles->selectRow(ind);
326 /***************************************************************************
327 Sets selected style
328 ***************************************************************************/
329 void races_dialog::style_selected(const QItemSelection &selected,
330 const QItemSelection &deselcted)
332 QModelIndex index ;
333 QVariant qvar;
334 QModelIndexList indexes = selected.indexes();
336 if (indexes.isEmpty()) {
337 return;
340 index = indexes.at(0);
341 qvar = index.data(Qt::UserRole);
342 selected_style = qvar.toInt();
345 /***************************************************************************
346 Sets selected leader
347 ***************************************************************************/
348 void races_dialog::leader_selected(int index)
350 if (leader_name->itemData(index).toBool())
352 is_male->setChecked(true);
353 is_female->setChecked(false);
354 selected_sex=0;
355 } else {
356 is_male->setChecked(false);
357 is_female->setChecked(true);
358 selected_sex=1;
362 /***************************************************************************
363 Button accepting all selection has been pressed, closes dialog if
364 everything is ok
365 ***************************************************************************/
366 void races_dialog::ok_pressed()
369 if (selected_nation == -1) {
370 return;
373 if (selected_sex == -1) {
374 output_window_append(ftc_client, _("You must select your sex."));
375 return;
378 if (selected_style == -1) {
379 output_window_append(ftc_client, _("You must select your city style."));
380 return;
383 if (leader_name->currentText().length() == 0) {
384 output_window_append(ftc_client, _("You must type a legal name."));
385 return;
387 dsend_packet_nation_select_req(&client.conn, player_number(tplayer),
388 selected_nation, selected_sex,
389 leader_name->currentText().toUtf8().data(),
390 selected_style);
391 delete this;
394 /***************************************************************************
395 Constructor for notify dialog
396 ***************************************************************************/
397 notify_dialog::notify_dialog(const char *caption, const char *headline,
398 const char *lines, QWidget *parent)
399 : fcwidget()
401 int x, y;
402 QString qlines;
404 setCursor(Qt::ArrowCursor);
405 setParent(parent);
406 setFrameStyle(QFrame::Box);
407 setWindowOpacity(0.5);
408 cw = new close_widget(this);
409 cw->put_to_corner();
411 #if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
412 qcaption = QString::fromLatin1(caption);
413 qheadline = QString::fromLatin1(headline);
414 qlines = QString::fromLatin1(lines);
415 #else
416 qcaption = QString::fromAscii(caption);
417 qheadline = QString::fromAscii(headline);
418 qlines = QString::fromAscii(lines);
419 #endif
420 qlist = qlines.split("\n");
421 small_font =::gui()->fc_fonts.get_font("gui_qt_font_notify_label");
422 x = 0;
423 y = 0;
424 calc_size(x, y);
425 resize(x, y);
426 gui()->mapview_wdg->find_place(gui()->mapview_wdg->width() - x - 4, 4,
427 x, y, x, y, 0);
428 move(x, y);
429 was_destroyed = false;
432 /***************************************************************************
433 Calculates size of notify dialog
434 ***************************************************************************/
435 void notify_dialog::calc_size(int &x, int &y)
437 QFontMetrics fm(*small_font);
438 int i;
439 QStringList str_list;
441 str_list = qlist;
442 str_list << qcaption << qheadline;
444 for (i = 0; i < str_list.count(); i++) {
445 x = qMax(x, fm.width(str_list.at(i)));
446 y = y + 3 + fm.height();
448 x = x + 15;
451 /***************************************************************************
452 Paint Event for notify dialog
453 ***************************************************************************/
454 void notify_dialog::paintEvent(QPaintEvent * paint_event)
456 QPainter painter(this);
457 QPainterPath path;
458 QPen pen;
459 QFontMetrics fm(*small_font);
460 int i;
462 pen.setWidth(1);
463 pen.setColor(QColor(232, 255, 0));
464 painter.setBrush(QColor(0, 0, 0, 175));
465 painter.drawRect(0, 0, width(), height());
466 painter.setFont(*small_font);
467 painter.setPen(pen);
468 painter.drawText(10, fm.height() + 3, qcaption);
469 painter.drawText(10, 2 * fm.height() + 6, qheadline);
470 for (i = 0; i < qlist.count(); i++) {
471 painter.drawText(10, 3 + (fm.height() + 3) * (i + 3), qlist[i]);
473 painter.drawLine(0,0,width(),0);
474 painter.drawLine(0,height()-1,width(),height()-1);
475 painter.drawLine(0,0,0,height());
476 painter.drawLine(width()-1,0,width()-1,height());
477 cw->put_to_corner();
480 /**************************************************************************
481 Called when mouse button was pressed, just to close on right click
482 **************************************************************************/
483 void notify_dialog::mousePressEvent(QMouseEvent *event)
485 cursor = event->globalPos() - geometry().topLeft();
486 if (event->button() == Qt::RightButton){
487 was_destroyed = true;
488 close();
492 /**************************************************************************
493 Called when mouse button was pressed and moving around
494 **************************************************************************/
495 void notify_dialog::mouseMoveEvent(QMouseEvent *event)
497 move(event->globalPos() - cursor);
498 setCursor(Qt::SizeAllCursor);
501 /**************************************************************************
502 Called when mouse button unpressed. Restores cursor.
503 **************************************************************************/
504 void notify_dialog::mouseReleaseEvent(QMouseEvent *event)
506 setCursor(Qt::ArrowCursor);
509 /***************************************************************************
510 Called when close button was pressed
511 ***************************************************************************/
512 void notify_dialog::update_menu()
514 was_destroyed = true;
515 destroy();
518 /***************************************************************************
519 Destructor for notify dialog, notice that somehow object is not destroyed
520 immediately, so it can be still visible for parent, check boolean
521 was_destroyed if u suspect it could not be destroyed yet
522 ***************************************************************************/
523 notify_dialog::~notify_dialog()
525 was_destroyed = true;
526 destroy();
529 /***************************************************************************
530 Button canceling all selections has been pressed.
531 ***************************************************************************/
532 void races_dialog::cancel_pressed()
534 delete this;
537 /***************************************************************************
538 Sets random nation
539 ***************************************************************************/
540 void races_dialog::random_pressed()
542 dsend_packet_nation_select_req(&client.conn,player_number(tplayer),-1,
543 false, "", 0);
544 delete this;
547 /**************************************************************************
548 Popup a dialog to display information about an event that has a
549 specific location. The user should be given the option to goto that
550 location.
551 **************************************************************************/
552 void popup_notify_goto_dialog(const char *headline, const char *lines,
553 const struct text_tag_list *tags,
554 struct tile *ptile)
556 /* PORTME */
559 /**************************************************************************
560 Popup a dialog to display connection message from server.
561 **************************************************************************/
562 void popup_connect_msg(const char *headline, const char *message)
564 /* PORTME */
567 /**************************************************************************
568 Popup a generic dialog to display some generic information.
569 **************************************************************************/
570 void popup_notify_dialog(const char *caption, const char *headline,
571 const char *lines)
573 notify_dialog *nd = new notify_dialog(caption, headline, lines,
574 gui()->mapview_wdg);
575 nd->show();
578 /**************************************************************************
579 Popup the nation selection dialog.
580 **************************************************************************/
581 void popup_races_dialog(struct player *pplayer)
583 race_dialog = new races_dialog(pplayer);
584 race_dialog->show();
587 /**************************************************************************
588 Close the nation selection dialog. This should allow the user to
589 (at least) select a unit to activate.
590 **************************************************************************/
591 void popdown_races_dialog(void)
593 if (is_race_dialog_open){
594 race_dialog->close();
595 is_race_dialog_open = false;
599 /**************************************************************************
600 Popup a dialog window to select units on a particular tile.
601 **************************************************************************/
602 void unit_select_dialog_popup(struct tile *ptile)
604 if(ptile != NULL && unit_list_size(ptile->units) > 1){
605 gui()->toggle_unit_sel_widget(ptile);
609 /**************************************************************************
610 Update the dialog window to select units on a particular tile.
611 **************************************************************************/
612 void unit_select_dialog_update_real(void)
614 gui()->update_unit_sel();
617 /**************************************************************************
618 The server has changed the set of selectable nations.
619 **************************************************************************/
620 void races_update_pickable(void)
622 /* FIXME handle this properly */
623 popdown_races_dialog();
626 /**************************************************************************
627 In the nation selection dialog, make already-taken nations unavailable.
628 This information is contained in the packet_nations_used packet.
629 **************************************************************************/
630 void races_toggles_set_sensitive(void)
632 /* PORTME */
633 /* maybe just emit signal about chosen toolbox ? */
636 /**************************************************************************
637 Popup a dialog asking if the player wants to start a revolution.
638 **************************************************************************/
639 void popup_revolution_dialog(struct government *government)
641 QMessageBox ask(gui()->central_wdg);
642 int ret;
644 if (0 > client.conn.playing->revolution_finishes) {
645 ask.setText(_("You say you wanna revolution?"));
646 ask.setStandardButtons(QMessageBox::Cancel | QMessageBox::Ok);
647 ask.setDefaultButton(QMessageBox::Cancel);
648 ask.setIcon(QMessageBox::Warning);
649 ask.setWindowTitle(_("Revolution!"));
650 ret = ask.exec();
652 switch (ret) {
653 case QMessageBox::Cancel:
654 break;
655 case QMessageBox::Ok:
656 revolution_response(government);
657 break;
659 } else {
660 revolution_response(government);
664 /***************************************************************************
665 Constructor for choice_dialog
666 ***************************************************************************/
667 choice_dialog::choice_dialog(const QString title, const QString text,
668 QWidget *parent): QWidget(parent)
670 QLabel *l = new QLabel(text);
672 signal_mapper = new QSignalMapper(this);
673 layout = new QVBoxLayout(this);
675 layout->addWidget(l);
676 setWindowFlags(Qt::Dialog);
677 setWindowTitle(title);
678 setAttribute(Qt::WA_DeleteOnClose);
679 gui()->set_diplo_dialog(this);
680 unit_id = -1;
683 /***************************************************************************
684 Destructor for choice dialog
685 ***************************************************************************/
686 choice_dialog::~choice_dialog()
688 data1_list.clear();
689 data2_list.clear();
690 delete signal_mapper;
691 gui()->set_diplo_dialog(NULL);
695 /***************************************************************************
696 Sets layout for choice dialog
697 ***************************************************************************/
698 void choice_dialog::set_layout()
700 connect(signal_mapper, SIGNAL(mapped(const int &)),
701 this, SLOT(execute_action(const int &)));
702 setLayout(layout);
705 /***************************************************************************
706 Adds new action for choice dialog
707 ***************************************************************************/
708 void choice_dialog::add_item(QString title, pfcn_void func, QVariant data1,
709 QVariant data2)
711 QPushButton *button = new QPushButton(title);
712 connect(button, SIGNAL(clicked()), signal_mapper, SLOT(map()));
713 signal_mapper->setMapping(button, func_list.count());
714 func_list.append(func);
715 data1_list.append(data1);
716 data2_list.append(data2);
717 layout->addWidget(button);
720 /***************************************************************************
721 Shows choice dialog
722 ***************************************************************************/
723 void choice_dialog::show_me()
725 QPoint p;
727 p = mapFromGlobal(QCursor::pos());
728 p.setY(p.y()-this->height());
729 p.setX(p.x()-this->width());
730 move(p);
731 show();
734 /***************************************************************************
735 Returns layout in choice dialog
736 ***************************************************************************/
737 QVBoxLayout *choice_dialog::get_layout()
739 return layout;
742 /***************************************************************************
743 Run chosen action and close dialog
744 ***************************************************************************/
745 void choice_dialog::execute_action(const int action)
747 pfcn_void func = func_list.at(action);
748 func(data1_list.at(action), data2_list.at(action));
749 close();
752 /***************************************************************************
753 Action establish trade for choice dialog
754 ***************************************************************************/
755 static void caravan_establish_trade(QVariant data1, QVariant data2)
757 dsend_packet_unit_establish_trade(&client.conn, data2.toInt());
758 caravan_dialog_open = false;
759 process_caravan_arrival(NULL);
762 /***************************************************************************
763 Action help build wonder for choice dialog
764 ***************************************************************************/
765 static void caravan_help_build(QVariant data1, QVariant data2)
767 dsend_packet_unit_help_build_wonder(&client.conn, data2.toInt());
768 caravan_dialog_open = false;
769 process_caravan_arrival(NULL);
772 /***************************************************************************
773 Action 'do nothing' with caravan for choice dialog
774 ***************************************************************************/
775 static void caravan_keep_moving(QVariant data1, QVariant data2)
777 caravan_dialog_open = false;
778 process_caravan_arrival(NULL);
781 /***************************************************************************
782 Empty action for choice dialog (just do nothing)
783 ***************************************************************************/
784 static void keep_moving(QVariant data1, QVariant data2)
787 /***************************************************************************
788 Starts revolution with targeted government as target or anarchy otherwise
789 ***************************************************************************/
790 void revolution_response(struct government *government)
792 if (!government) {
793 start_revolution();
794 } else {
795 set_government_choice(government);
798 /**************************************************************************
799 Popup a dialog giving a player choices when their caravan arrives at
800 a city (other than its home city). Example:
801 - Establish trade route.
802 - Help build wonder.
803 - Keep moving.
804 **************************************************************************/
805 void popup_caravan_dialog(struct unit *punit,
806 struct city *phomecity, struct city *pdestcity)
808 char title_buf[128], buf[128], buf2[1024];
809 bool can_establish, can_trade, can_wonder;
810 struct city* destcity;
811 struct unit* caravan;
812 QString wonder;
813 QString str;
814 QVariant qv1, qv2;
815 pfcn_void func;
817 fc_snprintf(title_buf, sizeof(title_buf),
818 /* TRANS: %s is a unit type */
819 _("Your %s Has Arrived"), unit_name_translation(punit));
820 fc_snprintf(buf, sizeof(buf),
821 _("Your %s from %s reaches the city of %s.\nWhat now?"),
822 unit_name_translation(punit),
823 city_name(phomecity), city_name(pdestcity));
825 caravan_dialog = new choice_dialog(QString(title_buf),
826 QString(buf),
827 gui()->game_tab_widget);
828 caravan_dialog_open = true;
829 qv1 = pdestcity->id;
830 qv2 = punit->id;
831 caravan_city_id = pdestcity->id;
832 caravan_unit_id = punit->id;
833 can_trade = can_cities_trade(phomecity, pdestcity);
834 can_establish = can_trade
835 && can_establish_trade_route(phomecity, pdestcity);
836 destcity = game_city_by_number(pdestcity->id);
837 caravan = game_unit_by_number(punit->id);
839 if (destcity && caravan && unit_can_help_build_wonder(caravan, destcity)) {
840 can_wonder = true;
841 fc_snprintf(buf2, sizeof(buf2), _("Help build _Wonder (%d remaining)"),
842 impr_build_shield_cost(destcity->production.value.building)
843 - destcity->shield_stock);
844 wonder = QString(buf2);
845 } else {
846 can_wonder = false;
847 wonder = QString(_("Help build _Wonder"));
850 if (can_trade) {
851 func = caravan_establish_trade;
852 str = can_establish ? QString(_("Establish _Trade route")) :
853 QString(_("Enter Marketplace"));
854 caravan_dialog->add_item(str, func, qv1, qv2);
856 if (can_wonder) {
857 func = caravan_help_build;
858 caravan_dialog->add_item(wonder, func, qv1, qv2);
860 func = caravan_keep_moving;
861 caravan_dialog->add_item(QString(_("Keep moving")), func, qv1, qv2);
863 caravan_dialog->set_layout();
864 caravan_dialog->show_me();
867 /**************************************************************************
868 Is there currently a caravan dialog open? This is important if there
869 can be only one such dialog at a time; otherwise return false.
870 **************************************************************************/
871 bool caravan_dialog_is_open(int *unit_id, int *city_id)
873 if (unit_id) {
874 *unit_id = caravan_unit_id;
876 if (city_id) {
877 *city_id = caravan_city_id;
879 return caravan_dialog_open;
882 /**************************************************************************
883 Popup a dialog giving a diplomatic unit some options when moving into
884 the target tile.
885 **************************************************************************/
886 void popup_diplomat_dialog(struct unit *punit, struct tile *dest_tile)
888 struct city *pcity;
889 struct unit *ptunit;
890 struct astring title = ASTRING_INIT, text = ASTRING_INIT;
891 int diplomat_id;
892 int diplomat_target_id;
893 QVariant qv1, qv2;
894 pfcn_void func;
896 if ((pcity = tile_city(dest_tile))) {
897 /* Spy/Diplomat acting against a city */
898 diplomat_target_id = pcity->id;
899 diplomat_id = punit->id;
900 gui()->set_current_unit(diplomat_id, diplomat_target_id);
901 astr_set(&title,
902 /* TRANS: %s is a unit name, e.g., Spy */
903 _("Choose Your %s's Strategy"), unit_name_translation(punit));
904 astr_set(&text,
905 _("Your %s has arrived at %s.\nWhat is your command?"),
906 unit_name_translation(punit),
907 city_name(pcity));
908 choice_dialog *cd = new choice_dialog(astr_str(&title),
909 astr_str(&text),
910 gui()->game_tab_widget);
911 qv1 = punit->id;
912 qv2 = pcity->id;
913 cd->unit_id = diplomat_id;
914 if (diplomat_can_do_action(punit, DIPLOMAT_EMBASSY, dest_tile)) {
915 func = diplomat_embassy;
916 cd->add_item(QString(_("Establish Embassy")),
917 func, qv1, qv2);
919 if (diplomat_can_do_action(punit, DIPLOMAT_INVESTIGATE, dest_tile)) {
920 func = diplomat_investigate;
921 cd->add_item(QString(_("Investigate City")), func, qv1, qv2);
923 if (!unit_has_type_flag(punit, UTYF_SPY)) {
924 if (diplomat_can_do_action(punit, DIPLOMAT_SABOTAGE, dest_tile)) {
925 func = diplomat_sabotage;
926 cd->add_item(QString(_("Sabotage City")), func, qv1, qv2);
928 if (diplomat_can_do_action(punit, DIPLOMAT_STEAL, dest_tile)) {
929 func = diplomat_steal;
930 cd->add_item(QString(_("Steal Technology")),
931 func, qv1, qv2);
933 if (diplomat_can_do_action(punit, DIPLOMAT_INCITE, dest_tile)) {
934 func = diplomat_incite;
935 cd->add_item(QString(_("Incite a Revolt")), func, qv1, qv2);
937 if (diplomat_can_do_action(punit, DIPLOMAT_MOVE, dest_tile)) {
938 func = diplomat_keep_moving;
939 cd->add_item(QString(_("Keep moving")), func, qv1, qv2);
941 } else {
942 if (diplomat_can_do_action(punit, SPY_POISON, dest_tile)) {
943 func = spy_poison;
944 cd->add_item(QString(_("Poison City")), func, qv1, qv2);
946 if (diplomat_can_do_action(punit, DIPLOMAT_SABOTAGE, dest_tile)) {
947 func = spy_request_sabotage_list;
948 cd->add_item(QString(_("Industrial Sabotage")),
949 func, qv1, qv2);
951 if (diplomat_can_do_action(punit, DIPLOMAT_STEAL, dest_tile)) {
952 func = spy_steal;
953 cd->add_item(QString(_("Steal Technology")),
954 func, qv1, qv2);
956 if (diplomat_can_do_action(punit, DIPLOMAT_INCITE, dest_tile)) {
957 func = diplomat_incite;
958 cd->add_item(QString(_("Incite a Revolt")), func, qv1, qv2);
960 if (diplomat_can_do_action(punit, DIPLOMAT_MOVE, dest_tile)) {
961 func = diplomat_keep_moving;
962 cd->add_item(QString(_("Keep moving")), func, qv1, qv2);
965 cd->set_layout();
966 cd->show_me();
967 } else {
968 if ((ptunit = unit_list_get(dest_tile->units, 0))) {
969 /* Spy/Diplomat acting against a unit */
971 diplomat_target_id = ptunit->id;
972 diplomat_id = punit->id;
973 gui()->set_current_unit(diplomat_id, diplomat_target_id);
974 astr_set(&text,
975 /* TRANS: %s is a unit name, e.g., Diplomat, Spy */
976 _("Your %s is waiting for your command."),
977 unit_name_translation(punit));
978 choice_dialog *cd = new choice_dialog(_("Subvert Enemy Unit"),
979 astr_str(&text),
980 gui()->game_tab_widget);
981 qv2 = ptunit->id;
982 qv1 = punit->id;
983 if (diplomat_can_do_action(punit, DIPLOMAT_BRIBE, dest_tile)) {
984 func = diplomat_bribe;
985 cd->add_item(QString(_("Bribe Enemy Unit")), func, qv1, qv2);
987 if (diplomat_can_do_action(punit, SPY_SABOTAGE_UNIT, dest_tile)) {
988 func = spy_sabotage_unit;
989 cd->add_item(QString(_("Sabotage Enemy Unit")),
990 func, qv1, qv2);
992 func = keep_moving;
993 cd->add_item(QString(_("Do nothing")), func, qv1, qv2);
994 cd->set_layout();
995 cd->show_me();
998 astr_free(&title);
999 astr_free(&text);
1002 /***************************************************************************
1003 Action bribe unit for choice dialog
1004 ***************************************************************************/
1005 static void diplomat_bribe(QVariant data1, QVariant data2)
1007 int diplomat_id = data1.toInt();
1008 int diplomat_target_id = data2.toInt();
1010 if (NULL != game_unit_by_number(diplomat_id)
1011 && NULL != game_unit_by_number(diplomat_target_id)) {
1012 request_diplomat_answer(DIPLOMAT_BRIBE, diplomat_id,
1013 diplomat_target_id, 0);
1017 /***************************************************************************
1018 Action sabotage unit for choice dialog
1019 ***************************************************************************/
1020 static void spy_sabotage_unit(QVariant data1, QVariant data2)
1022 int diplomat_id = data1.toInt();
1023 int diplomat_target_id = data2.toInt();
1025 request_diplomat_action(SPY_SABOTAGE_UNIT, diplomat_id,
1026 diplomat_target_id, 0);
1029 /***************************************************************************
1030 Action steal tech with spy for choice dialog
1031 ***************************************************************************/
1032 static void spy_steal(QVariant data1, QVariant data2)
1034 QString str;
1035 QVariant qv1, qv2;
1036 pfcn_void func;
1037 int diplomat_id = data1.toInt();
1038 int diplomat_target_id = data2.toInt();
1039 struct city *pvcity = game_city_by_number(diplomat_target_id);
1040 struct player *pvictim = NULL;
1041 choice_dialog *cd;
1042 int nr = 0;
1044 if (pvcity) {
1045 pvictim = city_owner(pvcity);
1047 cd = gui()->get_diplo_dialog();
1048 if (cd != NULL) {
1049 cd->close();
1051 struct astring stra = ASTRING_INIT;
1052 cd = new choice_dialog(_("_Steal"), _("Steal Technology"),
1053 gui()->game_tab_widget);
1054 qv1 = data1;
1055 struct player *pplayer = client.conn.playing;
1056 if (pvictim) {
1057 advance_index_iterate(A_FIRST, i) {
1058 if (player_invention_state(pvictim, i) == TECH_KNOWN &&
1059 (player_invention_state(pplayer, i) == TECH_UNKNOWN ||
1060 player_invention_state(pplayer, i) == TECH_PREREQS_KNOWN)) {
1061 func = spy_steal_something;
1062 str = advance_name_for_player(client.conn.playing, i);
1063 cd->add_item(str, func, qv1, i);
1064 nr++;
1066 } advance_index_iterate_end;
1067 astr_set(&stra, _("At %s's Discretion"),
1068 unit_name_translation(game_unit_by_number(diplomat_id)));
1069 func = spy_steal_something;
1070 str = astr_str(&stra);
1071 cd->add_item(str, func, qv1, A_UNSET);
1072 cd->set_layout();
1073 cd->show_me();
1075 astr_free(&stra);
1078 /***************************************************************************
1079 Action steal given tech for choice dialog
1080 ***************************************************************************/
1081 static void spy_steal_something(QVariant data1, QVariant data2)
1083 int diplomat_id;
1084 int diplomat_target_id;
1086 gui()->get_current_unit(&diplomat_id, &diplomat_target_id);
1087 if (NULL != game_unit_by_number(diplomat_id)
1088 && NULL != game_city_by_number(diplomat_target_id)) {
1089 request_diplomat_action(DIPLOMAT_STEAL, diplomat_id,
1090 diplomat_target_id, data2.toInt());
1094 /***************************************************************************
1095 Action request sabotage list for choice dialog
1096 ***************************************************************************/
1097 static void spy_request_sabotage_list(QVariant data1, QVariant data2)
1099 int diplomat_id = data1.toInt();
1100 int diplomat_target_id = data2.toInt();
1102 if (NULL != game_unit_by_number(diplomat_id)
1103 && NULL != game_city_by_number(diplomat_target_id)) {
1104 request_diplomat_answer(DIPLOMAT_SABOTAGE, diplomat_id,
1105 diplomat_target_id, 0);
1109 /***************************************************************************
1110 Action poison city for choice dialog
1111 ***************************************************************************/
1112 static void spy_poison(QVariant data1, QVariant data2)
1114 int diplomat_id = data1.toInt();
1115 int diplomat_target_id = data2.toInt();
1117 if (NULL != game_unit_by_number(diplomat_id)
1118 && NULL != game_city_by_number(diplomat_target_id)) {
1119 request_diplomat_action(SPY_POISON, diplomat_id, diplomat_target_id, 0);
1123 /***************************************************************************
1124 Action establish embassy for choice dialog
1125 ***************************************************************************/
1126 static void diplomat_embassy(QVariant data1, QVariant data2)
1128 int diplomat_id = data1.toInt();
1129 int diplomat_target_id = data2.toInt();
1131 if (NULL != game_unit_by_number(diplomat_id)
1132 && NULL != game_city_by_number(diplomat_target_id)) {
1133 request_diplomat_action(DIPLOMAT_EMBASSY, diplomat_id,
1134 diplomat_target_id, 0);
1138 /***************************************************************************
1139 Action investigate city for choice dialog
1140 ***************************************************************************/
1141 static void diplomat_investigate(QVariant data1, QVariant data2)
1143 int diplomat_id = data1.toInt();
1144 int diplomat_target_id = data2.toInt();
1146 if (NULL != game_city_by_number(diplomat_target_id)
1147 && NULL != game_unit_by_number(diplomat_id)) {
1148 request_diplomat_action(DIPLOMAT_INVESTIGATE, diplomat_id,
1149 diplomat_target_id, 0);
1153 /***************************************************************************
1154 Action sabotage for choice dialog
1155 ***************************************************************************/
1156 static void diplomat_sabotage(QVariant data1, QVariant data2)
1158 int diplomat_id = data1.toInt();
1159 int diplomat_target_id = data2.toInt();
1161 if (NULL != game_unit_by_number(diplomat_id)
1162 && NULL != game_city_by_number(diplomat_target_id)) {
1163 request_diplomat_action(DIPLOMAT_SABOTAGE, diplomat_id,
1164 diplomat_target_id, B_LAST + 1);
1168 /***************************************************************************
1169 Action steal with diplomat for choice dialog
1170 ***************************************************************************/
1171 static void diplomat_steal(QVariant data1, QVariant data2)
1173 int diplomat_id = data1.toInt();
1174 int diplomat_target_id = data2.toInt();
1176 if (NULL != game_unit_by_number(diplomat_id)
1177 && NULL != game_city_by_number(diplomat_target_id)) {
1178 request_diplomat_action(DIPLOMAT_STEAL, diplomat_id,
1179 diplomat_target_id, A_UNSET);
1183 /***************************************************************************
1184 Action incite revolt for choice dialog
1185 ***************************************************************************/
1186 static void diplomat_incite(QVariant data1, QVariant data2)
1188 int diplomat_id = data1.toInt();
1189 int diplomat_target_id = data2.toInt();
1191 if (NULL != game_unit_by_number(diplomat_id)
1192 && NULL != game_city_by_number(diplomat_target_id)) {
1193 request_diplomat_answer(DIPLOMAT_INCITE, diplomat_id,
1194 diplomat_target_id, 0);
1198 /***************************************************************************
1199 Action keep moving with diplomat for choice dialog
1200 ***************************************************************************/
1201 static void diplomat_keep_moving(QVariant data1, QVariant data2)
1203 struct unit *punit;
1204 struct city *pcity;
1205 int diplomat_id = data1.toInt();
1206 int diplomat_target_id = data2.toInt();
1208 if ((punit = game_unit_by_number(diplomat_id))
1209 && (pcity = game_city_by_number(diplomat_target_id))
1210 && !same_pos(unit_tile(punit), city_tile(pcity))) {
1211 request_diplomat_action(DIPLOMAT_MOVE, diplomat_id,
1212 diplomat_target_id, 0);
1216 /**************************************************************************
1217 Popup a window asking a diplomatic unit if it wishes to incite the
1218 given enemy city.
1219 **************************************************************************/
1220 void popup_incite_dialog(struct unit *actor, struct city *pcity, int cost)
1222 char buf[1024];
1223 char buf2[1024];
1224 int ret;
1225 int diplomat_id;
1226 int diplomat_target_id;
1228 fc_snprintf(buf, ARRAY_SIZE(buf), PL_("Treasury contains %d gold.",
1229 "Treasury contains %d gold.",
1230 client_player()->economic.gold),
1231 client_player()->economic.gold);
1233 if (INCITE_IMPOSSIBLE_COST == cost) {
1234 QMessageBox incite_impossible;
1236 fc_snprintf(buf2, ARRAY_SIZE(buf2),
1237 _("You can't incite a revolt in %s."), city_name(pcity));
1238 incite_impossible.setText(QString(buf2));
1239 incite_impossible.exec();
1240 } else if (cost <= client_player()->economic.gold) {
1241 QMessageBox ask;
1243 fc_snprintf(buf2, ARRAY_SIZE(buf2),
1244 PL_("Incite a revolt for %d gold?\n%s",
1245 "Incite a revolt for %d gold?\n%s", cost), cost, buf);
1246 ask.setText(QString(buf2));
1247 ask.setStandardButtons(QMessageBox::Cancel | QMessageBox::Ok);
1248 ask.setDefaultButton(QMessageBox::Cancel);
1249 ask.setIcon(QMessageBox::Question);
1250 ask.setWindowTitle(_("Incite a Revolt!"));
1251 ret = ask.exec();
1252 switch (ret) {
1253 case QMessageBox::Cancel:
1254 return;
1255 break;
1256 case QMessageBox::Ok:
1257 gui()->get_current_unit(&diplomat_id, &diplomat_target_id);
1258 request_diplomat_action(DIPLOMAT_INCITE, diplomat_id,
1259 diplomat_target_id, 0);
1260 break;
1262 } else {
1263 QMessageBox too_much;
1265 fc_snprintf(buf2, ARRAY_SIZE(buf2),
1266 PL_("Inciting a revolt costs %d gold.\n%s",
1267 "Inciting a revolt costs %d gold.\n%s", cost), cost,
1268 buf);
1269 too_much.setText(QString(buf2));
1270 too_much.exec();
1274 /**************************************************************************
1275 Popup a dialog asking a diplomatic unit if it wishes to bribe the
1276 given enemy unit.
1277 **************************************************************************/
1278 void popup_bribe_dialog(struct unit *actor, struct unit *punit, int cost)
1280 QMessageBox ask;
1281 int ret;
1282 QString str;
1283 char buf[1024];
1284 char buf2[1024];
1285 int diplomat_id;
1286 int diplomat_target_id;
1288 gui()->get_current_unit(&diplomat_id, &diplomat_target_id);
1289 fc_snprintf(buf, ARRAY_SIZE(buf), PL_("Treasury contains %d gold.",
1290 "Treasury contains %d gold.",
1291 client_player()->economic.gold),
1292 client_player()->economic.gold);
1293 if (unit_has_type_flag(punit, UTYF_UNBRIBABLE)) {
1294 ask.setWindowTitle(_("Ooops..."));
1295 ask.setText(_("This unit cannot be bribed!"));
1296 ask.exec();
1297 return;
1300 ask.setWindowTitle(QString(_("Bribe Enemy Unit")));
1301 if (cost <= client_player()->economic.gold) {
1302 fc_snprintf(buf2, ARRAY_SIZE(buf2), PL_("Bribe unit for %d gold?\n%s",
1303 "Bribe unit for %d gold?\n%s",
1304 cost), cost, buf);
1305 ask.setText(QString(buf2));
1306 ask.setStandardButtons(QMessageBox::Cancel | QMessageBox::Ok);
1307 ask.setDefaultButton(QMessageBox::Cancel);
1308 ask.setIcon(QMessageBox::Question);
1309 ret = ask.exec();
1310 switch (ret) {
1311 case QMessageBox::Cancel:
1312 break;
1313 case QMessageBox::Ok:
1314 request_diplomat_action(DIPLOMAT_BRIBE, diplomat_id,
1315 diplomat_target_id, 0);
1316 break;
1317 default:
1318 break;
1320 } else {
1321 fc_snprintf(buf2, ARRAY_SIZE(buf2),
1322 PL_("Bribing the unit costs %d gold.\n%s",
1323 "Bribing the unit costs %d gold.\n%s", cost), cost, buf);
1324 ask.setWindowTitle(_("Traitors Demand Too Much!"));
1325 ask.exec();
1329 /***************************************************************************
1330 Action pillage for choice dialog
1331 ***************************************************************************/
1332 static void pillage_something(QVariant data1, QVariant data2)
1334 int punit_id;
1335 int what;
1336 struct unit *punit;
1338 what = data1.toInt();
1339 punit_id = data2.toInt();
1340 punit = game_unit_by_number(punit_id);
1341 struct act_tgt target;
1343 if (what >= S_LAST + game.control.num_base_types) {
1344 target.type = ATT_ROAD;
1345 target.obj.road = what - S_LAST - game.control.num_base_types;
1346 } else if (what >= S_LAST) {
1347 target.type = ATT_BASE;
1348 target.obj.base = what - S_LAST;
1349 } else {
1350 target.type = ATT_SPECIAL;
1351 target.obj.spe = static_cast<tile_special_type>(what);
1354 request_new_unit_activity_targeted(punit, ACTIVITY_PILLAGE,
1355 &target);
1356 ::is_showing_pillage_dialog = false;
1359 /***************************************************************************
1360 Action sabotage with spy for choice dialog
1361 ***************************************************************************/
1362 static void spy_sabotage(QVariant data1, QVariant data2)
1364 int diplomat_id;
1365 int diplomat_target_id;
1367 gui()->get_current_unit(&diplomat_id, &diplomat_target_id);
1368 if (NULL != game_unit_by_number(diplomat_id)
1369 && NULL != game_city_by_number(diplomat_target_id)) {
1370 request_diplomat_action(DIPLOMAT_SABOTAGE, diplomat_id,
1371 diplomat_target_id, data2.toInt()+1);
1375 /**************************************************************************
1376 Popup a dialog asking a diplomatic unit if it wishes to sabotage the
1377 given enemy city.
1378 **************************************************************************/
1379 void popup_sabotage_dialog(struct unit *actor, struct city *pcity)
1382 QString str;
1383 QVariant qv1, qv2;
1384 int diplomat_id;
1385 int diplomat_target_id;
1386 pfcn_void func;
1387 choice_dialog *cd = new choice_dialog(_("_Sabotage"),
1388 _("Select Improvement to Sabotage"),
1389 gui()->game_tab_widget);
1390 int nr = 0;
1391 struct astring stra = ASTRING_INIT;
1393 gui()->get_current_unit(&diplomat_id, &diplomat_target_id);
1394 qv1 = diplomat_id;
1395 func = spy_sabotage;
1396 cd->add_item(QString(_("City Production")), func, qv1, -1);
1397 city_built_iterate(pcity, pimprove) {
1398 if (pimprove->sabotage > 0) {
1399 func = spy_sabotage;
1400 str = city_improvement_name_translation(pcity, pimprove);
1401 qv2 = nr;
1402 cd->add_item(str, func, qv1, improvement_number(pimprove));
1403 nr++;
1405 } city_built_iterate_end;
1406 astr_set(&stra, _("At %s's Discretion"),
1407 unit_name_translation(game_unit_by_number(diplomat_id)));
1408 func = spy_sabotage;
1409 str = astr_str(&stra);
1410 cd->add_item(str, func, qv1, B_LAST);
1411 cd->set_layout();
1412 cd->show_me();
1413 astr_free(&stra);
1416 /**************************************************************************
1417 Popup a dialog asking the unit which improvement they would like to
1418 pillage.
1419 **************************************************************************/
1420 void popup_pillage_dialog(struct unit *punit, bv_special spe,
1421 bv_bases bases, bv_roads roads)
1423 QString str;
1424 QVariant qv1, qv2;
1425 pfcn_void func;
1426 struct act_tgt tgt;
1427 choice_dialog *cd;
1429 if (is_showing_pillage_dialog){
1430 return;
1432 cd = new choice_dialog(_("What To Pillage"), _("Select what to pillage:"),
1433 gui()->game_tab_widget);
1434 qv2 = punit->id;
1435 while (get_preferred_pillage(&tgt, spe, bases, roads)) {
1436 int what = S_LAST;
1437 bv_special what_spe;
1438 bv_bases what_base;
1439 bv_roads what_road;
1441 BV_CLR_ALL(what_spe);
1442 BV_CLR_ALL(what_base);
1443 BV_CLR_ALL(what_road);
1445 switch (tgt.type) {
1446 case ATT_SPECIAL:
1447 BV_SET(what_spe, tgt.obj.spe);
1448 what = tgt.obj.spe;
1449 clear_special(&spe, tgt.obj.spe);
1450 break;
1451 case ATT_BASE:
1452 BV_SET(what_base, tgt.obj.base);
1453 what = tgt.obj.base + S_LAST;
1454 BV_CLR(bases, tgt.obj.base);
1455 break;
1456 case ATT_ROAD:
1457 BV_SET(what_road, tgt.obj.road);
1458 what = tgt.obj.road + S_LAST + game.control.num_base_types;
1459 BV_CLR(roads, tgt.obj.road);
1460 break;
1462 func = pillage_something;
1463 str = get_infrastructure_text(what_spe, what_base, what_road);
1464 qv1 = what;
1465 cd->add_item(str, func, qv1,qv2);
1467 cd->set_layout();
1468 cd->show_me();
1471 /****************************************************************************
1472 Pops up a dialog to confirm disband of the unit(s).
1473 ****************************************************************************/
1474 void popup_disband_dialog(struct unit_list *punits)
1476 QMessageBox ask;
1477 int ret;
1478 QString str;
1480 if (!punits || unit_list_size(punits) == 0) {
1481 return;
1483 if (unit_list_size(punits) == 1) {
1484 ask.setText(_("Are you sure you want to disband that unit?"));
1485 } else {
1486 str =
1487 QString(_("Are you sure you want to disband those %1 units?")).arg
1488 (unit_list_size(punits));
1489 ask.setText(str);
1491 ask.setWindowTitle(_("Disband"));
1492 ask.setStandardButtons(QMessageBox::Cancel | QMessageBox::Ok);
1493 ask.setDefaultButton(QMessageBox::Cancel);
1494 ask.setIcon(QMessageBox::Question);
1495 ask.setWindowTitle(_("Disband unit(s)"));
1496 ret = ask.exec();
1498 switch (ret) {
1499 case QMessageBox::Cancel:
1500 return;
1501 break;
1502 case QMessageBox::Ok:
1503 unit_list_iterate(punits, punit) {
1504 if (!unit_has_type_flag(punit, UTYF_UNDISBANDABLE)) {
1505 request_unit_disband(punit);
1507 } unit_list_iterate_end;
1508 break;
1512 /**************************************************************************
1513 Ruleset (modpack) has suggested loading certain tileset. Confirm from
1514 user and load.
1515 **************************************************************************/
1516 void popup_tileset_suggestion_dialog(void)
1518 qDebug() << Q_FUNC_INFO << "PORTME";
1521 /****************************************************************
1522 Ruleset (modpack) has suggested loading certain soundset. Confirm from
1523 user and load.
1524 *****************************************************************/
1525 void popup_soundset_suggestion_dialog(void)
1527 qDebug() << Q_FUNC_INFO << "PORTME";
1530 /**************************************************************************
1531 Tileset (modpack) has suggested loading certain theme. Confirm from
1532 user and load.
1533 **************************************************************************/
1534 bool popup_theme_suggestion_dialog(const char *theme_name)
1536 /* PORTME */
1537 return false;
1540 /**************************************************************************
1541 This function is called when the client disconnects or the game is
1542 over. It should close all dialog windows for that game.
1543 **************************************************************************/
1544 void popdown_all_game_dialogs(void)
1546 int i;
1547 QList <choice_dialog *> cd_list;
1549 cd_list = gui()->game_tab_widget->findChildren <choice_dialog *>();
1550 for (i = 0; i < cd_list.count(); i++) {
1551 cd_list[i]->close();
1555 /****************************************************************
1556 Returns id of a diplomat currently handled in diplomat dialog
1557 *****************************************************************/
1558 int diplomat_handled_in_diplomat_dialog(void)
1560 choice_dialog *cd = gui()->get_diplo_dialog();
1562 if (cd != NULL){
1563 return cd->unit_id;
1564 } else {
1565 return -1;
1569 /****************************************************************
1570 Closes the diplomat dialog
1571 ****************************************************************/
1572 void close_diplomat_dialog(void)
1574 choice_dialog *cd;
1576 cd = gui()->get_diplo_dialog();
1577 if (cd != NULL){
1578 cd->close();
1580 gui()->set_current_unit(-1, -1);
1583 /****************************************************************
1584 Updates caravan dialog
1585 ****************************************************************/
1586 void caravan_dialog_update(void)
1588 char buf2[1024];
1589 struct city *destcity;
1590 struct unit *caravan;
1591 QString wonder;
1592 QString str;
1593 QVariant qv1, qv2;
1594 pfcn_void func;
1595 int i;
1596 QVBoxLayout *layout;
1597 QPushButton *qpb;
1599 if (caravan_dialog == NULL) {
1600 return;
1602 destcity = game_city_by_number(caravan_city_id);
1603 caravan = game_unit_by_number(caravan_unit_id);
1604 i = 0;
1605 layout = caravan_dialog->get_layout();
1606 foreach (func, caravan_dialog->func_list) {
1607 if (func == caravan_help_build) {
1608 if (destcity && caravan
1609 && unit_can_help_build_wonder(caravan, destcity)) {
1610 fc_snprintf(buf2, sizeof(buf2),
1611 _("Help build _Wonder (%d remaining)"),
1612 impr_build_shield_cost(destcity->production.value.building)
1613 - destcity->shield_stock);
1614 wonder = QString(buf2);
1615 } else {
1616 wonder = QString(_("Help build _Wonder"));
1618 qpb = qobject_cast<QPushButton *>(layout->itemAt(i + 1)->widget());
1619 qpb->setText(wonder);
1621 i++;
1625 /****************************************************************
1626 Player has gained a new tech.
1627 *****************************************************************/
1628 void show_tech_gained_dialog(Tech_type_id tech)
1632 /****************************************************************
1633 Show tileset error dialog.
1634 *****************************************************************/
1635 void show_tileset_error(const char *msg)
1637 /* PORTME */
1640 /****************************************************************
1641 Popup dialog for upgrade units
1642 *****************************************************************/
1643 void popup_upgrade_dialog(struct unit_list *punits)
1645 char buf[512];
1646 QMessageBox ask;
1647 int ret;
1649 if (!punits || unit_list_size(punits) == 0) {
1650 return;
1652 if (!get_units_upgrade_info(buf, sizeof(buf), punits)) {
1653 ask.setText(QString(buf));
1654 ask.setWindowTitle(_("Upgrade Unit!"));
1655 } else {
1656 ask.setWindowTitle(_("Upgrade Obsolete Units"));
1657 ask.setStandardButtons(QMessageBox::Cancel | QMessageBox::Ok);
1658 ask.setDefaultButton(QMessageBox::Cancel);
1659 ask.setIcon(QMessageBox::Question);
1660 ret = ask.exec();
1662 switch (ret) {
1663 case QMessageBox::Cancel:
1664 return;
1665 break;
1666 case QMessageBox::Ok:
1667 unit_list_iterate(punits, punit) {
1668 request_unit_upgrade(punit);
1669 } unit_list_iterate_end;
1670 break;
1675 /****************************************************************
1676 Contructor for unit_select
1677 *****************************************************************/
1678 unit_select::unit_select(tile *ptile, QWidget *parent)
1680 QPoint p, final_p;
1682 setParent(parent);
1683 utile = ptile;
1684 pix = NULL;
1685 show_line = 0;
1686 highligh_num = -1;
1687 ufont = new QFont;
1688 ufont->setItalic(true);
1689 info_font = gui()->fc_fonts.get_font("gui_qt_font_notify_label");
1690 update_units();
1691 h_pix = NULL;
1692 create_pixmap();
1693 p = mapFromGlobal(QCursor::pos());
1694 setMouseTracking(true);
1695 final_p.setX(p.x());
1696 final_p.setY(p.y());
1697 if (p.x() + width() > parentWidget()->width()) {
1698 final_p.setX(parentWidget()->width() - width());
1700 if (p.y() - height() < 0) {
1701 final_p.setY(height());
1703 move(final_p.x(), final_p.y() - height());
1705 /****************************************************************
1706 Destructor for unit select
1707 *****************************************************************/
1708 unit_select::~unit_select()
1710 delete h_pix;
1711 delete pix;
1712 delete ufont;
1715 /****************************************************************
1716 Create pixmap of whole widget except borders (pix)
1717 *****************************************************************/
1718 void unit_select::create_pixmap()
1720 struct unit *punit;
1721 QPixmap *tmp_pix;
1722 struct canvas *unit_pixmap;
1723 QList <QPixmap*>pix_list;
1724 QPainter p;
1725 QString str;
1726 int x, y, i;
1727 int rate, f;
1728 int a;
1729 QPen pen;
1730 QFontMetrics fm(*info_font);
1732 if (pix != NULL) {
1733 delete pix;
1734 pix = NULL;
1737 if (unit_list.count() > 0) {
1738 punit = unit_list.at(0);
1739 item_size.setWidth(tileset_full_tile_width(tileset));
1740 item_size.setHeight(tileset_tile_height(tileset) * 3 / 2);
1741 more = false;
1742 if (h_pix == NULL) {
1743 h_pix = new QPixmap(item_size.width(), item_size.height());
1744 h_pix->fill(QColor(100, 100, 100, 140));
1746 if (unit_list.size() < 5) {
1747 row_count = 1;
1748 pix = new QPixmap((unit_list.size()) * item_size.width(),
1749 item_size.height());
1750 } else if (unit_list.size() < 9) {
1751 row_count = 2;
1752 pix = new QPixmap(4 * item_size.width(), 2 * item_size.height());
1753 } else {
1754 row_count = 3;
1755 if (unit_list_size(utile->units) > unit_list.size() - 1) {
1756 more = true;
1758 pix = new QPixmap(4 * item_size.width(), 3 * item_size.height());
1760 pix->fill(Qt::transparent);
1761 foreach(punit, unit_list) {
1762 unit_pixmap = qtg_canvas_create(tileset_full_tile_width(tileset),
1763 tileset_tile_height(tileset) * 3 / 2);
1764 unit_pixmap->map_pixmap.fill(Qt::transparent);
1765 put_unit(punit, unit_pixmap, 0, 0);
1766 pix_list.push_back(&unit_pixmap->map_pixmap);
1768 a = qMin(item_size.width() / 4, 12);
1769 x = 0, y = -item_size.height(), i = -1;
1770 p.begin(pix);
1771 ufont->setPixelSize(a);
1772 p.setFont(*ufont);
1773 pen.setColor(QColor(232, 255, 0));
1774 p.setPen(pen);
1776 while (!pix_list.isEmpty()) {
1777 tmp_pix = pix_list.takeFirst();
1778 i++;
1779 if (i % 4 == 0) {
1780 x = 0;
1781 y = y + item_size.height();
1783 punit = unit_list.at(i);
1784 Q_ASSERT(punit != NULL);
1785 rate = unit_type(punit)->move_rate;
1786 f = ((punit->fuel) - 1);
1787 if (i == highligh_num) {
1788 p.drawPixmap(x, y, *h_pix);
1789 p.drawPixmap(x, y, *tmp_pix);
1790 } else {
1791 p.drawPixmap(x, y, *tmp_pix);
1794 if (utype_fuel(unit_type(punit))) {
1795 str = QString(move_points_text((rate * f) + punit->moves_left, false));
1796 } else {
1797 str = QString(move_points_text(punit->moves_left, false));
1799 /* TRANS: MP = Movement points */
1800 str = QString(_("MP:")) + str;
1801 p.drawText(x, y + item_size.height() - 4, str);
1803 x = x + item_size.width();
1804 delete tmp_pix;
1806 p.end();
1807 setFixedWidth(pix->width() + 20);
1808 setFixedHeight(pix->height() + 2 * (fm.height() + 6));
1809 qDeleteAll(pix_list.begin(), pix_list.end());
1813 /****************************************************************
1814 Event for mouse moving around unit_select
1815 *****************************************************************/
1816 void unit_select::mouseMoveEvent(QMouseEvent *event)
1818 int a, b;
1819 int old_h;
1820 QFontMetrics fm(*info_font);
1822 old_h = highligh_num;
1823 highligh_num = -1;
1824 if (event->x() > width() - 11
1825 || event->y() > height() - fm.height() - 5
1826 || event->y() < fm.height() + 3 || event->x() < 11) {
1827 /** do nothing if mouse is on border, just skip next if */
1828 } else if (row_count > 0) {
1829 a = (event->x() - 10) / item_size.width();
1830 b = (event->y() - fm.height() - 3) / item_size.height();
1831 highligh_num = b * 4 + a;
1833 if (old_h != highligh_num) {
1834 create_pixmap();
1835 update();
1839 /****************************************************************
1840 Mouse pressed event for unit_select.
1841 Left Button - chooses units
1842 Right Button - closes widget
1843 *****************************************************************/
1844 void unit_select::mousePressEvent(QMouseEvent *event)
1846 struct unit *punit;
1847 if (event->button() == Qt::RightButton) {
1848 was_destroyed = true;
1849 close();
1850 destroy();
1852 if (event->button() == Qt::LeftButton && highligh_num != -1
1853 && highligh_num < unit_list.count()) {
1854 punit = unit_list.at(highligh_num);
1855 unit_focus_set(punit);
1856 was_destroyed = true;
1857 close();
1858 destroy();
1862 /****************************************************************
1863 Redirected paint event
1864 *****************************************************************/
1865 void unit_select::paint(QPainter *painter, QPaintEvent *event)
1867 QFontMetrics fm(*info_font);
1868 int h, i;
1869 int *f_size;
1870 QPen pen;
1871 QString str, str2;
1872 struct unit *punit;
1873 int point_size = info_font->pointSize();
1874 int pixel_size = info_font->pixelSize();
1876 if (point_size < 0) {
1877 f_size = &pixel_size;
1878 } else {
1879 f_size = &point_size;
1881 if (highligh_num != -1 && highligh_num < unit_list.count()) {
1882 punit = unit_list.at(highligh_num);
1883 str2 = QString(unit_activity_text(punit))
1884 + QString(" ") + QString(_("HP")) + QString(": ")
1885 + QString::number(punit->hp) + QString("/")
1886 + QString::number(unit_type(punit)->hp);
1888 str = QString::number(unit_list_size(utile->units)) + " "
1889 + QString(_("units"));
1890 for (i = *f_size; i > 4; i--) {
1891 if (point_size < 0) {
1892 info_font->setPixelSize(i);
1893 } else {
1894 info_font->setPointSize(i);
1896 QFontMetrics qfm(*info_font);
1897 if (10 + qfm.width(str2) < width()) {
1898 break;
1901 h = fm.height();
1902 painter->setBrush(QColor(0, 0, 0, 135));
1903 painter->drawRect(0, 0, width(), height());
1904 if (pix != NULL) {
1905 painter->drawPixmap(10, h + 3, *pix);
1906 pen.setColor(QColor(232, 255, 0));
1907 painter->setPen(pen);
1908 painter->setFont(*info_font);
1909 painter->drawText(10, h, str);
1910 if (highligh_num != -1 && highligh_num < unit_list.count()) {
1911 painter->drawText(10, height() - 5, str2);
1914 if (point_size < 0) {
1915 info_font->setPixelSize(*f_size);
1916 } else {
1917 info_font->setPointSize(*f_size);
1920 /****************************************************************
1921 Paint event, redirects to paint(...)
1922 *****************************************************************/
1923 void unit_select::paintEvent(QPaintEvent *event)
1925 QPainter painter;
1927 painter.begin(this);
1928 paint(&painter, event);
1929 painter.end();
1932 /****************************************************************
1933 Function from abstract fcwidget to update menu, its not needed
1934 cause widget is easy closable via right mouse click
1935 *****************************************************************/
1936 void unit_select::update_menu()
1940 /****************************************************************
1941 Updates unit list on tile
1942 *****************************************************************/
1943 void unit_select::update_units()
1945 int i = 1;
1947 if (utile == NULL) {
1948 struct unit *punit = head_of_units_in_focus();
1949 if (punit) {
1950 utile = unit_tile(punit);
1953 unit_list.clear();
1954 unit_list_iterate(utile->units, punit) {
1955 if (i > show_line * 4)
1956 unit_list.push_back(punit);
1957 i++;
1958 } unit_list_iterate_end;
1961 /****************************************************************
1962 Mouse wheel event for unit_select
1963 *****************************************************************/
1964 void unit_select::wheelEvent(QWheelEvent *event)
1966 int nr;
1968 if (more == false && utile == NULL) {
1969 return;
1971 nr = qCeil(static_cast<qreal>(unit_list_size(utile->units)) / 4) - 3;
1972 if (event->delta() < 0) {
1973 show_line++;
1974 show_line = qMin(show_line, nr);
1975 } else {
1976 show_line--;
1977 show_line = qMax(0, show_line);
1979 update_units();
1980 create_pixmap();
1981 update();
1982 event->accept();
1985 /***************************************************************************
1986 Set current unit handled in diplo dialog
1987 ***************************************************************************/
1988 void fc_client::set_current_unit(int curr, int target)
1990 current_unit_id = curr;
1991 current_unit_target_id = target;
1994 /***************************************************************************
1995 Get current unit handled in diplo dialog
1996 ***************************************************************************/
1997 void fc_client::get_current_unit(int *curr, int *target)
1999 *curr = current_unit_id;
2000 *target = current_unit_target_id;
2003 /***************************************************************************
2004 Set current diplo dialog
2005 ***************************************************************************/
2006 void fc_client::set_diplo_dialog(choice_dialog *widget)
2008 opened_dialog = widget;
2011 /***************************************************************************
2012 Get current diplo dialog
2013 ***************************************************************************/
2014 choice_dialog* fc_client::get_diplo_dialog()
2016 return opened_dialog;