Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix a crash in the units view #2416

Merged
merged 2 commits into from
Oct 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
138 changes: 61 additions & 77 deletions client/views/view_units.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -150,10 +150,7 @@ void units_view::update_units()
QFontMetrics fm(f);
int h = fm.height() + 24;

int entries_used = 0; // Position in the units array
struct unit_view_entry unit_entries[U_LAST];

get_units_view_data(unit_entries, &entries_used);
auto unit_entries = get_units_view_data();

// Variables for the nested loops
int total_count = 0; // Sum of unit type
Expand Down Expand Up @@ -185,9 +182,9 @@ void units_view::update_units()
unittypes_in_table[key] = ui.units_table->item(r, 0);
}

for (int i = 0; i < entries_used; i++) {
struct unit_view_entry *pentry = unit_entries + i;
const struct unit_type *putype = pentry->type;
for (int i = 0; i < unit_entries.size(); i++) {
const unit_view_entry &entry = unit_entries[i];
const struct unit_type *putype = entry.type;
cid id = cid_encode_unit(putype);

auto existing_row_for_unittype = unittypes_in_table.find(id);
Expand Down Expand Up @@ -223,7 +220,7 @@ void units_view::update_units()
case 2:
// Is Upgradable
item->setTextAlignment(Qt::AlignVCenter | Qt::AlignHCenter);
if (pentry->upg) {
if (entry.upg) {
item->setData(Qt::DisplayRole, "★");
upg_count++;
} else {
Expand All @@ -233,44 +230,44 @@ void units_view::update_units()
case 3:
// # In Progress
item->setTextAlignment(Qt::AlignVCenter | Qt::AlignHCenter);
item->setData(Qt::DisplayRole, pentry->in_prod);
in_progress += pentry->in_prod;
item->setData(Qt::DisplayRole, entry.in_prod);
in_progress += entry.in_prod;
break;
case 4:
// # Active
item->setTextAlignment(Qt::AlignVCenter | Qt::AlignHCenter);
item->setData(Qt::DisplayRole, pentry->count);
total_count += pentry->count;
item->setData(Qt::DisplayRole, entry.count);
total_count += entry.count;
break;
case 5:
// Shield upkeep
item->setTextAlignment(Qt::AlignVCenter | Qt::AlignHCenter);
if (pentry->shield_cost == 0) {
if (entry.shield_cost == 0) {
item->setText("-");
} else {
item->setData(Qt::DisplayRole, pentry->shield_cost);
item->setData(Qt::DisplayRole, entry.shield_cost);
}
total_shield += pentry->shield_cost;
total_shield += entry.shield_cost;
break;
case 6:
// Food upkeep
item->setTextAlignment(Qt::AlignVCenter | Qt::AlignHCenter);
if (pentry->food_cost == 0) {
if (entry.food_cost == 0) {
item->setText("-");
} else {
item->setData(Qt::DisplayRole, pentry->food_cost);
item->setData(Qt::DisplayRole, entry.food_cost);
}
total_food += pentry->food_cost;
total_food += entry.food_cost;
break;
case 7:
// Gold upkeep
item->setTextAlignment(Qt::AlignVCenter | Qt::AlignHCenter);
if (pentry->gold_cost == 0) {
if (entry.gold_cost == 0) {
item->setText("-");
} else {
item->setData(Qt::DisplayRole, pentry->gold_cost);
item->setData(Qt::DisplayRole, entry.gold_cost);
}
total_gold += pentry->gold_cost;
total_gold += entry.gold_cost;
break;
}
ui.units_table->setItem(current_row, j, item);
Expand Down Expand Up @@ -355,10 +352,7 @@ void units_view::update_waiting()
QFontMetrics fm(f);
int h = fm.height() + 24;

struct unit_waiting_entry unit_entries[U_LAST];

int entries_used = 0;
get_units_waiting_data(unit_entries, &entries_used);
auto unit_entries = get_units_waiting_data();

max_row = ui.uwt_table->rowCount();

Expand All @@ -372,12 +366,12 @@ void units_view::update_waiting()
ids_in_table[item->text()] = item;
}

for (int i = 0; i < entries_used; i++) {
struct unit_waiting_entry *pentry = unit_entries + i;
const struct unit_type *putype = pentry->type;
for (int i = 0; i < unit_entries.size(); i++) {
const unit_waiting_entry &entry = unit_entries[i];
const struct unit_type *putype = entry.type;
cid id = cid_encode_unit(putype);
QString unit_id = QString("%1").arg(pentry->id);
QString unit_waittime = format_simple_duration(abs(pentry->timer));
QString unit_id = QString("%1").arg(entry.id);
QString unit_waittime = format_simple_duration(abs(entry.timer));

if (!ids_in_table.contains(unit_id)) {
// Create a new row for the unit
Expand Down Expand Up @@ -406,7 +400,7 @@ void units_view::update_waiting()
case 2:
// # Location
item->setTextAlignment(Qt::AlignLeft | Qt::AlignVCenter);
item->setText(QString(_("%1")).arg(pentry->city_name));
item->setText(QString(_("%1")).arg(entry.city_name));
break;
case 3:
// # Time Left
Expand Down Expand Up @@ -644,10 +638,9 @@ struct unit *find_nearest_unit(const struct unit_type *utype,
/**
* Returns an array of units data.
*/
void get_units_view_data(struct unit_view_entry *entries,
int *num_entries_used)
std::vector<unit_view_entry> get_units_view_data()
{
*num_entries_used = 0;
auto entries = std::vector<unit_view_entry>();

players_iterate(pplayer)
{
Expand Down Expand Up @@ -696,72 +689,61 @@ void get_units_view_data(struct unit_view_entry *entries,
continue;
}

entries[*num_entries_used].type = unittype;
entries[*num_entries_used].count = count;
entries[*num_entries_used].in_prod = in_progress;
entries[*num_entries_used].upg = upgradable;
entries[*num_entries_used].gold_cost = gold_cost;
entries[*num_entries_used].food_cost = food_cost;
entries[*num_entries_used].shield_cost = shield_cost;
(*num_entries_used)++;
entries.push_back({.type = unittype,
.count = count,
.in_prod = in_progress,
.food_cost = food_cost,
.gold_cost = gold_cost,
.shield_cost = shield_cost,
.upg = upgradable});
}
unit_type_iterate_end;
}
players_iterate_end;

std::sort(entries, entries + *num_entries_used,
[](const auto &lhs, const auto &rhs) {
return QString::localeAwareCompare(
utype_name_translation(lhs.type),
utype_name_translation(rhs.type))
< 0;
});
std::sort(
entries.begin(), entries.end(), [](const auto &lhs, const auto &rhs) {
return QString::localeAwareCompare(utype_name_translation(lhs.type),
utype_name_translation(rhs.type))
< 0;
});
return entries;
}

/**
* Returns an array of units subject to unitwaittime.
*/
void get_units_waiting_data(struct unit_waiting_entry *entries,
int *num_entries_used)
std::vector<unit_waiting_entry> get_units_waiting_data()
{
*num_entries_used = 0;

if (nullptr == client.conn.playing) {
return;
return {};
}

int pcity_near_dist = 0; // Init distance
auto entries = std::vector<unit_waiting_entry>();

unit_list_iterate(client.conn.playing->units, punit)
{
int pcity_near_dist = 0; // Init distance
struct city *pcity_near = get_nearest_city(punit, &pcity_near_dist);

if (!can_unit_move_now(punit) && punit->ssa_controller == SSA_NONE) {

entries[*num_entries_used].type = punit->utype;
entries[*num_entries_used].city_name =
get_nearest_city_text(pcity_near, pcity_near_dist);
entries[*num_entries_used].timer =
time(nullptr) - punit->action_timestamp;
entries[*num_entries_used].id = punit->id;

(*num_entries_used)++;
}

// Skip unused unit types
if (*num_entries_used == 0) {
continue;
entries.push_back(
{.type = punit->utype,
.timer = time(nullptr) - punit->action_timestamp,
.city_name = get_nearest_city_text(pcity_near, pcity_near_dist),
.id = punit->id});
}
}
unit_list_iterate_end;

std::sort(entries, entries + *num_entries_used,
[](const auto &lhs, const auto &rhs) {
return QString::localeAwareCompare(
utype_name_translation(lhs.type),
utype_name_translation(rhs.type))
< 0;
});
std::sort(
entries.begin(), entries.end(), [](const auto &lhs, const auto &rhs) {
return QString::localeAwareCompare(utype_name_translation(lhs.type),
utype_name_translation(rhs.type))
< 0;
});

return entries;
}

/************************************
Expand All @@ -782,7 +764,9 @@ void units_view_dialog_update(void *unused)
if (queen()->game_tab_widget->currentIndex() == i) {
w = queen()->game_tab_widget->widget(i);
uv = reinterpret_cast<units_view *>(w);
uv->update_view();
if (uv) {
uv->update_view();
}
}
}
queen()->updateSidebarTooltips();
Expand Down
8 changes: 2 additions & 6 deletions client/views/view_units.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ struct unit_view_entry {
int count, in_prod, total_cost, food_cost, gold_cost, shield_cost;
bool upg;
};
std::vector<unit_view_entry> get_units_view_data();

/**
* Structure of unit waiting data for the Units View.
Expand All @@ -38,12 +39,7 @@ struct unit_waiting_entry {
QString city_name;
int id;
};

void get_units_view_data(struct unit_view_entry *entries,
int *num_entries_used);

void get_units_waiting_data(struct unit_waiting_entry *entries,
int *num_entries_used);
std::vector<unit_waiting_entry> get_units_waiting_data();

void units_view_dialog_update(void *unused);

Expand Down
Loading