Some miscellaneous updates to main help, for new features and otherwise.
[freeciv.git] / client / gui-qt / repodlgs.cpp
blob79b71377e86057ec3526de75d6673d28337bbba1
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 <QApplication>
20 #include <QComboBox>
21 #include <QHeaderView>
22 #include <QMessageBox>
23 #include <QProgressBar>
24 #include <QScrollArea>
25 #include <QTableWidget>
27 // common
28 #include "control.h"
29 #include "research.h"
31 // client
32 #include "repodlgs_common.h"
33 #include "reqtree.h"
34 #include "sprite.h"
35 #include "text.h"
37 // gui-qt
38 #include "cityrep.h"
39 #include "qtg_cxxside.h"
41 #include "repodlgs.h"
43 /****************************************************************************
44 Compare unit_items (used for techs) by name
45 ****************************************************************************/
46 bool comp_less_than(const qlist_item &q1, const qlist_item &q2)
48 return (q1.tech_str < q2.tech_str);
51 /****************************************************************************
52 Constructor for research diagram
53 ****************************************************************************/
54 research_diagram::research_diagram(QWidget *parent): QWidget(parent)
56 req = create_reqtree(client_player(), true);
57 get_reqtree_dimensions(req, &width, &height);
58 pcanvas = qtg_canvas_create(width, height);
59 pcanvas->map_pixmap.fill(Qt::transparent);
62 /****************************************************************************
63 Destructor for research diagram
64 ****************************************************************************/
65 research_diagram::~research_diagram()
67 qtg_canvas_free(pcanvas);
68 destroy_reqtree(req);
71 /****************************************************************************
72 Recreates whole diagram and schedules update
73 ****************************************************************************/
74 void research_diagram::update_reqtree()
76 destroy_reqtree(req);
77 req = create_reqtree(client_player(), true);
78 draw_reqtree(req, pcanvas, 0, 0, 0, 0, width, height);
79 update();
82 /****************************************************************************
83 Mouse handler for research_diagram
84 ****************************************************************************/
85 void research_diagram::mousePressEvent(QMouseEvent *event)
87 Tech_type_id tech = get_tech_on_reqtree(req, event->x(), event->y());
89 if (event->button() == Qt::LeftButton && can_client_issue_orders()) {
90 switch (player_invention_state(client_player(), tech)) {
91 case TECH_PREREQS_KNOWN:
92 dsend_packet_player_research(&client.conn, tech);
93 break;
94 case TECH_UNKNOWN:
95 dsend_packet_player_tech_goal(&client.conn, tech);
96 break;
97 case TECH_KNOWN:
98 break;
103 /****************************************************************************
104 Paint event for research_diagram
105 ****************************************************************************/
106 void research_diagram::paintEvent(QPaintEvent *event)
108 QPainter painter;
110 painter.begin(this);
111 painter.drawPixmap(0, 0, width, height, pcanvas->map_pixmap);
112 painter.end();
115 /****************************************************************************
116 Returns size of research_diagram
117 ****************************************************************************/
118 QSize research_diagram::size()
120 QSize s;
122 s.setWidth(width);;
123 s.setHeight(height);
124 return s;
127 /****************************************************************************
128 Consctructor for science_report
129 ****************************************************************************/
130 science_report::science_report(): QWidget()
132 QSize size;
133 QSizePolicy size_expanding_policy(QSizePolicy::Expanding,
134 QSizePolicy::Expanding);
135 QSizePolicy size_fixed_policy(QSizePolicy::Minimum, QSizePolicy::Minimum);
137 goal_combo = new QComboBox();
138 info_label = new QLabel();
139 progress = new QProgressBar();
140 progress_label = new QLabel();
141 researching_combo = new QComboBox();
142 sci_layout = new QGridLayout();
143 res_diag = new research_diagram();
144 scroll = new QScrollArea();
146 curr_list = NULL;
147 goal_list = NULL;
148 progress->setTextVisible(true);
149 progress_label->setSizePolicy(size_fixed_policy);
150 sci_layout->addWidget(progress_label, 0, 0, 1, 8);
151 sci_layout->addWidget(researching_combo, 1, 0, 1, 4);
152 researching_combo->setSizePolicy(size_fixed_policy);
153 sci_layout->addWidget(progress, 1, 5, 1, 4);
154 progress->setSizePolicy(size_fixed_policy);
155 sci_layout->addWidget(goal_combo, 2, 0, 1, 4);
156 goal_combo->setSizePolicy(size_fixed_policy);
157 sci_layout->addWidget(info_label, 2, 5, 1, 4);
158 info_label->setSizePolicy(size_fixed_policy);
160 size = res_diag->size();
161 res_diag->setMinimumSize(size);
162 scroll->setAutoFillBackground(true);
163 scroll->setPalette(QPalette(QColor(215,215,215)));
164 scroll->setWidget(res_diag);
165 scroll->setSizePolicy(size_expanding_policy);
166 sci_layout->addWidget(scroll, 4, 0, 1, 10);
168 QObject::connect(researching_combo, SIGNAL(currentIndexChanged(int)),
169 SLOT(current_tech_changed(int)));
171 QObject::connect(goal_combo, SIGNAL(currentIndexChanged(int)),
172 SLOT(goal_tech_changed(int)));
174 setLayout(sci_layout);
178 /****************************************************************************
179 Destructor for science report
180 Removes "SCI" string marking it as closed
181 And frees given index on list marking it as ready for new widget
182 ****************************************************************************/
183 science_report::~science_report()
185 gui()->remove_repo_dlg("SCI");
186 gui()->remove_place(index);
189 /****************************************************************************
190 Updates science_report and marks it as opened
191 It has to be called soon after constructor.
192 It could be in constructor but compiler will yell about not used variable
193 ****************************************************************************/
194 void science_report::init(bool raise)
196 index = gui()->gimme_place();
197 gui()->add_game_tab(this, _("Research"), index);
198 if (raise == false) {
199 gui()->game_tab_widget->change_color(index, Qt::red);
200 } else {
201 gui()->game_tab_widget->setCurrentIndex(index);
203 gui()->add_repo_dlg("SCI");
204 update_report();
207 /****************************************************************************
208 Schedules paint event in some qt queue
209 ****************************************************************************/
210 void science_report::redraw()
212 update();
215 /****************************************************************************
216 Updates all important widgets on science_report
217 ****************************************************************************/
218 void science_report::update_report()
221 struct player_research *research = player_research_get(client_player());
222 const char *text;
223 int total;
224 int done = research->bulbs_researched;
225 QVariant qvar, qres;
226 double not_used;
227 QString str;
228 qlist_item item;
230 fc_assert_ret(NULL != research);
232 if (curr_list) {
233 delete curr_list;
236 if (goal_list) {
237 delete goal_list;
240 if (research->researching != A_UNSET) {
241 total = total_bulbs_required(client.conn.playing);
242 } else {
243 total = -1;
246 curr_list = new QList<qlist_item>;
247 goal_list = new QList<qlist_item>;
248 progress_label->setText(science_dialog_text());
249 progress_label->setAlignment(Qt::AlignHCenter);
250 info_label->setAlignment(Qt::AlignHCenter);
251 info_label->setText(get_science_goal_text(research->tech_goal));
252 text = get_science_target_text(&not_used);
253 str = QString::fromUtf8(text);
254 progress->setFormat(str);
255 progress->setMinimum(0);
256 progress->setMaximum(total);
258 if (done <= total) {
259 progress->setValue(done);
260 } else {
261 done = total;
262 progress->setValue(done);
265 /** Collect all techs which are reachable in the next step. */
266 advance_index_iterate(A_FIRST, i) {
267 if (TECH_PREREQS_KNOWN == research->inventions[i].state) {
268 item.tech_str
270 QString::fromUtf8(advance_name_translation(advance_by_number(i)));
271 item.id = i;
272 curr_list->append(item);
274 } advance_index_iterate_end;
277 /** Collect all techs which are reachable in next 10 steps. */
278 advance_index_iterate(A_FIRST, i) {
279 if (player_invention_reachable(client_player(), i, true)
280 && TECH_KNOWN != research->inventions[i].state
281 && (i == research->tech_goal
282 || 10 >= research->inventions[i].num_required_techs)) {
283 item.tech_str
284 = QString::fromUtf8(advance_name_translation(advance_by_number(i)));
285 item.id = i;
286 goal_list->append(item);
288 } advance_index_iterate_end;
290 /** sort both lists */
291 qSort(goal_list->begin(), goal_list->end(), comp_less_than);
292 qSort(curr_list->begin(), curr_list->end(), comp_less_than);
294 /** fill combo boxes */
295 researching_combo->blockSignals(true);
296 goal_combo->blockSignals(true);
298 researching_combo->clear();
299 goal_combo->clear();
300 for (int i = 0; i < curr_list->count(); i++) {
301 qvar = curr_list->at(i).id;
302 researching_combo->insertItem(i, curr_list->at(i).tech_str, qvar);
305 for (int i = 0; i < goal_list->count(); i++) {
306 qvar = goal_list->at(i).id;
307 goal_combo->insertItem(i, goal_list->at(i).tech_str, qvar);
310 /** set current tech and goal */
311 qres = research->researching;
313 if (qres == A_UNSET) {
314 researching_combo->insertItem(0, _("None"), A_UNSET);
315 researching_combo->setCurrentIndex(0);
316 } else {
317 for (int i = 0; i < researching_combo->count(); i++) {
318 qvar = researching_combo->itemData(i);
320 if (qvar == qres) {
321 researching_combo->setCurrentIndex(i);
326 qres = research->tech_goal;
328 if (qres == A_UNSET) {
329 goal_combo->insertItem(0, _("None"), A_UNSET);
330 goal_combo->setCurrentIndex(0);
331 } else {
332 for (int i = 0; i < goal_combo->count(); i++) {
333 qvar = goal_combo->itemData(i);
335 if (qvar == qres) {
336 goal_combo->setCurrentIndex(i);
341 researching_combo->blockSignals(false);
342 goal_combo->blockSignals(false);
344 update_reqtree();
347 /****************************************************************************
348 Calls update for research_diagram
349 ****************************************************************************/
350 void science_report::update_reqtree()
352 res_diag->update_reqtree();
355 /****************************************************************************
356 Slot used when combo box with current tech changes
357 ****************************************************************************/
358 void science_report::current_tech_changed(int index)
360 QVariant qvar;
361 qvar = researching_combo->itemData(index);
363 if (researching_combo->hasFocus()) {
364 if (can_client_issue_orders()) {
365 dsend_packet_player_research(&client.conn, qvar.toInt());
370 /****************************************************************************
371 Slot used when combo box with goal have been changed
372 ****************************************************************************/
373 void science_report::goal_tech_changed(int index)
375 QVariant qvar;
376 qvar = goal_combo->itemData(index);
378 if (goal_combo->hasFocus()) {
379 if (can_client_issue_orders()) {
380 dsend_packet_player_tech_goal(&client.conn, qvar.toInt());
385 /**************************************************************************
386 Update the science report.
387 **************************************************************************/
388 void real_science_report_dialog_update(void)
390 int i;
391 science_report *sci_rep;
392 QWidget *w;
394 if (gui()->is_repo_dlg_open("SCI")) {
395 i = gui()->gimme_index_of("SCI");
396 fc_assert(i != -1);
397 w = gui()->game_tab_widget->widget(i);
398 sci_rep = reinterpret_cast<science_report*>(w);
399 sci_rep->update_report();
403 /**************************************************************************
404 Constructor for units report
405 **************************************************************************/
406 units_report::units_report(): QWidget()
408 QGridLayout *units_layout= new QGridLayout;
409 units_widget = new QTableWidget;
410 find_button = new QPushButton;
411 upgrade_button = new QPushButton;
412 QStringList slist;
413 slist << _("Unit Type") << Q_("?Upgradable unit [short]:U") << _("In-Prog")
414 << _("Active") << _("Shield") << _("Food") << _("Gold");
415 units_widget->setColumnCount(slist.count());
416 units_widget->setHorizontalHeaderLabels(slist);
417 units_widget->setProperty("showGrid", "false");
418 units_widget->setProperty("selectionBehavior", "SelectRows");
419 units_widget->setEditTriggers(QAbstractItemView::NoEditTriggers);
420 units_widget->horizontalHeader()->resizeSections(QHeaderView::
421 ResizeToContents);
422 units_widget->verticalHeader()->setVisible(false);
423 units_widget->setSelectionMode(QAbstractItemView::SingleSelection);
424 find_button->setText(_("Find _Nearest"));
425 find_button->setEnabled(false);
426 upgrade_button->setText(_("Upgrade"));
427 upgrade_button->setEnabled(false);
428 units_layout->addWidget(units_widget, 1, 0, 5, 5);
429 units_layout->addWidget(find_button, 0, 0, 1, 1);
430 units_layout->addWidget(upgrade_button, 0, 1, 1, 1);
432 connect(find_button, SIGNAL(pressed()), SLOT(find_units()));
433 connect(upgrade_button, SIGNAL(pressed()), SLOT(upgrade_units()));
434 connect(units_widget->selectionModel(),
435 SIGNAL(selectionChanged(const QItemSelection &,
436 const QItemSelection &)),
437 SLOT(selection_changed(const QItemSelection &,
438 const QItemSelection &)));
439 setLayout(units_layout);
443 /****************************************************************************
444 Destructor for units report
445 ****************************************************************************/
446 units_report::~units_report()
448 gui()->remove_repo_dlg("UNI");
449 gui()->remove_place(index);
452 /****************************************************************************
453 Updates units_report and marks it as opened
454 It has to be called soon after constructor.
455 ****************************************************************************/
456 void units_report::init()
458 curr_row = -1;
459 index = gui()->gimme_place();
460 gui()->add_game_tab(this, _("Units"), index);
461 gui()->game_tab_widget->setCurrentIndex(index);
462 gui()->add_repo_dlg("UNI");
465 /**************************************************************************
466 Updates all widgets in units reports
467 **************************************************************************/
468 void units_report::update_report()
470 struct urd_info {
471 int active_count;
472 int building_count;
473 int upkeep[O_LAST];
475 int output;
476 int row, column;
477 Unit_type_id utype_id;
478 QTableWidgetItem *unit_item;
479 struct urd_info unit_array[utype_count()];
480 struct urd_info unit_totals;
481 struct urd_info *info;
482 QVariant qvar;
484 units_widget->setRowCount(0);
485 units_widget->clearContents();
486 memset(unit_array, '\0', sizeof(unit_array));
487 memset(&unit_totals, '\0', sizeof(unit_totals));
488 /* Count units. */
489 players_iterate(pplayer) {
490 if (client_has_player() && pplayer != client_player()) {
491 continue;
494 unit_list_iterate(pplayer->units, punit) {
495 info = unit_array + utype_index(unit_type(punit));
497 if (0 != punit->homecity) {
498 for (output = 0; output < O_LAST; output++) {
499 info->upkeep[output] += punit->upkeep[output];
502 info->active_count++;
503 } unit_list_iterate_end;
504 city_list_iterate(pplayer->cities, pcity) {
505 if (VUT_UTYPE == pcity->production.kind) {
506 int num_units;
507 info = unit_array + utype_index(pcity->production.value.utype);
508 /* Account for build slots in city */
509 (void) city_production_build_units(pcity, true, &num_units);
510 /* Unit is in progress even if it won't be done this turn */
511 num_units = MAX(num_units, 1);
512 info->building_count += num_units;
514 } city_list_iterate_end;
515 } players_iterate_end;
516 row = 0;
517 unit_type_iterate(utype) {
518 utype_id = utype_index(utype);
519 info = unit_array + utype_id;
521 if (0 == info->active_count && 0 == info->building_count) {
522 continue; /* We don't need a row for this type. */
524 units_widget->setRowCount(row + 1);
525 for (column = 0; column < 7; column++) {
526 unit_item = new QTableWidgetItem;
527 unit_item->setTextAlignment(Qt::AlignHCenter);
528 switch (column) {
529 case 0:
530 unit_item->setTextAlignment(Qt::AlignLeft);
531 unit_item->setText(utype_name_translation(utype));
532 qvar = utype_id;
533 unit_item->setData(Qt::UserRole, qvar);
534 break;
535 case 1:
536 if ((client_has_player()
537 && NULL != can_upgrade_unittype(client_player(), utype))) {
538 unit_item->setCheckState(Qt::Checked);
539 } else {
540 unit_item->setCheckState(Qt::Unchecked);
542 break;
543 case 2:
544 unit_item->setText(QString::number(info->building_count));
545 break;
546 case 3:
547 unit_item->setText(QString::number(info->active_count));
548 break;
549 case 4:
550 unit_item->setText(QString::number(info->upkeep[O_SHIELD]));
551 break;
552 case 5:
553 unit_item->setText(QString::number(info->upkeep[O_FOOD]));
554 break;
555 case 6:
556 unit_item->setText(QString::number(info->upkeep[O_GOLD]));
557 break;
559 units_widget->setItem(row, column, unit_item);
561 /* Update totals. */
562 unit_totals.active_count += info->active_count;
563 for (output = 0; output < O_LAST; output++) {
564 unit_totals.upkeep[output] += info->upkeep[output];
566 unit_totals.building_count += info->building_count;
568 row++;
569 } unit_type_iterate_end;
570 row++;
571 units_widget->setRowCount(row);
572 for (column = 0; column < 7; column++) {
573 unit_item = new QTableWidgetItem;
574 unit_item->setTextAlignment(Qt::AlignHCenter);
575 switch (column) {
576 case 0:
577 unit_item->setTextAlignment(Qt::AlignLeft);
578 unit_item->setText(_("Totals:"));
579 break;
580 case 1:
581 unit_item->setCheckState(Qt::Unchecked);
582 break;
583 case 2:
584 unit_item->setText(QString::number(unit_totals.building_count));
585 break;
586 case 3:
587 unit_item->setText(QString::number(unit_totals.active_count));
588 break;
589 case 4:
590 unit_item->setText(QString::number(unit_totals.upkeep[O_SHIELD]));
591 break;
592 case 5:
593 unit_item->setText(QString::number(unit_totals.upkeep[O_FOOD]));
594 break;
595 case 6:
596 unit_item->setText(QString::number(unit_totals.upkeep[O_GOLD]));
597 break;
599 units_widget->setItem(row - 1, column, unit_item);
601 units_widget->resizeRowsToContents();
602 max_row = row - 1;
605 /**************************************************************************
606 Finds closest unit
607 **************************************************************************/
608 struct unit *units_report::find_nearest_unit(const struct unit_type *utype,
609 struct tile *ptile)
611 struct unit *best_candidate = NULL;
612 int best_dist = FC_INFINITY, dist;
614 players_iterate(pplayer) {
615 if (client_has_player() && pplayer != client_player()) {
616 continue;
619 unit_list_iterate(pplayer->units, punit) {
620 if (utype == unit_type(punit)
621 && FOCUS_AVAIL == punit->client.focus_status
622 && 0 < punit->moves_left
623 && !punit->done_moving && !punit->ai_controlled) {
624 dist = sq_map_distance(unit_tile(punit), ptile);
625 if (dist < best_dist) {
626 best_candidate = punit;
627 best_dist = dist;
630 } unit_list_iterate_end;
631 } players_iterate_end;
632 return best_candidate;
635 /**************************************************************************
636 Action for button 'find units' in units report
637 **************************************************************************/
638 void units_report::find_units()
640 struct tile *ptile;
641 struct unit *punit;
642 struct unit_type *utype;
644 utype = utype_by_number(uid);
645 ptile = get_center_tile_mapcanvas();
646 if ((punit = find_nearest_unit(utype, ptile))) {
647 center_tile_mapcanvas(unit_tile(punit));
649 if (ACTIVITY_IDLE == punit->activity
650 || ACTIVITY_SENTRY == punit->activity) {
651 if (can_unit_do_activity(punit, ACTIVITY_IDLE)) {
652 unit_focus_set_and_select(punit);
658 /**************************************************************************
659 Upgrades selected units after clicking 'upgrade' button
660 **************************************************************************/
661 void units_report::upgrade_units()
664 struct unit_type *utype;
665 struct unit_type *upgrade;
666 utype = utype_by_number(uid);
667 int price;
668 QMessageBox ask;
669 QString s1, s2;
670 int ret;
671 char buf[1024];
672 char buf2[2048];
674 upgrade = can_upgrade_unittype(client_player(), utype);
675 price = unit_upgrade_price(client_player(), utype, upgrade);
676 fc_snprintf(buf, ARRAY_SIZE(buf), PL_("Treasury contains %d gold.",
677 "Treasury contains %d gold.",
678 client_player()->economic.gold),
679 client_player()->economic.gold);
680 fc_snprintf(buf2, ARRAY_SIZE(buf2),
681 PL_("Upgrade as many %s to %s as possible "
682 "for %d gold each?\n%s",
683 "Upgrade as many %s to %s as possible "
684 "for %d gold each?\n%s", price),
685 utype_name_translation(utype),
686 utype_name_translation(upgrade), price, buf);
687 s2 = QString(buf2);
688 ask.setText(s2);
689 ask.setStandardButtons(QMessageBox::Cancel | QMessageBox::Ok);
690 ask.setDefaultButton(QMessageBox::Cancel);
691 ask.setWindowTitle(_("Upgrade Obsolete Units"));
692 ret = ask.exec();
694 switch (ret) {
695 case QMessageBox::Cancel:
696 return;
697 case QMessageBox::Ok:
698 dsend_packet_unit_type_upgrade(&client.conn, utype_number(utype));
699 return;
703 /**************************************************************************
704 Action for changed selection in units report
705 **************************************************************************/
706 void units_report::selection_changed(const QItemSelection& sl,
707 const QItemSelection& ds)
709 QTableWidgetItem *itm;
710 int i;
711 QVariant qvar;
712 struct unit_type *utype;
713 find_button->setEnabled(false);
714 upgrade_button->setEnabled(false);
716 if (sl.isEmpty()) {
717 return;
720 curr_row = sl.indexes().at(0).row();
721 if (curr_row >= 0 && curr_row < max_row) {
722 itm = units_widget->item(curr_row, 0);
723 qvar = itm->data(Qt::UserRole);
724 uid = qvar.toInt();
725 utype = utype_by_number(uid);
726 itm = units_widget->item(curr_row, 3);
727 i = itm->text().toInt();
728 if (i > 0) {
729 find_button->setEnabled(true);
731 if (can_client_issue_orders()
732 && NULL != can_upgrade_unittype(client_player(), utype)) {
733 upgrade_button->setEnabled(true);
738 /**************************************************************************
739 Constructor for eceonmy report
740 **************************************************************************/
741 eco_report::eco_report(): QWidget()
743 QGridLayout *eco_layout = new QGridLayout;
744 eco_widget = new QTableWidget;
745 disband_button = new QPushButton;
746 sell_button = new QPushButton;
747 sell_redun_button = new QPushButton;
748 eco_label = new QLabel;
750 QStringList slist;
751 slist << _("Type") << Q_("?Building or Unit type:Name") << _("Redundant")
752 << _("Count") << _("Cost") << _("U Total");
753 eco_widget->setColumnCount(slist.count());
754 eco_widget->setHorizontalHeaderLabels(slist);
755 eco_widget->setProperty("showGrid", "false");
756 eco_widget->setProperty("selectionBehavior", "SelectRows");
757 eco_widget->setEditTriggers(QAbstractItemView::NoEditTriggers);
758 eco_widget->horizontalHeader()->resizeSections(QHeaderView::Stretch);
759 eco_widget->verticalHeader()->setVisible(false);
760 eco_widget->setSelectionMode(QAbstractItemView::SingleSelection);
761 disband_button->setText(_("_Disband"));
762 disband_button->setEnabled(false);
763 sell_button->setText(_("Sell _All"));
764 sell_button->setEnabled(false);
765 sell_redun_button->setText(_("Sell _Redundant"));
766 sell_redun_button->setEnabled(false);
767 eco_layout->addWidget(eco_widget, 1, 0, 5, 5);
768 eco_layout->addWidget(disband_button, 0, 0, 1, 1);
769 eco_layout->addWidget(sell_button, 0, 1, 1, 1);
770 eco_layout->addWidget(sell_redun_button, 0, 2, 1, 1);
771 eco_layout->addWidget(eco_label, 6, 0, 1, 5);
773 connect(disband_button, SIGNAL(pressed()), SLOT(disband_units()));
774 connect(sell_button, SIGNAL(pressed()), SLOT(sell_buildings()));
775 connect(sell_redun_button, SIGNAL(pressed()), SLOT(sell_redundant()));
776 connect(eco_widget->selectionModel(),
777 SIGNAL(selectionChanged(const QItemSelection &,
778 const QItemSelection &)),
779 SLOT(selection_changed(const QItemSelection &,
780 const QItemSelection &)));
781 setLayout(eco_layout);
784 /**************************************************************************
785 Destructor for economy report
786 **************************************************************************/
787 eco_report::~eco_report()
789 gui()->remove_repo_dlg("ECO");
790 gui()->remove_place(index);
793 /**************************************************************************
794 Initializes place in tab for economy report
795 **************************************************************************/
796 void eco_report::init()
798 curr_row = -1;
799 index = gui()->gimme_place();
800 gui()->add_game_tab(this, _("Economy"), index);
801 gui()->game_tab_widget->setCurrentIndex(index);
802 gui()->add_repo_dlg("ECO");
805 /**************************************************************************
806 Refresh all widgets for economy report
807 **************************************************************************/
808 void eco_report::update_report()
810 struct improvement_entry building_entries[B_LAST];
811 struct unit_entry unit_entries[U_LAST];
812 int entries_used, building_total, unit_total, tax, i, j;
813 char buf[256];
814 QTableWidgetItem *item;
815 QFont f = QApplication::font();
816 int h;
817 QFontMetrics fm(f);
818 h = fm.height() + 6;
819 QPixmap pix_scaled;
820 eco_widget->setRowCount(0);
821 eco_widget->clearContents();
822 get_economy_report_data(building_entries, &entries_used,
823 &building_total, &tax);
824 for (i = 0; i < entries_used; i++) {
825 struct improvement_entry *pentry = building_entries + i;
826 struct impr_type *pimprove = pentry->type;
827 QPixmap *pix = get_building_sprite(tileset, pimprove)->pm;
828 pix_scaled = pix->scaledToHeight(h);
829 cid cid = cid_encode_building(pimprove);
831 eco_widget->insertRow(i);
832 for (j = 0; j < 6; j++) {
833 item = new QTableWidgetItem;
834 item->setTextAlignment(Qt::AlignHCenter);
835 switch (j) {
836 case 0:
837 item->setData(Qt::DecorationRole, pix_scaled);
838 item->setData(Qt::UserRole, cid);
839 break;
840 case 1:
841 item->setTextAlignment(Qt::AlignLeft);
842 item->setText(improvement_name_translation(pimprove));
843 break;
844 case 2:
845 item->setText(QString::number(pentry->redundant));
846 break;
847 case 3:
848 item->setText(QString::number(pentry->count));
849 break;
850 case 4:
851 item->setText(QString::number(pentry->cost));
852 break;
853 case 5:
854 item->setText(QString::number(pentry->total_cost));
855 break;
857 eco_widget->setItem(i, j, item);
860 max_row = i;
861 get_economy_report_units_data(unit_entries, &entries_used, &unit_total);
862 for (i = 0; i < entries_used; i++) {
863 struct unit_entry *pentry = unit_entries + i;
864 struct unit_type *putype = pentry->type;
865 QPixmap *pix = get_unittype_sprite(tileset, putype,
866 direction8_invalid(), true)->pm;
867 cid cid = cid_encode_unit(putype);
869 eco_widget->insertRow(i + max_row);
870 for (j = 0; j < 6; j++) {
871 item = new QTableWidgetItem;
872 item->setTextAlignment(Qt::AlignHCenter);
873 switch (j) {
874 case 0:
875 item->setData(Qt::DecorationRole, *pix);
876 item->setData(Qt::UserRole, cid);
877 break;
878 case 1:
879 item->setTextAlignment(Qt::AlignLeft);
880 item->setText(utype_name_translation(putype));
881 break;
882 case 2:
883 item->setText(QString::number(0));
884 break;
885 case 3:
886 item->setText(QString::number(pentry->count));
887 break;
888 case 4:
889 item->setText(QString::number(pentry->cost));
890 break;
891 case 5:
892 item->setText(QString::number(pentry->total_cost));
893 break;
895 eco_widget->setItem(max_row + i, j, item);
898 max_row = max_row + i;
899 fc_snprintf(buf, sizeof(buf), _("Income: %d Total Costs: %d"),
900 tax, building_total + unit_total);
901 eco_label->setText(buf);
904 /**************************************************************************
905 Action for selection changed in economy report
906 **************************************************************************/
907 void eco_report::selection_changed(const QItemSelection & sl,
908 const QItemSelection & ds)
910 QTableWidgetItem *itm;
911 int i;
912 QVariant qvar;
913 struct universal selected;
914 struct impr_type *pimprove;
915 disband_button->setEnabled(false);
916 sell_button->setEnabled(false);
917 sell_redun_button->setEnabled(false);
919 if (sl.isEmpty()) {
920 return;
923 curr_row = sl.indexes().at(0).row();
924 if (curr_row >= 0 && curr_row <= max_row) {
925 itm = eco_widget->item(curr_row, 0);
926 qvar = itm->data(Qt::UserRole);
927 uid = qvar.toInt();
928 selected = cid_decode(uid);
929 switch (selected.kind) {
930 case VUT_IMPROVEMENT:
931 pimprove = selected.value.building;
932 counter = eco_widget->item(curr_row, 3)->text().toInt();
933 if (can_sell_building(pimprove)) {
934 sell_button->setEnabled(true);
936 itm = eco_widget->item(curr_row, 2);
937 i = itm->text().toInt();
938 if (i > 0) {
939 sell_redun_button->setEnabled(true);
941 break;
942 case VUT_UTYPE:
943 counter = eco_widget->item(curr_row, 3)->text().toInt();
944 disband_button->setEnabled(true);
945 break;
946 default:
947 log_error("Not supported type: %d.", selected.kind);
952 /**************************************************************************
953 Disband pointed units (in economy report)
954 **************************************************************************/
955 void eco_report::disband_units()
957 struct universal selected;
959 char buf[1024];
960 QString s;
961 QMessageBox ask;
962 int ret;
963 selected = cid_decode(uid);
964 struct unit_type *putype = selected.value.utype;
965 fc_snprintf(buf, ARRAY_SIZE(buf),
966 _("Do you really wish to disband "
967 "every %s (%d total)?"),
968 utype_name_translation(putype), counter);
970 s = QString(buf);
971 ask.setText(s);
972 ask.setStandardButtons(QMessageBox::Cancel | QMessageBox::Ok);
973 ask.setDefaultButton(QMessageBox::Cancel);
974 ask.setWindowTitle(_("Disband Units"));
975 ret = ask.exec();
976 switch (ret) {
977 case QMessageBox::Cancel:
978 return;
979 case QMessageBox::Ok:
980 disband_all_units(putype, false, buf, sizeof(buf));
981 break;
983 s = QString(buf);
984 ask.setText(s);
985 ask.setStandardButtons(QMessageBox::Ok);
986 ask.setWindowTitle(_("Disband Results"));
987 ask.exec();
990 /**************************************************************************
991 Sell all pointed builings
992 **************************************************************************/
993 void eco_report::sell_buildings()
995 struct universal selected;
996 char buf[1024];
997 QString s;
998 QMessageBox ask;
999 int ret;
1000 selected = cid_decode(uid);
1001 struct impr_type *pimprove = selected.value.building;
1002 fc_snprintf(buf, ARRAY_SIZE(buf),
1003 _("Do you really wish to sell "
1004 "every %s (%d total)?"),
1005 improvement_name_translation(pimprove), counter);
1007 s = QString(buf);
1008 ask.setText(s);
1009 ask.setStandardButtons(QMessageBox::Cancel | QMessageBox::Ok);
1010 ask.setDefaultButton(QMessageBox::Cancel);
1011 ask.setWindowTitle(_("Sell Improvements"));
1012 ret = ask.exec();
1013 switch (ret) {
1014 case QMessageBox::Cancel:
1015 return;
1016 case QMessageBox::Ok:
1017 sell_all_improvements(pimprove, false, buf, sizeof(buf));
1018 break;
1020 s = QString(buf);
1021 ask.setText(s);
1022 ask.setStandardButtons(QMessageBox::Ok);
1023 ask.setWindowTitle(_("Sell-Off: Results"));
1024 ask.exec();
1027 /**************************************************************************
1028 Sells redundant buildings
1029 **************************************************************************/
1030 void eco_report::sell_redundant()
1032 struct universal selected;
1033 char buf[1024];
1034 QString s;
1035 QMessageBox ask;
1036 int ret;
1037 selected = cid_decode(uid);
1038 struct impr_type *pimprove = selected.value.building;
1039 fc_snprintf(buf, ARRAY_SIZE(buf),
1040 _("Do you really wish to sell "
1041 "every redundant %s (%d total)?"),
1042 improvement_name_translation(pimprove), counter);
1044 s = QString(buf);
1045 ask.setText(s);
1046 ask.setStandardButtons(QMessageBox::Cancel | QMessageBox::Ok);
1047 ask.setDefaultButton(QMessageBox::Cancel);
1048 ask.setWindowTitle(_("Sell Improvements"));
1049 ret = ask.exec();
1050 switch (ret) {
1051 case QMessageBox::Cancel:
1052 return;
1053 case QMessageBox::Ok:
1054 sell_all_improvements(pimprove, true, buf, sizeof(buf));
1055 break;
1057 s = QString(buf);
1058 ask.setText(s);
1059 ask.setStandardButtons(QMessageBox::Ok);
1060 ask.setWindowTitle(_("Sell-Off: Results"));
1061 ask.exec();
1064 /**************************************************************************
1065 Constructor for endgame report
1066 **************************************************************************/
1067 endgame_report::endgame_report(const struct packet_endgame_report *packet): QWidget()
1069 QGridLayout *end_layout = new QGridLayout;
1070 end_widget = new QTableWidget;
1071 unsigned int i;
1073 players = 0;
1074 const size_t col_num = packet->category_num + 3;
1075 QStringList slist;
1076 slist << _("Player") << _("Nation") << _("Score");
1077 for (i = 0 ; i < col_num - 3; i++) {
1078 slist << Q_(packet->category_name[i]);
1080 end_widget->setColumnCount(slist.count());
1081 end_widget->setHorizontalHeaderLabels(slist);
1082 end_widget->setProperty("showGrid", "false");
1083 end_widget->setProperty("selectionBehavior", "SelectRows");
1084 end_widget->setEditTriggers(QAbstractItemView::NoEditTriggers);
1085 end_widget->verticalHeader()->setVisible(false);
1086 end_widget->setSelectionMode(QAbstractItemView::SingleSelection);
1087 end_layout->addWidget(end_widget, 1, 0, 5, 5);
1088 setLayout(end_layout);
1092 /**************************************************************************
1093 Destructor for endgame report
1094 **************************************************************************/
1095 endgame_report::~endgame_report()
1097 gui()->remove_repo_dlg("END");
1098 gui()->remove_place(index);
1101 /**************************************************************************
1102 Initializes place in tab for endgame report
1103 **************************************************************************/
1104 void endgame_report::init()
1106 index = gui()->gimme_place();
1107 gui()->add_game_tab(this, _("Score"), index);
1108 gui()->game_tab_widget->setCurrentIndex(index);
1109 gui()->add_repo_dlg("END");
1112 /**************************************************************************
1113 Refresh all widgets for economy report
1114 **************************************************************************/
1115 void endgame_report::update_report(const struct packet_endgame_player *packet)
1117 QTableWidgetItem *item;
1118 QPixmap *pix;
1119 unsigned int i;
1120 const struct player *pplayer = player_by_number(packet->player_id);
1121 const size_t col_num = packet->category_num + 3;
1122 end_widget->insertRow(players);
1123 for (i = 0; i < col_num; i++) {
1124 item = new QTableWidgetItem;
1125 switch (i) {
1126 case 0:
1127 item->setText(player_name(pplayer));
1128 break;
1129 case 1:
1130 pix = get_nation_flag_sprite(tileset, nation_of_player(pplayer))->pm;
1131 if (pix != NULL){
1132 item->setData(Qt::DecorationRole, *pix);
1134 break;
1135 case 2:
1136 item->setText(QString::number(packet->score));
1137 item->setTextAlignment(Qt::AlignHCenter);
1138 break;
1139 default:
1140 item->setText(QString::number(packet->category_score[i-3]));
1141 item->setTextAlignment(Qt::AlignHCenter);
1142 break;
1144 end_widget->setItem(players, i, item);
1146 players++;
1147 end_widget->resizeRowsToContents();
1150 /**************************************************************************
1151 Display the science report. Optionally raise it.
1152 Typically triggered by F6.
1153 **************************************************************************/
1154 void science_report_dialog_popup(bool raise)
1157 science_report *sci_rep;
1158 int i;
1159 QWidget *w;
1161 if (client_is_global_observer()){
1162 return;
1164 if (!gui()->is_repo_dlg_open("SCI")) {
1165 sci_rep = new science_report;
1166 sci_rep->init(raise);
1167 } else {
1168 i = gui()->gimme_index_of("SCI");
1169 fc_assert(i != -1);
1170 if (gui()->game_tab_widget->currentIndex() == i) {
1171 return;
1173 w = gui()->game_tab_widget->widget(i);
1174 sci_rep = reinterpret_cast<science_report*>(w);
1175 if (raise == false) {
1176 gui()->game_tab_widget->change_color(i, Qt::red);
1177 } else {
1178 gui()->game_tab_widget->setCurrentWidget(sci_rep);
1183 /**************************************************************************
1184 Update the economy report.
1185 **************************************************************************/
1186 void real_economy_report_dialog_update(void)
1188 int i;
1189 eco_report *eco_rep;
1190 QWidget *w;
1192 if (gui()->is_repo_dlg_open("ECO")) {
1193 i = gui()->gimme_index_of("ECO");
1194 fc_assert(i != -1);
1195 w = gui()->game_tab_widget->widget(i);
1196 eco_rep = reinterpret_cast<eco_report*>(w);
1197 eco_rep->update_report();
1201 /**************************************************************************
1202 Display the economy report. Optionally raise it.
1203 Typically triggered by F5.
1204 **************************************************************************/
1205 void economy_report_dialog_popup(bool raise)
1207 int i;
1208 eco_report *eco_rep;
1209 QWidget *w;
1210 if (!gui()->is_repo_dlg_open("ECO")) {
1211 eco_rep = new eco_report;
1212 eco_rep->init();
1213 eco_rep->update_report();
1215 else {
1216 i = gui()->gimme_index_of("ECO");
1217 fc_assert(i != -1);
1218 w = gui()->game_tab_widget->widget(i);
1219 eco_rep = reinterpret_cast<eco_report*>(w);
1220 gui()->game_tab_widget->setCurrentWidget(eco_rep);
1224 /**************************************************************************
1225 Update the units report.
1226 **************************************************************************/
1227 void real_units_report_dialog_update(void)
1229 int i;
1230 units_report *units_rep;
1231 QWidget *w;
1233 if (gui()->is_repo_dlg_open("UNI")) {
1234 i = gui()->gimme_index_of("UNI");
1235 fc_assert(i != -1);
1236 w = gui()->game_tab_widget->widget(i);
1237 units_rep = reinterpret_cast<units_report*>(w);
1238 units_rep->update_report();
1242 /**************************************************************************
1243 Display the units report. Optionally raise it.
1244 Typically triggered by F2.
1245 **************************************************************************/
1246 void units_report_dialog_popup(bool raise)
1248 int i;
1249 units_report *ur;
1250 QWidget *w;
1251 if (!gui()->is_repo_dlg_open("UNI")) {
1252 units_report *units_rep = new units_report;
1253 units_rep->init();
1254 units_rep->update_report();
1255 } else {
1256 i = gui()->gimme_index_of("UNI");
1257 fc_assert(i != -1);
1258 w = gui()->game_tab_widget->widget(i);
1259 ur = reinterpret_cast<units_report*>(w);
1260 gui()->game_tab_widget->setCurrentWidget(ur);
1264 /****************************************************************************
1265 Show a dialog with player statistics at endgame.
1266 ****************************************************************************/
1267 void endgame_report_dialog_start(const struct packet_endgame_report *packet)
1269 endgame_report *end_rep;
1270 end_rep = new endgame_report(packet);
1271 end_rep->init();
1274 /****************************************************************************
1275 Received endgame report information about single player.
1276 ****************************************************************************/
1277 void endgame_report_dialog_player(const struct packet_endgame_player *packet)
1279 int i;
1280 endgame_report *end_rep;
1281 QWidget *w;
1283 if (gui()->is_repo_dlg_open("END")) {
1284 i = gui()->gimme_index_of("END");
1285 fc_assert(i != -1);
1286 w = gui()->game_tab_widget->widget(i);
1287 end_rep = reinterpret_cast<endgame_report*>(w);
1288 end_rep->update_report(packet);
1292 /****************************************************************************
1293 Resize and redraw the requirement tree.
1294 ****************************************************************************/
1295 void science_report_dialog_redraw(void)
1297 int i;
1298 science_report *sci_rep;
1299 QWidget *w;
1301 if (gui()->is_repo_dlg_open("SCI")) {
1302 i = gui()->gimme_index_of("SCI");
1303 fc_assert(i != -1);
1304 w = gui()->game_tab_widget->widget(i);
1305 sci_rep = reinterpret_cast<science_report*>(w);
1306 sci_rep->redraw();