#include "InspectWindow.h" #include #include #include #include #include #include #include "ArenaView.h" const double InspectWindow::kSpeeds[] = { 0.0, 0.5, 1.0, 2.0, 10.0 }; const int InspectWindow::kSpeedCount = 5; InspectWindow::InspectWindow(ArenaSimulation* sim, const VisualsConfig* visuals, const std::string& arenaName, QWidget* parent) : QWidget(parent) , m_sim(sim) { setWindowTitle(tr("Inspect \u2014 %1").arg(QString::fromStdString(arenaName))); resize(900, 700); setAttribute(Qt::WA_DeleteOnClose, false); QVBoxLayout* mainLayout = new QVBoxLayout(this); mainLayout->setContentsMargins(0, 0, 0, 0); mainLayout->setSpacing(0); // Header: arena name + speed buttons { QWidget* header = new QWidget(this); QHBoxLayout* headerLayout = new QHBoxLayout(header); headerLayout->setContentsMargins(8, 4, 8, 4); headerLayout->setSpacing(8); QLabel* nameLabel = new QLabel(QString::fromStdString(arenaName), header); QFont nameFont = nameLabel->font(); nameFont.setBold(true); nameFont.setPointSize(nameFont.pointSize() + 2); nameLabel->setFont(nameFont); headerLayout->addWidget(nameLabel); headerLayout->addStretch(); const char* labels[] = { "0x", "0.5x", "1x", "2x", "10x" }; QSignalMapper* mapper = new QSignalMapper(this); for (int i = 0; i < kSpeedCount; ++i) { QPushButton* btn = new QPushButton(labels[i], header); btn->setCheckable(true); btn->setChecked(i == 2); headerLayout->addWidget(btn); m_speedButtons.push_back(btn); mapper->setMapping(btn, i); connect(btn, &QPushButton::clicked, mapper, qOverload<>(&QSignalMapper::map)); } connect(mapper, qOverload(&QSignalMapper::mapped), this, &InspectWindow::onSpeedButton); header->setFixedHeight(header->sizeHint().height()); mainLayout->addWidget(header); } // Arena view (center, stretch) m_arenaView = new ArenaView(sim, visuals, this); mainLayout->addWidget(m_arenaView, 1); connect(m_arenaView, &ArenaView::speedChanged, this, &InspectWindow::onSpeedChanged); // Info panel (bottom) { QWidget* infoPanel = new QWidget(this); QHBoxLayout* infoLayout = new QHBoxLayout(infoPanel); infoLayout->setContentsMargins(8, 4, 8, 4); infoLayout->setSpacing(16); QVBoxLayout* team1Layout = new QVBoxLayout(); m_team1Header = new QLabel(infoPanel); QFont headerFont = m_team1Header->font(); headerFont.setBold(true); m_team1Header->setFont(headerFont); team1Layout->addWidget(m_team1Header); m_team1Content = new QLabel(infoPanel); team1Layout->addWidget(m_team1Content); team1Layout->addStretch(); infoLayout->addLayout(team1Layout); QVBoxLayout* team2Layout = new QVBoxLayout(); m_team2Header = new QLabel(infoPanel); m_team2Header->setFont(headerFont); team2Layout->addWidget(m_team2Header); m_team2Content = new QLabel(infoPanel); team2Layout->addWidget(m_team2Content); team2Layout->addStretch(); infoLayout->addLayout(team2Layout); mainLayout->addWidget(infoPanel); } // Poll timer for info panel updates m_pollTimer = new QTimer(this); connect(m_pollTimer, &QTimer::timeout, this, &InspectWindow::pollStatus); m_pollTimer->start(100); // Show initial status pollStatus(); setFocusPolicy(Qt::StrongFocus); } void InspectWindow::closeEvent(QCloseEvent* event) { m_arenaView->stopRendering(); m_pollTimer->stop(); emit closed(); event->accept(); } void InspectWindow::keyPressEvent(QKeyEvent* event) { if (event->key() == Qt::Key_Space) { m_arenaView->togglePause(); } else { QWidget::keyPressEvent(event); } } void InspectWindow::onSpeedButton(int index) { if (index >= 0 && index < kSpeedCount) { m_arenaView->setGameSpeed(kSpeeds[index]); } } void InspectWindow::onSpeedChanged(double multiplier) { for (int i = 0; i < kSpeedCount; ++i) { const bool active = (std::abs(kSpeeds[i] - multiplier) < 0.001); m_speedButtons[static_cast(i)]->setChecked(active); } } void InspectWindow::pollStatus() { const ArenaStatus status = m_sim->status(); updateInfoPanel(status); } void InspectWindow::updateInfoPanel(const ArenaStatus& status) { for (int ti = 0; ti < 2; ++ti) { const ArenaStatus::TeamStatus& team = status.teams[ti]; QLabel* header = (ti == 0) ? m_team1Header : m_team2Header; QLabel* content = (ti == 0) ? m_team1Content : m_team2Content; if (status.finished && status.winnerTeam == ti) { header->setText(tr("[WON] %1").arg(QString::fromStdString(team.name))); } else { header->setText(QString::fromStdString(team.name)); } QString lines; for (const ArenaStatus::Entry& entry : team.entries) { if (!lines.isEmpty()) { lines += "\n"; } lines += QString("%1/%2 %3 L%4") .arg(entry.surviving) .arg(entry.total) .arg(QString::fromStdString(entry.displayName)) .arg(entry.level); } content->setText(lines); } }