diff --git a/client/views/view_units.cpp b/client/views/view_units.cpp index cd61d69396..55f1a41989 100644 --- a/client/views/view_units.cpp +++ b/client/views/view_units.cpp @@ -2,6 +2,7 @@ * SPDX-License-Identifier: GPL-3.0-or-later * SPDX-FileCopyrightText: Freeciv21 and Freeciv contributors * SPDX-FileCopyrightText: James Robertson + * SPDX-FileCopyrightText: Tobias Rehbein */ /** @@ -67,8 +68,10 @@ units_view::units_view() : QWidget() // Configure the unitwaittime table slist.clear(); - slist << _("Type") << _("Name") << _("Location") << _("Time Left"); + slist << _("Type") << _("Name") << _("Location") << _("Time Left") + << _("Id"); ui.uwt_widget->setColumnCount(slist.count()); + ui.uwt_widget->setColumnHidden(4, true); ui.uwt_widget->setHorizontalHeaderLabels(slist); ui.uwt_widget->setSortingEnabled(true); ui.uwt_widget->setAlternatingRowColors(true); @@ -299,57 +302,86 @@ void units_view::update_waiting() QFontMetrics fm(f); int h = fm.height() + 24; - ui.uwt_widget->setRowCount(0); - ui.uwt_widget->clearContents(); - struct unit_waiting_entry unit_entries[U_LAST]; int entries_used = 0; get_units_waiting_data(unit_entries, &entries_used); - max_row = 0; + max_row = ui.uwt_widget->rowCount(); + + // Remember all units initially in the table. This allows us to distinguish + // between known units we need to update and new units we need to add to + // the table. As we remove all updated units from this map, the remaining + // items are the units we need to remove from the table. + QMap ids_in_table; + for (int r = 0; r < max_row; r++) { + QTableWidgetItem *item = ui.uwt_widget->item(r, 4); + 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; cid id = cid_encode_unit(putype); - - ui.uwt_widget->insertRow(max_row); - for (int j = 0; j < 4; j++) { - auto item = new QTableWidgetItem; - switch (j) { - case 0: - // Unit type image sprite - { - auto sprite = - get_unittype_sprite(tileset, putype, direction8_invalid()) - ->scaledToHeight(h); - QLabel *lbl = new QLabel; - lbl->setPixmap(QPixmap(sprite)); - lbl->setAlignment(Qt::AlignVCenter | Qt::AlignHCenter); - ui.uwt_widget->setCellWidget(i, j, lbl); + QString unit_id = QString("%1").arg(pentry->id); + QString unit_waittime = format_simple_duration(abs(pentry->timer)); + + if (!ids_in_table.contains(unit_id)) { + // Create a new row for the unit + ui.uwt_widget->insertRow(max_row); + for (int j = 0; j < 5; j++) { + auto item = new QTableWidgetItem; + switch (j) { + case 0: + // Unit type image sprite + { + auto sprite = + get_unittype_sprite(tileset, putype, direction8_invalid()) + ->scaledToHeight(h); + QLabel *lbl = new QLabel; + lbl->setPixmap(QPixmap(sprite)); + lbl->setAlignment(Qt::AlignVCenter | Qt::AlignHCenter); + ui.uwt_widget->setCellWidget(i, j, lbl); + } + item->setData(Qt::UserRole, id); + break; + case 1: + // Unit type name + item->setTextAlignment(Qt::AlignLeft | Qt::AlignVCenter); + item->setText(utype_name_translation(putype)); + break; + case 2: + // # Location + item->setTextAlignment(Qt::AlignLeft | Qt::AlignVCenter); + item->setText(QString(_("%1")).arg(pentry->city_name)); + break; + case 3: + // # Time Left + item->setTextAlignment(Qt::AlignLeft | Qt::AlignVCenter); + item->setText(QString(_("%1")).arg(unit_waittime)); + break; + case 4: + // # Id + item->setTextAlignment(Qt::AlignRight | Qt::AlignVCenter); + item->setText(QString("%1").arg(unit_id)); + break; } - item->setData(Qt::UserRole, id); - break; - case 1: - // Unit type name - item->setTextAlignment(Qt::AlignLeft | Qt::AlignVCenter); - item->setText(utype_name_translation(putype)); - break; - case 2: - // # Location - item->setTextAlignment(Qt::AlignLeft | Qt::AlignVCenter); - item->setText(QString(_("%1")).arg(pentry->city_name)); - break; - case 3: - // # Time Left - item->setTextAlignment(Qt::AlignLeft | Qt::AlignVCenter); - item->setText(QString(_("%1")).arg( - format_simple_duration(abs(pentry->timer)))); - break; + ui.uwt_widget->setItem(max_row, j, item); } - ui.uwt_widget->setItem(max_row, j, item); + max_row++; + } else { + // Unit is already in table, update the corresponding row. + int row = ids_in_table[unit_id]->row(); + ui.uwt_widget->item(row, 3)->setText(unit_waittime); + ids_in_table.remove(unit_id); } - max_row++; + } + + // Delete units initially in the table, but not waiting anymore. + for (int i = 0; i < ids_in_table.values().size(); i++) { + int row = ids_in_table.values()[i]->row(); + ui.uwt_widget->removeRow(row); + max_row--; } if (max_row == 0) { @@ -649,6 +681,7 @@ void get_units_waiting_data(struct unit_waiting_entry *entries, 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)++; } diff --git a/client/views/view_units.h b/client/views/view_units.h index 999fbc73f4..cbb0f61330 100644 --- a/client/views/view_units.h +++ b/client/views/view_units.h @@ -1,6 +1,7 @@ /* * SPDX-License-Identifier: GPL-3.0-or-later * SPDX-FileCopyrightText: James Robertson + * SPDX-FileCopyrightText: Tobias Rehbein */ #pragma once @@ -35,6 +36,7 @@ struct unit_waiting_entry { const struct unit_type *type; time_t timer; QString city_name; + int id; }; void get_units_view_data(struct unit_view_entry *entries,