#include "MultiBuildingContent.h" #include #include #include "Building.h" #include "BuildingIconCache.h" #include "ClearBeltControl.h" #include "CountRow.h" #include "FactoryQueries.h" #include "GameConfig.h" #include "SelectionNames.h" #include "Simulation.h" #include "StatRow.h" namespace { // Size the type symbol is drawn at on a count row, matching the card header's chip. const int kCountSymbolSizePx = 20; } // namespace MultiBuildingContent::MultiBuildingContent(const SelectionContext& context, const SelectionRequest& request, QWidget* parent) : SelectionContent(context, std::nullopt, parent) , m_ids(request.buildings) { // The header names the size of the selection instead of an object // (REQ-UI-MULTI-SELECTION). setIdentity(QPixmap(), tr("%1 buildings").arg(static_cast(m_ids.size()))); buildSummary(); // A selection holding any belt-subsystem tile can still be cleared as a whole // (REQ-UI-BELT-CLEAR), even though the mixture is what kept it from aggregating. bool hasBeltTile = false; for (BuildingId id : m_ids) { const Building* building = findBuilding(context.sim->getFactoryState(), id); if (building && isBeltSubsystemType(building->type)) { hasBeltTile = true; break; } } if (hasBeltTile) { getRuntimeLayout()->addWidget(new ClearBeltControl(context, m_ids, this)); } } void MultiBuildingContent::buildSummary() { std::map counts; for (BuildingId id : m_ids) { const Building* building = findBuilding(getContext().sim->getFactoryState(), id); if (building) { counts[building->type]++; continue; } const ConstructionSite* site = findSite(getContext().sim->getFactoryState(), id); if (site) { counts[site->type]++; } } int totalCost = 0; for (const std::pair& entry : counts) { getRuntimeLayout()->addWidget(new CountRow( getContext().buildingIcons->getChip(buildingTypeId(entry.first), kCountSymbolSizePx), getBuildingTypeName(entry.first), entry.second, this)); // Only player-placeable buildings count toward the total; the HQ and defence // stations are excluded (REQ-UI-MULTI-SELECTION). A construction site counts at // its type's full placement cost regardless of progress. const BuildingDef* def = getContext().config->buildings.findBuildingDef(entry.first); if (def && def->playerPlaceable) { totalCost += def->cost * entry.second; } } StatRow* totalRow = new StatRow(tr("Total cost"), this); totalRow->setValue(QString::number(totalCost)); totalRow->setValueEmphasized(true); getRuntimeLayout()->addWidget(totalRow); }