43 QFont font =
ui.units_table->horizontalHeader()->font();
44 font.setWeight(QFont::Bold);
45 ui.units_table->horizontalHeader()->setFont(font);
46 ui.uwt_table->horizontalHeader()->setFont(font);
50 slist <<
_(
"Type") <<
_(
"Name") <<
_(
"★ Upgradable")
51 <<
_(
"⚒ In Progress") <<
_(
"⚔ Active") <<
_(
"Shield Upkeep")
52 <<
_(
"Food Upkeep") <<
_(
"Gold Upkeep");
53 ui.units_label->setText(QString(
_(
"Units:")));
54 ui.units_table->setColumnCount(slist.count());
55 ui.units_table->setHorizontalHeaderLabels(slist);
56 ui.units_table->setSortingEnabled(
false);
57 ui.units_table->setAlternatingRowColors(
true);
58 ui.upg_but->setText(
_(
"Upgrade"));
59 ui.upg_but->setToolTip(
_(
"Upgrade selected unit."));
60 ui.upg_but->setDisabled(
true);
61 ui.find_but->setText(
_(
"Find Nearest"));
62 ui.find_but->setToolTip(
_(
"Center the map on the nearest unit in relation "
63 "to where the map is now."));
64 ui.find_but->setDisabled(
true);
65 ui.disband_but->setText(
_(
"Disband All"));
66 ui.disband_but->setToolTip(
_(
"Disband all of the selected unit."));
67 ui.disband_but->setDisabled(
true);
71 slist <<
_(
"Type") <<
_(
"Name") <<
_(
"Location") <<
_(
"Time Left")
73 ui.uwt_table->setColumnCount(slist.count());
74 ui.uwt_table->setColumnHidden(4,
true);
75 ui.uwt_table->setHorizontalHeaderLabels(slist);
76 ui.uwt_table->setSortingEnabled(
true);
77 ui.uwt_table->setAlternatingRowColors(
true);
78 ui.uwt_label->setText(
"Units Waiting:");
86 auto equalHeight = std::max(
ui.units_widget->minimumSizeHint().height(),
87 ui.uwt_widget->minimumSizeHint().height());
88 ui.splitter->setSizes({equalHeight, equalHeight});
93 "citybar.shields",
"",
"",
false);
94 ui.units_table->horizontalHeaderItem(5)->setIcon(
crop_sprite(spr));
98 "citybar.food",
"",
"",
false);
99 ui.units_table->horizontalHeaderItem(6)->setIcon(
crop_sprite(spr));
103 "citybar.trade",
"",
"",
false);
104 ui.units_table->horizontalHeaderItem(7)->setIcon(
crop_sprite(spr));
106 connect(
ui.upg_but, &QAbstractButton::pressed,
this,
108 connect(
ui.find_but, &QAbstractButton::pressed,
this,
110 connect(
ui.disband_but, &QAbstractButton::pressed,
this,
112 connect(
ui.units_table->selectionModel(),
113 &QItemSelectionModel::selectionChanged,
this,
115 setLayout(
ui.units_layout);
135 QTimer *timer =
new QTimer(
this);
149 QFont f = QApplication::font();
151 int h = fm.height() + 24;
160 int total_shield = 0;
162 int max_row =
ui.units_table->rowCount();
175 std::map<cid, QTableWidgetItem *> unittypes_in_table;
176 for (
int r = 0; r <
ui.units_table->rowCount(); r++) {
177 QTableWidgetItem *
item =
ui.units_table->item(r, 0);
180 cid key = (
cid)
item->data(Qt::UserRole).toInt(&ok);
182 unittypes_in_table[key] =
ui.units_table->item(r, 0);
185 for (
int i = 0; i < unit_entries.size(); i++) {
190 auto existing_row_for_unittype = unittypes_in_table.find(
id);
191 bool new_row = existing_row_for_unittype == unittypes_in_table.end();
196 current_row = existing_row_for_unittype->second->row();
199 for (
int j = 0; j < 8; j++) {
200 QTableWidgetItem *
item =
new QTableWidgetItem;
208 QLabel *lbl =
new QLabel;
209 lbl->setPixmap(QPixmap(sprite));
210 lbl->setAlignment(Qt::AlignVCenter | Qt::AlignHCenter);
211 ui.units_table->setCellWidget(current_row, j, lbl);
213 item->setData(Qt::UserRole,
id);
217 item->setTextAlignment(Qt::AlignLeft | Qt::AlignVCenter);
222 item->setTextAlignment(Qt::AlignVCenter | Qt::AlignHCenter);
224 item->setData(Qt::DisplayRole,
"★");
227 item->setData(Qt::DisplayRole,
"-");
232 item->setTextAlignment(Qt::AlignVCenter | Qt::AlignHCenter);
233 item->setData(Qt::DisplayRole,
entry.in_prod);
234 in_progress +=
entry.in_prod;
238 item->setTextAlignment(Qt::AlignVCenter | Qt::AlignHCenter);
239 item->setData(Qt::DisplayRole,
entry.count);
240 total_count +=
entry.count;
244 item->setTextAlignment(Qt::AlignVCenter | Qt::AlignHCenter);
245 if (
entry.shield_cost == 0) {
248 item->setData(Qt::DisplayRole,
entry.shield_cost);
250 total_shield +=
entry.shield_cost;
254 item->setTextAlignment(Qt::AlignVCenter | Qt::AlignHCenter);
255 if (
entry.food_cost == 0) {
258 item->setData(Qt::DisplayRole,
entry.food_cost);
260 total_food +=
entry.food_cost;
264 item->setTextAlignment(Qt::AlignVCenter | Qt::AlignHCenter);
265 if (
entry.gold_cost == 0) {
268 item->setData(Qt::DisplayRole,
entry.gold_cost);
270 total_gold +=
entry.gold_cost;
273 ui.units_table->setItem(current_row, j,
item);
279 unittypes_in_table.erase(
id);
284 for (
const auto &[
_, value] : unittypes_in_table) {
285 ui.units_table->removeRow(value->row());
292 for (
int j = 0; j < 8; j++) {
293 QTableWidgetItem *item_totals =
new QTableWidgetItem;
297 item_totals->setTextAlignment(Qt::AlignRight);
298 item_totals->setText(
_(
"--------------------\nTotals:"));
302 item_totals->setTextAlignment(Qt::AlignCenter);
303 item_totals->setText(QString(
_(
"------\n%1")).arg(upg_count));
307 item_totals->setTextAlignment(Qt::AlignCenter);
308 item_totals->setText(QString(
_(
"------\n%1")).arg(in_progress));
311 item_totals->setTextAlignment(Qt::AlignCenter);
312 item_totals->setText(QString(
_(
"------\n%1")).arg(total_count));
315 item_totals->setTextAlignment(Qt::AlignCenter);
316 item_totals->setText(QString(
_(
"------\n%1")).arg(total_shield));
319 item_totals->setTextAlignment(Qt::AlignCenter);
320 item_totals->setText(QString(
_(
"------\n%1")).arg(total_food));
323 item_totals->setTextAlignment(Qt::AlignCenter);
324 item_totals->setText(QString(
_(
"------\n%1")).arg(total_gold));
327 ui.units_table->setItem(
max_row, j, item_totals);
331 ui.units_widget->setHidden(
true);
333 ui.units_widget->setHidden(
false);
334 ui.units_table->resizeRowsToContents();
335 ui.units_table->resizeColumnsToContents();
336 ui.units_table->horizontalHeader()->resizeSections(
337 QHeaderView::ResizeToContents);
338 ui.units_table->verticalHeader()->setSectionResizeMode(
339 QHeaderView::ResizeToContents);
351 QFont f = QApplication::font();
353 int h = fm.height() + 24;
364 for (
int r = 0; r <
max_row; r++) {
365 QTableWidgetItem *
item =
ui.uwt_table->item(r, 4);
369 for (
int i = 0; i < unit_entries.size(); i++) {
373 QString unit_id = QString(
"%1").arg(
entry.id);
376 if (!ids_in_table.contains(unit_id)) {
379 for (
int j = 0; j < 5; j++) {
380 auto item =
new QTableWidgetItem;
388 QLabel *lbl =
new QLabel;
389 lbl->setPixmap(QPixmap(sprite));
390 lbl->setAlignment(Qt::AlignVCenter | Qt::AlignHCenter);
391 ui.uwt_table->setCellWidget(i, j, lbl);
393 item->setData(Qt::UserRole,
id);
397 item->setTextAlignment(Qt::AlignLeft | Qt::AlignVCenter);
402 item->setTextAlignment(Qt::AlignLeft | Qt::AlignVCenter);
403 item->setText(QString(
_(
"%1")).arg(
entry.city_name));
407 item->setTextAlignment(Qt::AlignLeft | Qt::AlignVCenter);
408 item->setText(QString(
_(
"%1")).arg(unit_waittime));
412 item->setTextAlignment(Qt::AlignRight | Qt::AlignVCenter);
413 item->setText(QString(
"%1").arg(unit_id));
421 int row = ids_in_table[unit_id]->row();
422 ui.uwt_table->item(row, 3)->setText(unit_waittime);
423 ids_in_table.remove(unit_id);
428 for (
int i = 0; i < ids_in_table.values().
size(); i++) {
429 int row = ids_in_table.values()[i]->row();
430 ui.uwt_table->removeRow(row);
435 ui.uwt_widget->setHidden(
true);
437 ui.uwt_widget->setHidden(
false);
439 ui.uwt_table->resizeRowsToContents();
440 ui.uwt_table->resizeColumnsToContents();
441 ui.uwt_table->horizontalHeader()->resizeSections(
442 QHeaderView::ResizeToContents);
443 ui.uwt_table->verticalHeader()->setSectionResizeMode(
444 QHeaderView::ResizeToContents);
452 const QItemSelection &ds)
463 QTableWidgetItem *itm;
468 ui.upg_but->setDisabled(
true);
469 ui.disband_but->setDisabled(
true);
470 ui.find_but->setDisabled(
true);
476 curr_row = sl.indexes().at(0).row();
477 max_row =
ui.units_table->rowCount() - 1;
480 qvar = itm->data(Qt::UserRole);
485 ui.disband_but->setDisabled(
false);
486 ui.find_but->setDisabled(
false);
488 upg =
ui.units_table->item(
curr_row, 2)->text();
490 ui.upg_but->setDisabled(
false);
493 ui.upg_but->setDisabled(
true);
510 buf = QString(
_(
"Do you really wish to disband every %1 (%2 total)?"))
515 ask->setStandardButtons(QMessageBox::Cancel | QMessageBox::Yes);
516 ask->setDefaultButton(QMessageBox::Cancel);
517 ask->button(QMessageBox::Yes)->setText(
_(
"Yes Disband"));
518 ask->setAttribute(Qt::WA_DeleteOnClose);
519 connect(ask, &hud_message_box::accepted, [=]() {
528 result->setStandardButtons(QMessageBox::Ok);
529 result->setAttribute(Qt::WA_DeleteOnClose);
553 if (ACTIVITY_IDLE == punit->
activity
554 || ACTIVITY_SENTRY == punit->
activity) {
577 QString b = QString::asprintf(
PL_(
"Treasury contains %d gold.",
578 "Treasury contains %d gold.",
581 QString c = QString::asprintf(
PL_(
"Upgrade as many %s to %s as possible "
582 "for %d gold each?\n%s",
583 "Upgrade as many %s to %s as possible "
584 "for %d gold each?\n%s",
592 ask->setStandardButtons(QMessageBox::Cancel | QMessageBox::Yes);
593 ask->setDefaultButton(QMessageBox::Cancel);
594 ask->button(QMessageBox::Yes)->setText(
_(
"Yes Upgrade"));
595 ask->setAttribute(Qt::WA_DeleteOnClose);
596 connect(ask, &hud_message_box::accepted,
597 [=]() { dsend_packet_unit_type_upgrade(&
client.
conn, type); });
611 struct unit *best_candidate = NULL;
624 && 0 < punit->moves_left && !punit->done_moving
625 && punit->ssa_controller == SSA_NONE) {
627 if (dist < best_dist) {
628 best_candidate = punit;
637 return best_candidate;
645 auto entries = std::vector<unit_view_entry>();
660 bool upgradable =
false;
671 if (punit->homecity != 0) {
672 gold_cost += punit->upkeep[
O_GOLD];
673 food_cost += punit->upkeep[
O_FOOD];
674 shield_cost += punit->upkeep[
O_SHIELD];
682 if (pcity->production.value.utype == unittype
683 && pcity->production.kind == VUT_UTYPE) {
690 if (count == 0 && in_progress == 0) {
694 entries.push_back({.type = unittype,
696 .in_prod = in_progress,
697 .food_cost = food_cost,
698 .gold_cost = gold_cost,
699 .shield_cost = shield_cost,
707 entries.begin(), entries.end(), [](
const auto &lhs,
const auto &rhs) {
708 return QString::localeAwareCompare(utype_name_translation(lhs.type),
709 utype_name_translation(rhs.type))
724 auto entries = std::vector<unit_waiting_entry>();
728 int pcity_near_dist = 0;
733 {.type = punit->utype,
734 .timer = time(
nullptr) - punit->action_timestamp,
742 entries.begin(), entries.end(), [](
const auto &lhs,
const auto &rhs) {
743 return QString::localeAwareCompare(utype_name_translation(lhs.type),
744 utype_name_translation(rhs.type))
764 if (
queen()->isRepoDlgOpen(QStringLiteral(
"UNI"))) {
766 if (
queen()->game_tab_widget->currentIndex() == i) {
786 if (!
queen()->isRepoDlgOpen(QStringLiteral(
"UNI"))) {
794 if (w->isVisible()) {
814 if (
queen()->isRepoDlgOpen(QStringLiteral(
"UNI"))) {
QPixmap crop_sprite(const QPixmap *sprite)
Helper function to crop a sprite.
#define city_list_iterate(citylist, pcity)
#define city_list_iterate_end
void set_text_title(const QString &s1, const QString &s2)
Sets text and title and shows message box.
void center_on_tile(tile *tile, bool animate=true)
Centers the view on a tile.
int gimmeIndexOf(const QString &str)
Returns index on game tab page of given report dialog.
int addGameTab(QWidget *widget)
Inserts tab widget to game view page.
void removeRepoDlg(const QString &str)
Removes report dialog string from the list marking it as closed.
void updateSidebarTooltips()
Updates top bar tooltips.
void gimmePlace(QWidget *widget, const QString &str)
Finds not used index on game_view_tab and returns it.
fc_game_tab_widget * game_tab_widget
Table widget to display units view (F2)
void update_buttons(const QItemSelection &sl)
Updates the buttons according to the item selection sl in the units table.
void init()
Initializes place in tab for units view.
void disband_units()
Disband selected units.
void update_waiting()
Function to load the units waiting table.
void update_view()
Refresh all widgets for units view.
void update_units()
Updates the units table.
void find_nearest()
Find nearest selected unit, closest units view when button is clicked.
units_view()
Constructor for units view.
void upgrade_units()
Upgrade selected units.
void selection_changed(const QItemSelection &sl, const QItemSelection &ds)
Action for selection changed in units view.
~units_view()
Destructor for units view.
bool client_has_player()
Either controlling or observing.
struct player * client_player()
Either controlling or observing.
struct city * get_nearest_city(const struct unit *punit, int *sq_dist)
Find city nearest to given unit and optionally return squared city distance Parameter sq_dist may be ...
struct universal cid_decode(cid id)
Decode the CID into a city_production structure.
cid cid_encode_unit(const struct unit_type *punittype)
Encode a CID for the target unit type.
void unit_focus_set_and_select(struct unit *punit)
The only difference is that here we draw the "cross".
class fc_client * king()
Return fc_client instance.
#define PL_(String1, String2, n)
bool can_unit_move_now(const struct unit *punit)
Returns if unit can move now.
constexpr auto LOG_VERBOSE
#define fc_assert(condition)
#define fc_assert_action(condition, action)
int sq_map_distance(const struct tile *tile0, const struct tile *tile1)
Return squared distance between two tiles.
pageGame * queen()
Return game instandce.
#define players_iterate_end
#define players_iterate(_pplayer)
void disband_all_units(const struct unit_type *punittype, bool in_cities_only, char *message, size_t message_sz)
Disband all supported units of the given type.
Structure of data for the Units View.
Structure of unit waiting data for the Units View.
enum unit_activity activity
const struct unit_type * utype
const QString get_nearest_city_text(struct city *pcity, int sq_dist)
Returns the text describing the city and its distance.
const QPixmap * get_unittype_sprite(const struct tileset *t, const struct unit_type *punittype, enum direction8 facing, const QColor &replace)
Return the sprite for the unit type (the base "unit" sprite).
QPixmap * tiles_lookup_sprite_tag_alt(struct tileset *t, QtMsgType level, const char *tag, const char *alt, const char *what, const char *name, bool scale)
Lookup sprite to match tag, or else to match alt if don't find, or else return nullptr,...
void top_bar_show_map()
Callback to show map.
const struct unit_type * utype
bool can_unit_do_activity(const struct unit *punit, enum unit_activity activity)
Return TRUE iff the unit can do the given untargeted activity at its current location.
#define unit_list_iterate(unitlist, punit)
#define unit_list_iterate_end
const struct unit_type * unit_type_get(const struct unit *punit)
Return the unit type for this unit.
struct unit_type * utype_by_number(const Unit_type_id id)
Return a pointer for the unit type struct for the given unit type id.
const struct unit_type * can_upgrade_unittype(const struct player *pplayer, const struct unit_type *punittype)
Return whether this player can upgrade this unit type (to any other unit type).
const char * utype_name_translation(const struct unit_type *punittype)
Return the (translated) name of the unit type.
Unit_type_id utype_number(const struct unit_type *punittype)
Return the unit type index.
int unit_upgrade_price(const struct player *pplayer, const struct unit_type *from, const struct unit_type *to)
Return the cost (gold) of upgrading a single unit of the specified type to the new type.
#define unit_type_iterate(_p)
#define unit_type_iterate_end
struct tile * get_center_tile_mapcanvas()
Finds the current center tile of the mapcanvas.
std::vector< unit_waiting_entry > get_units_waiting_data()
Returns an array of units subject to unitwaittime.
std::vector< unit_view_entry > get_units_view_data()
Returns an array of units data.
void units_view_dialog_update(void *unused)
Update the units view.
void popdown_units_view()
Closes units view.
struct unit * find_nearest_unit(const struct unit_type *utype, struct tile *ptile)
Function to help us find the nearest unit.
void units_view_dialog_popup()
Display the unis view.