Files
dota_factory/src/ui/selection/MultiBuildingContent.cpp

100 lines
3.0 KiB
C++

#include "MultiBuildingContent.h"
#include <map>
#include <QVBoxLayout>
#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<int>(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<BuildingType, int> 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<const BuildingType, int>& 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);
}