#include "GamesPanel.h" #include #include #include #include #include #include #include // --------------------------------------------------------------------------- // Helper: parse "GAM CODE1Name1 CODE2Name2 ..." → name->code map // --------------------------------------------------------------------------- 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.isEmpty()) continue; // First up-to-4 uppercase chars = code, remainder = name int splitPos = 0; while (splitPos < entry.size() && entry[splitPos].isUpper()) ++splitPos; const QString code = entry.left(qMin(splitPos, 4)); QString name = entry.mid(code.size()); name.replace("_S", " "); if (code.isEmpty() || 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 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 ---- 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..."); rightLayout->addWidget(instLabel); rightLayout->addWidget(m_installedList, 1); splitter->addWidget(leftWidget); splitter->addWidget(rightWidget); splitter->setStretchFactor(0, 1); splitter->setStretchFactor(1, 1); splitter->setSizes({420, 420}); layout->addWidget(splitter); // Enable Add button only when something is selected in available list connect(m_availableList, &QListWidget::currentRowChanged, this, [this](int row) { m_addBtn->setEnabled(row >= 0); }); connect(m_addBtn, &QPushButton::clicked, this, &GamesPanel::onAddClicked); } // --------------------------------------------------------------------------- // 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); rebuildAvailable(); } // --------------------------------------------------------------------------- // Load all available games (GAM listall response) // --------------------------------------------------------------------------- void GamesPanel::loadAllFromResponse(const QString &response) { m_allGames = parseGamResponse(response, "listall"); rebuildAvailable(); } // --------------------------------------------------------------------------- // Rebuild available list = allGames minus installedGames (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 button clicked → emit GAM add // --------------------------------------------------------------------------- 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])); }