213 lines
8.5 KiB
C++
213 lines
8.5 KiB
C++
#include "GamesPanel.h"
|
|
|
|
#include <QHBoxLayout>
|
|
#include <QLabel>
|
|
#include <QLineEdit>
|
|
#include <QListWidget>
|
|
#include <QPushButton>
|
|
#include <QSet>
|
|
#include <QSplitter>
|
|
#include <QVBoxLayout>
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Helper: parse "GAM <subCmd> 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<QString,QString> parseGamResponse(const QString &response,
|
|
const QString &subCmd)
|
|
{
|
|
QMap<QString,QString> 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("<b>Available Games</b>", 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("<b>Installed Games</b>", 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<value>)");
|
|
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<value>)");
|
|
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<QString> 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 <code> ,p (no params)
|
|
// GST <code> ,p,t<time> (time only)
|
|
// GST <code> ,p,c<countdown> (countdown only)
|
|
// GST <code> ,p,t<time>,c<countdown> (both)
|
|
// ---------------------------------------------------------------------------
|
|
void GamesPanel::onStartClicked()
|
|
{
|
|
auto *item = m_installedList->currentItem();
|
|
if (!item) return;
|
|
const QString name = item->text();
|
|
if (!m_installedGames.contains(name)) return;
|
|
|
|
const QString code = m_installedGames[name];
|
|
const QString timeVal = m_timeEdit->text().trimmed();
|
|
const QString countVal = m_countdownEdit->text().trimmed();
|
|
|
|
QString params = ",p";
|
|
if (!timeVal.isEmpty()) params += QString(",t%1").arg(timeVal);
|
|
if (!countVal.isEmpty()) params += QString(",c%1").arg(countVal);
|
|
|
|
emit commandRequested(QString("GST %1 %2").arg(code, params));
|
|
}
|