#include "GamesPanel.h" #include #include #include #include #include #include #include #include // --------------------------------------------------------------------------- // Helper: parse "GAM XXXXNAME1 XXXXNAME2 ..." // Code is always the first 4 characters; remainder is the display name. // "_S" sequences in the name are replaced with spaces. // --------------------------------------------------------------------------- static QMap parseGamResponse(const QString &response, const QString &subCmd) { QMap result; const QStringList tokens = response.split(' ', Qt::SkipEmptyParts); if (tokens.size() < 3 || tokens[0] != "GAM" || tokens[1] != subCmd) return result; for (const QString &entry : tokens.mid(2)) { if (entry.size() < 5) continue; const QString code = entry.left(4); QString name = entry.mid(4); name.replace("_S", " "); if (name.isEmpty()) continue; result[name] = code; } return result; } // --------------------------------------------------------------------------- // Constructor // --------------------------------------------------------------------------- GamesPanel::GamesPanel(QWidget *parent) : QWidget(parent) { auto *layout = new QHBoxLayout(this); layout->setContentsMargins(2, 2, 2, 2); auto *splitter = new QSplitter(Qt::Horizontal, this); // ---- Left pane: Available (not yet installed) games ---- auto *leftWidget = new QWidget(splitter); auto *leftLayout = new QVBoxLayout(leftWidget); leftLayout->setContentsMargins(4, 4, 4, 4); leftLayout->setSpacing(4); auto *availLabel = new QLabel("Available Games", leftWidget); availLabel->setStyleSheet("color: #555;"); m_availableList = new QListWidget(leftWidget); m_availableList->addItem("Connect to load available games..."); m_addBtn = new QPushButton("Add to Installed →", leftWidget); m_addBtn->setEnabled(false); leftLayout->addWidget(availLabel); leftLayout->addWidget(m_availableList, 1); leftLayout->addWidget(m_addBtn); // ---- Right pane: Installed games + Start/Stop + time/countdown inputs ---- auto *rightWidget = new QWidget(splitter); auto *rightLayout = new QVBoxLayout(rightWidget); rightLayout->setContentsMargins(4, 4, 4, 4); rightLayout->setSpacing(4); auto *instLabel = new QLabel("Installed Games", rightWidget); instLabel->setStyleSheet("color: #555;"); m_installedList = new QListWidget(rightWidget); m_installedList->addItem("Connect to load installed games..."); // Parameter inputs row auto *paramRow = new QHBoxLayout(); auto *timeLabel = new QLabel("Time:", rightWidget); m_timeEdit = new QLineEdit(rightWidget); m_timeEdit->setPlaceholderText("seconds"); m_timeEdit->setFixedWidth(72); m_timeEdit->setToolTip("Optional: game duration in seconds (adds ,t)"); auto *countLabel = new QLabel("Countdown:", rightWidget); m_countdownEdit = new QLineEdit(rightWidget); m_countdownEdit->setPlaceholderText("seconds"); m_countdownEdit->setFixedWidth(72); m_countdownEdit->setToolTip("Optional: countdown duration in seconds (adds ,c)"); paramRow->addWidget(timeLabel); paramRow->addWidget(m_timeEdit); paramRow->addSpacing(8); paramRow->addWidget(countLabel); paramRow->addWidget(m_countdownEdit); paramRow->addStretch(1); // Start / Stop button row auto *btnRow = new QHBoxLayout(); m_startBtn = new QPushButton("▶ Start Game", rightWidget); m_stopBtn = new QPushButton("■ Stop Game", rightWidget); m_startBtn->setEnabled(false); m_startBtn->setStyleSheet( "QPushButton { color: white; background-color: #2e7d32;" " border-radius: 4px; padding: 3px 10px; }" "QPushButton:hover { background-color: #1b5e20; }" "QPushButton:disabled { background-color: #888; color: #ccc; }"); m_stopBtn->setStyleSheet( "QPushButton { color: white; background-color: #c62828;" " border-radius: 4px; padding: 3px 10px; }" "QPushButton:hover { background-color: #b71c1c; }"); btnRow->addWidget(m_startBtn); btnRow->addWidget(m_stopBtn); btnRow->addStretch(1); rightLayout->addWidget(instLabel); rightLayout->addWidget(m_installedList, 1); rightLayout->addLayout(paramRow); rightLayout->addLayout(btnRow); splitter->addWidget(leftWidget); splitter->addWidget(rightWidget); splitter->setStretchFactor(0, 1); splitter->setStretchFactor(1, 1); splitter->setSizes({420, 420}); layout->addWidget(splitter); // Enable Add only when available list has selection connect(m_availableList, &QListWidget::currentRowChanged, this, [this](int row) { m_addBtn->setEnabled(row >= 0); }); // Enable Start only when installed list has selection connect(m_installedList, &QListWidget::currentRowChanged, this, [this](int row) { m_startBtn->setEnabled(row >= 0); }); connect(m_addBtn, &QPushButton::clicked, this, &GamesPanel::onAddClicked); connect(m_startBtn, &QPushButton::clicked, this, &GamesPanel::onStartClicked); connect(m_stopBtn, &QPushButton::clicked, this, [this]() { emit commandRequested(QStringLiteral("GST")); }); } // --------------------------------------------------------------------------- // Load installed games (GAM list response) // --------------------------------------------------------------------------- void GamesPanel::loadFromResponse(const QString &response) { m_installedGames = parseGamResponse(response, "list"); m_installedList->clear(); for (const QString &name : m_installedGames.keys()) m_installedList->addItem(name); m_startBtn->setEnabled(false); rebuildAvailable(); } // --------------------------------------------------------------------------- // Load full catalogue (GAM listall response) // --------------------------------------------------------------------------- void GamesPanel::loadAllFromResponse(const QString &response) { m_allGames = parseGamResponse(response, "listall"); rebuildAvailable(); } // --------------------------------------------------------------------------- // Rebuild available list = allGames minus installedGames (matched by code) // --------------------------------------------------------------------------- void GamesPanel::rebuildAvailable() { const QSet installedCodes(m_installedGames.values().begin(), m_installedGames.values().end()); m_availableList->clear(); for (auto it = m_allGames.constBegin(); it != m_allGames.constEnd(); ++it) { if (!installedCodes.contains(it.value())) m_availableList->addItem(it.key()); } if (m_availableList->count() == 0 && !m_allGames.isEmpty()) m_availableList->addItem("(all available games are installed)"); m_addBtn->setEnabled(false); } // --------------------------------------------------------------------------- // Add selected available game // --------------------------------------------------------------------------- void GamesPanel::onAddClicked() { auto *item = m_availableList->currentItem(); if (!item) return; const QString name = item->text(); if (!m_allGames.contains(name)) return; emit commandRequested(QString("GAM add %1").arg(m_allGames[name])); } // --------------------------------------------------------------------------- // Start selected installed game: // GST ,p (no params) // GST ,p,t