554 lines
22 KiB
C++
554 lines
22 KiB
C++
#include <QApplication>
|
||
#include <QClipboard>
|
||
#include <QGuiApplication>
|
||
#include <QButtonGroup>
|
||
#include <QFont>
|
||
#include <QGridLayout>
|
||
#include <QCheckBox>
|
||
#include <QHBoxLayout>
|
||
#include <QHash>
|
||
#include <QLabel>
|
||
#include <QLineEdit>
|
||
#include <QPushButton>
|
||
#include <QRadioButton>
|
||
#include <QRegularExpression>
|
||
#include <QSlider>
|
||
#include <QSpinBox>
|
||
#include <QTabWidget>
|
||
#include <QTextEdit>
|
||
#include <QTreeWidgetItem>
|
||
#include <QVBoxLayout>
|
||
#include <QWidget>
|
||
|
||
#include "GamesPanel.h"
|
||
#include "LogPanel.h"
|
||
#include "PowerPanel.h"
|
||
#include "SettingsTree.h"
|
||
#include "VersionsPanel.h"
|
||
#include "WebSocketController.h"
|
||
|
||
#ifdef __EMSCRIPTEN__
|
||
#include <emscripten.h>
|
||
#endif
|
||
|
||
// ---------------------------------------------------------------------------
|
||
// Copy text to the OS clipboard.
|
||
// Uses navigator.clipboard (modern, async) with execCommand fallback (HTTP).
|
||
// Falls back to Qt clipboard on non-WASM builds.
|
||
// ---------------------------------------------------------------------------
|
||
static void copyToClipboard(const QString &text)
|
||
{
|
||
#ifdef __EMSCRIPTEN__
|
||
QByteArray utf8 = text.toUtf8();
|
||
EM_ASM({
|
||
var txt = UTF8ToString($0, $1);
|
||
if (navigator.clipboard && navigator.clipboard.writeText) {
|
||
navigator.clipboard.writeText(txt).catch(function() {
|
||
var ta = document.createElement('textarea');
|
||
ta.value = txt;
|
||
ta.style.position = 'fixed';
|
||
ta.style.opacity = '0';
|
||
document.body.appendChild(ta);
|
||
ta.focus(); ta.select();
|
||
document.execCommand('copy');
|
||
document.body.removeChild(ta);
|
||
});
|
||
} else {
|
||
var ta = document.createElement('textarea');
|
||
ta.value = txt;
|
||
ta.style.position = 'fixed';
|
||
ta.style.opacity = '0';
|
||
document.body.appendChild(ta);
|
||
ta.focus(); ta.select();
|
||
document.execCommand('copy');
|
||
document.body.removeChild(ta);
|
||
}
|
||
}, utf8.constData(), utf8.size());
|
||
#else
|
||
QGuiApplication::clipboard()->setText(text);
|
||
#endif
|
||
}
|
||
|
||
static QWidget *makeGamesTab(WebSocketController *ctrl, QWidget *parent)
|
||
{
|
||
auto *panel = new GamesPanel(parent);
|
||
ctrl->setGamesPanel(panel);
|
||
// Route GAM add commands back through the controller
|
||
QObject::connect(panel, &GamesPanel::commandRequested,
|
||
ctrl, &WebSocketController::sendCommand);
|
||
return panel;
|
||
}
|
||
|
||
static QWidget *makeVersionsTab(WebSocketController *ctrl, QWidget *parent)
|
||
{
|
||
auto *panel = new VersionsPanel(parent);
|
||
ctrl->setVersionsPanel(panel);
|
||
return panel;
|
||
}
|
||
|
||
static QWidget *makeSettingsTab(WebSocketController *ctrl, QWidget *parent)
|
||
{
|
||
auto *page = new QWidget(parent);
|
||
auto *layout = new QVBoxLayout(page);
|
||
layout->setContentsMargins(2, 2, 2, 2);
|
||
layout->setSpacing(4);
|
||
|
||
// --- Sliders row: brightness and volume side by side (top) ---
|
||
auto *slidersRow = new QHBoxLayout();
|
||
|
||
auto *brightnessLabel = new QLabel("Brightness:", page);
|
||
auto *brightnessSlider = new QSlider(Qt::Horizontal, page);
|
||
brightnessSlider->setMinimum(1);
|
||
brightnessSlider->setMaximum(12);
|
||
brightnessSlider->setValue(1);
|
||
brightnessSlider->setEnabled(false);
|
||
auto *brightnessVal = new QLabel("–", page);
|
||
brightnessVal->setFixedWidth(28);
|
||
|
||
auto *volumeLabel = new QLabel("Volume:", page);
|
||
auto *volumeSlider = new QSlider(Qt::Horizontal, page);
|
||
volumeSlider->setMinimum(1);
|
||
volumeSlider->setMaximum(6);
|
||
volumeSlider->setValue(1);
|
||
volumeSlider->setEnabled(false);
|
||
auto *volumeVal = new QLabel("–", page);
|
||
volumeVal->setFixedWidth(28);
|
||
|
||
slidersRow->addWidget(brightnessLabel);
|
||
slidersRow->addWidget(brightnessSlider, 1);
|
||
slidersRow->addWidget(brightnessVal);
|
||
slidersRow->addSpacing(16);
|
||
slidersRow->addWidget(volumeLabel);
|
||
slidersRow->addWidget(volumeSlider, 1);
|
||
slidersRow->addWidget(volumeVal);
|
||
layout->addLayout(slidersRow);
|
||
|
||
// --- Tree (takes all spare vertical space) ---
|
||
auto *tree = new SettingsTree(page);
|
||
auto *ph = new QTreeWidgetItem(tree);
|
||
ph->setText(0, "Connect to load settings...");
|
||
layout->addWidget(tree, 1);
|
||
ctrl->setSettingsTree(tree);
|
||
|
||
// --- Single compact toolbar row: name input + 3 GBL buttons + checkbox (below tree) ---
|
||
auto *toolbar = new QHBoxLayout();
|
||
auto *nameEdit = new QLineEdit(page);
|
||
nameEdit->setPlaceholderText("Config name...");
|
||
nameEdit->setMaximumWidth(160);
|
||
auto *saveBtn = new QPushButton("Save", page);
|
||
auto *loadBtn = new QPushButton("Restore From File", page);
|
||
auto *resetBtn = new QPushButton("Restore Defaults", page);
|
||
resetBtn->setStyleSheet(
|
||
"QPushButton { color: white; background-color: #c62828; border-radius: 4px; padding: 3px 8px; }"
|
||
"QPushButton:hover { background-color: #b71c1c; }"
|
||
"QPushButton:disabled { background-color: #888888; color: #cccccc; }");
|
||
auto *autoPowerOff = new QCheckBox("Auto Power Off", page);
|
||
toolbar->addWidget(nameEdit);
|
||
toolbar->addWidget(saveBtn);
|
||
toolbar->addWidget(loadBtn);
|
||
toolbar->addWidget(resetBtn);
|
||
toolbar->addStretch(1);
|
||
toolbar->addWidget(autoPowerOff);
|
||
layout->addLayout(toolbar);
|
||
|
||
// --- Reset to defaults (inline confirm row — no QMessageBox::exec on WASM) ---
|
||
auto *confirmRow = new QHBoxLayout();
|
||
auto *confirmLabel = new QLabel(page);
|
||
confirmLabel->setText("Click again to confirm reset:");
|
||
confirmLabel->setStyleSheet("color: #c62828;");
|
||
confirmLabel->setVisible(false);
|
||
auto *confirmYesBtn = new QPushButton("Yes, Reset", page);
|
||
confirmYesBtn->setStyleSheet(
|
||
"QPushButton { color: white; background-color: #c62828; border-radius: 4px; padding: 2px 8px; }");
|
||
confirmYesBtn->setVisible(false);
|
||
auto *confirmNoBtn = new QPushButton("Cancel", page);
|
||
confirmNoBtn->setVisible(false);
|
||
confirmRow->addWidget(confirmLabel);
|
||
confirmRow->addWidget(confirmYesBtn);
|
||
confirmRow->addWidget(confirmNoBtn);
|
||
confirmRow->addStretch(1);
|
||
layout->addLayout(confirmRow);
|
||
|
||
// ----------------------------------------------------------------
|
||
// Connections
|
||
// ----------------------------------------------------------------
|
||
|
||
// Save config
|
||
auto doSave = [ctrl, nameEdit]() {
|
||
QString name = nameEdit->text().trimmed();
|
||
name.remove(QRegularExpression("[^A-Za-z0-9]"));
|
||
if (name.isEmpty()) return;
|
||
ctrl->sendCommand(QString("GBL SaveToFile %1").arg(name));
|
||
nameEdit->clear();
|
||
};
|
||
QObject::connect(saveBtn, &QPushButton::clicked, page, doSave);
|
||
QObject::connect(nameEdit, &QLineEdit::returnPressed, page, doSave);
|
||
|
||
// Restore from file
|
||
QObject::connect(loadBtn, &QPushButton::clicked, page, [ctrl, nameEdit]() {
|
||
QString name = nameEdit->text().trimmed();
|
||
name.remove(QRegularExpression("[^A-Za-z0-9]"));
|
||
if (name.isEmpty()) return;
|
||
ctrl->sendCommand(QString("GBL LoadFromFile %1").arg(name));
|
||
nameEdit->clear();
|
||
});
|
||
|
||
// Reset confirm
|
||
QObject::connect(resetBtn, &QPushButton::clicked, page,
|
||
[confirmLabel, confirmYesBtn, confirmNoBtn]() {
|
||
confirmLabel->setVisible(true);
|
||
confirmYesBtn->setVisible(true);
|
||
confirmNoBtn->setVisible(true);
|
||
});
|
||
QObject::connect(confirmYesBtn, &QPushButton::clicked, page,
|
||
[ctrl, confirmLabel, confirmYesBtn, confirmNoBtn]() {
|
||
ctrl->sendCommand(QStringLiteral("GBL ResetAllToDefaults"));
|
||
confirmLabel->setVisible(false);
|
||
confirmYesBtn->setVisible(false);
|
||
confirmNoBtn->setVisible(false);
|
||
});
|
||
QObject::connect(confirmNoBtn, &QPushButton::clicked, page,
|
||
[confirmLabel, confirmYesBtn, confirmNoBtn]() {
|
||
confirmLabel->setVisible(false);
|
||
confirmYesBtn->setVisible(false);
|
||
confirmNoBtn->setVisible(false);
|
||
});
|
||
|
||
// Auto power off
|
||
QObject::connect(autoPowerOff, &QCheckBox::toggled, page, [ctrl](bool checked) {
|
||
ctrl->sendCommand(checked ? QStringLiteral("POW EnableAutoOff")
|
||
: QStringLiteral("POW KeepOn"));
|
||
});
|
||
|
||
// Query brightness/volume ranges+values on connect; disable on disconnect
|
||
QObject::connect(ctrl->socket(), &QWebSocket::connected, page, [ctrl]() {
|
||
ctrl->sendCommand(QStringLiteral("GBL brightnessMin"));
|
||
ctrl->sendCommand(QStringLiteral("GBL brightnessMax"));
|
||
ctrl->sendCommand(QStringLiteral("GBL brightness"));
|
||
ctrl->sendCommand(QStringLiteral("GBL sound/volumeMin"));
|
||
ctrl->sendCommand(QStringLiteral("GBL sound/volumeMax"));
|
||
ctrl->sendCommand(QStringLiteral("GBL sound/volume"));
|
||
});
|
||
QObject::connect(ctrl->socket(), &QWebSocket::disconnected, page,
|
||
[brightnessSlider, brightnessVal, volumeSlider, volumeVal]() {
|
||
brightnessSlider->setEnabled(false);
|
||
brightnessVal->setText(QStringLiteral("–"));
|
||
volumeSlider->setEnabled(false);
|
||
volumeVal->setText(QStringLiteral("–"));
|
||
});
|
||
|
||
// Parse incoming GBL brightness / sound/volume responses
|
||
QObject::connect(ctrl->socket(), &QWebSocket::textMessageReceived, page,
|
||
[brightnessSlider, brightnessVal, volumeSlider, volumeVal](const QString &msg) {
|
||
// helper: parse "GBL <key>=<int>" and return {ok, value}
|
||
auto parseGbl = [&](const QString &key) -> std::pair<bool,int> {
|
||
const QString prefix = QString("GBL %1=").arg(key);
|
||
if (!msg.startsWith(prefix)) return {false, 0};
|
||
bool ok = false;
|
||
int v = msg.mid(prefix.length()).toInt(&ok);
|
||
return {ok, v};
|
||
};
|
||
|
||
if (auto [ok, v] = parseGbl("brightness"); ok) {
|
||
brightnessSlider->setValue(v);
|
||
brightnessVal->setText(QString::number(v));
|
||
brightnessSlider->setEnabled(true);
|
||
} else if (auto [ok, v] = parseGbl("brightnessMin"); ok) {
|
||
brightnessSlider->setMinimum(v);
|
||
} else if (auto [ok, v] = parseGbl("brightnessMax"); ok) {
|
||
brightnessSlider->setMaximum(v);
|
||
} else if (auto [ok, v] = parseGbl("sound/volume"); ok) {
|
||
volumeSlider->setValue(v);
|
||
volumeVal->setText(QString::number(v));
|
||
volumeSlider->setEnabled(true);
|
||
} else if (auto [ok, v] = parseGbl("sound/volumeMin"); ok) {
|
||
volumeSlider->setMinimum(v);
|
||
} else if (auto [ok, v] = parseGbl("sound/volumeMax"); ok) {
|
||
volumeSlider->setMaximum(v);
|
||
}
|
||
});
|
||
|
||
// Live label update while dragging; send command only on release
|
||
QObject::connect(brightnessSlider, &QSlider::valueChanged, page,
|
||
[brightnessVal](int v) { brightnessVal->setText(QString::number(v)); });
|
||
QObject::connect(brightnessSlider, &QSlider::sliderReleased, page,
|
||
[ctrl, brightnessSlider]() {
|
||
ctrl->sendCommand(QString("GBL brightness=%1").arg(brightnessSlider->value()));
|
||
});
|
||
|
||
QObject::connect(volumeSlider, &QSlider::valueChanged, page,
|
||
[volumeVal](int v) { volumeVal->setText(QString::number(v)); });
|
||
QObject::connect(volumeSlider, &QSlider::sliderReleased, page,
|
||
[ctrl, volumeSlider]() {
|
||
ctrl->sendCommand(QString("GBL sound/volume=%1").arg(volumeSlider->value()));
|
||
});
|
||
|
||
return page;
|
||
}
|
||
|
||
static QWidget *makeManualTab(WebSocketController *ctrl, QWidget *parent)
|
||
{
|
||
auto *page = new QWidget(parent);
|
||
auto *layout = new QVBoxLayout(page);
|
||
layout->setContentsMargins(2, 2, 2, 2);
|
||
layout->setSpacing(4);
|
||
|
||
// 4 independent command input boxes (Enter to send, no Send button)
|
||
const QStringList placeholders = {
|
||
"Command 1...",
|
||
"Command 2...",
|
||
"Command 3...",
|
||
"Command 4...",
|
||
};
|
||
auto *inputGrid = new QGridLayout();
|
||
inputGrid->setSpacing(4);
|
||
for (int i = 0; i < 4; ++i) {
|
||
auto *edit = new QLineEdit(page);
|
||
edit->setPlaceholderText(placeholders[i]);
|
||
edit->setFont(QFont("Courier", 10));
|
||
inputGrid->addWidget(edit, i / 2, i % 2);
|
||
QObject::connect(edit, &QLineEdit::returnPressed, page, [edit, ctrl]() {
|
||
const QString cmd = edit->text().trimmed();
|
||
if (!cmd.isEmpty()) { ctrl->sendCommand(cmd); edit->clear(); }
|
||
});
|
||
}
|
||
layout->addLayout(inputGrid);
|
||
|
||
// Log view + action buttons
|
||
auto *log = new QTextEdit(page);
|
||
log->setReadOnly(true);
|
||
log->setFont(QFont("Courier", 9));
|
||
|
||
auto *logBtnRow = new QHBoxLayout();
|
||
auto *copyLogBtn = new QPushButton("Copy Log", page);
|
||
auto *clearBtn = new QPushButton("Clear Log", page);
|
||
copyLogBtn->setMaximumWidth(110);
|
||
clearBtn->setMaximumWidth(100);
|
||
logBtnRow->addWidget(copyLogBtn);
|
||
logBtnRow->addWidget(clearBtn);
|
||
logBtnRow->addStretch(1);
|
||
|
||
layout->addWidget(log, 1);
|
||
layout->addLayout(logBtnRow);
|
||
ctrl->addLogView(log);
|
||
|
||
QObject::connect(clearBtn, &QPushButton::clicked, log, &QTextEdit::clear);
|
||
QObject::connect(copyLogBtn, &QPushButton::clicked, page,
|
||
[log]() { copyToClipboard(log->toPlainText()); });
|
||
return page;
|
||
}
|
||
|
||
static QWidget *makePowerTab(WebSocketController *ctrl, QWidget *parent)
|
||
{
|
||
auto *panel = new PowerPanel(parent);
|
||
ctrl->setPowerPanel(panel);
|
||
return panel;
|
||
}
|
||
|
||
static QWidget *makeLogsTab(WebSocketController *ctrl, QWidget *parent)
|
||
{
|
||
auto *panel = new LogPanel(ctrl, parent);
|
||
ctrl->setLogPanel(panel);
|
||
return panel;
|
||
}
|
||
|
||
static QWidget *makePanelsTab(WebSocketController *ctrl, QWidget *parent)
|
||
{
|
||
auto *page = new QWidget(parent);
|
||
auto *layout = new QVBoxLayout(page);
|
||
auto *log = new QTextEdit(page);
|
||
log->setReadOnly(true);
|
||
layout->addWidget(log, 1);
|
||
ctrl->addLogView(log);
|
||
return page;
|
||
}
|
||
|
||
int main(int argc, char *argv[])
|
||
{
|
||
QApplication app(argc, argv);
|
||
|
||
QWidget window;
|
||
window.setWindowTitle("ESA WebSocket Client");
|
||
|
||
auto *mainLayout = new QVBoxLayout(&window);
|
||
mainLayout->setContentsMargins(6, 6, 6, 6);
|
||
mainLayout->setSpacing(4);
|
||
|
||
// --- ICON → IP helper (formula + hardcoded overrides) ---
|
||
// Returns the IP string for a given ICON number.
|
||
static const auto iconToIp = [](int icon) -> QString {
|
||
static const QHash<int,QString> overrides = {
|
||
{280, QStringLiteral("10.10.1.30")},
|
||
};
|
||
if (overrides.contains(icon))
|
||
return overrides[icon];
|
||
const int subnet = (icon - 1) / 254;
|
||
const int host = ((icon - 1) % 254) + 1;
|
||
return QString("10.10.%1.%2").arg(subnet).arg(host);
|
||
};
|
||
|
||
// --- Hidden urlEdit still used by WebSocketController::startConnection() ---
|
||
auto *urlEdit = new QLineEdit(&window);
|
||
urlEdit->setVisible(false);
|
||
|
||
auto *statusLabel = new QLabel("Disconnected", &window);
|
||
|
||
// --- Network connection row ---
|
||
auto *headerRow = new QHBoxLayout();
|
||
headerRow->addWidget(new QLabel("Network connection:", &window));
|
||
|
||
// Option 1 – fixed IP
|
||
auto *radioFixed = new QRadioButton("10.110.110.10", &window);
|
||
|
||
// Option 2 – ICON number → derived IP
|
||
auto *radioIcon = new QRadioButton(&window);
|
||
auto *iconSpin = new QSpinBox(&window);
|
||
iconSpin->setRange(1, 9999);
|
||
iconSpin->setValue(280);
|
||
iconSpin->setFixedWidth(68);
|
||
iconSpin->setAlignment(Qt::AlignRight);
|
||
auto *iconIpLabel = new QLabel(iconToIp(280), &window);
|
||
iconIpLabel->setStyleSheet("color: #555; font-style: italic;");
|
||
|
||
// Option 3 – free text (hostname or raw IP)
|
||
auto *radioOther = new QRadioButton("other:", &window);
|
||
auto *otherEdit = new QLineEdit(&window);
|
||
otherEdit->setText("ftsDevkit4.local");
|
||
otherEdit->setFixedWidth(160);
|
||
otherEdit->setEnabled(false); // only active when radioOther selected
|
||
|
||
auto *btnGroup = new QButtonGroup(&window);
|
||
btnGroup->addButton(radioFixed, 0);
|
||
btnGroup->addButton(radioIcon, 1);
|
||
btnGroup->addButton(radioOther, 2);
|
||
radioIcon->setChecked(true); // default selection
|
||
|
||
headerRow->addWidget(radioFixed);
|
||
headerRow->addWidget(radioIcon);
|
||
headerRow->addWidget(iconSpin);
|
||
headerRow->addWidget(iconIpLabel);
|
||
headerRow->addSpacing(8);
|
||
headerRow->addWidget(radioOther);
|
||
headerRow->addWidget(otherEdit);
|
||
headerRow->addStretch(1);
|
||
|
||
// Buttons
|
||
auto *connectBtn = new QPushButton("Connect", &window);
|
||
auto *disconnectBtn = new QPushButton("Disconnect", &window);
|
||
auto *shutdownBtn = new QPushButton("Shutdown", &window);
|
||
disconnectBtn->setEnabled(false);
|
||
shutdownBtn->setEnabled(false);
|
||
shutdownBtn->setStyleSheet(
|
||
"QPushButton { color: white; background-color: #c62828;"
|
||
" border-radius: 4px; padding: 3px 10px; }"
|
||
"QPushButton:hover { background-color: #b71c1c; }"
|
||
"QPushButton:disabled { background-color: #888888; color: #cccccc; }");
|
||
headerRow->addWidget(connectBtn);
|
||
headerRow->addWidget(disconnectBtn);
|
||
headerRow->addWidget(shutdownBtn);
|
||
headerRow->addWidget(statusLabel);
|
||
mainLayout->addLayout(headerRow);
|
||
|
||
// --- Build URL from current selection into the hidden urlEdit ---
|
||
auto updateUrl = [=]() {
|
||
const int port = 5424;
|
||
QString host;
|
||
if (radioFixed->isChecked()) {
|
||
host = QStringLiteral("10.110.110.10");
|
||
} else if (radioIcon->isChecked()) {
|
||
host = iconToIp(iconSpin->value());
|
||
} else {
|
||
host = otherEdit->text().trimmed();
|
||
if (host.isEmpty()) host = QStringLiteral("127.0.0.1");
|
||
}
|
||
urlEdit->setText(QString("ws://%1:%2/").arg(host).arg(port));
|
||
};
|
||
updateUrl(); // set initial value
|
||
|
||
// Keep iconIpLabel in sync and rebuild URL whenever ICON changes
|
||
QObject::connect(iconSpin, QOverload<int>::of(&QSpinBox::valueChanged), &window,
|
||
[=](int v) { iconIpLabel->setText(iconToIp(v)); updateUrl(); });
|
||
QObject::connect(btnGroup, QOverload<int>::of(&QButtonGroup::idClicked), &window,
|
||
[=](int) {
|
||
otherEdit->setEnabled(radioOther->isChecked());
|
||
updateUrl();
|
||
});
|
||
QObject::connect(otherEdit, &QLineEdit::textChanged, &window, [=]() {
|
||
if (radioOther->isChecked()) updateUrl();
|
||
});
|
||
|
||
// --- Controller ---
|
||
auto *ctrl = new WebSocketController(urlEdit, statusLabel, &window);
|
||
|
||
// --- Tabs ---
|
||
auto *tabs = new QTabWidget(&window);
|
||
tabs->addTab(makeGamesTab (ctrl, &window), "Games");
|
||
tabs->addTab(makeVersionsTab(ctrl, &window), "Versions");
|
||
tabs->addTab(makeManualTab (ctrl, &window), "Manual");
|
||
tabs->addTab(makeSettingsTab(ctrl, &window), "Settings");
|
||
tabs->addTab(makePowerTab (ctrl, &window), "Power");
|
||
tabs->addTab(makeLogsTab (ctrl, &window), "Logs");
|
||
tabs->addTab(makePanelsTab (ctrl, &window), "Panels");
|
||
mainLayout->addWidget(tabs, 1);
|
||
|
||
// --- Shutdown: inline confirm (no QMessageBox::exec on WASM) ---
|
||
auto *shutdownConfirmLabel = new QLabel("Confirm shutdown:", &window);
|
||
auto *shutdownConfirmYes = new QPushButton("Yes, Shutdown", &window);
|
||
auto *shutdownConfirmNo = new QPushButton("Cancel", &window);
|
||
shutdownConfirmLabel->setStyleSheet("color: #c62828; font-weight: bold;");
|
||
shutdownConfirmYes->setStyleSheet(
|
||
"QPushButton { color: white; background-color: #c62828; border-radius: 4px; padding: 2px 8px; }");
|
||
shutdownConfirmLabel->setVisible(false);
|
||
shutdownConfirmYes->setVisible(false);
|
||
shutdownConfirmNo->setVisible(false);
|
||
headerRow->addWidget(shutdownConfirmLabel);
|
||
headerRow->addWidget(shutdownConfirmYes);
|
||
headerRow->addWidget(shutdownConfirmNo);
|
||
|
||
QObject::connect(shutdownBtn, &QPushButton::clicked, &window,
|
||
[shutdownConfirmLabel, shutdownConfirmYes, shutdownConfirmNo]() {
|
||
shutdownConfirmLabel->setVisible(true);
|
||
shutdownConfirmYes->setVisible(true);
|
||
shutdownConfirmNo->setVisible(true);
|
||
});
|
||
QObject::connect(shutdownConfirmYes, &QPushButton::clicked, &window,
|
||
[ctrl, shutdownConfirmLabel, shutdownConfirmYes, shutdownConfirmNo]() {
|
||
ctrl->sendCommand(QStringLiteral("POW ShutDown"));
|
||
shutdownConfirmLabel->setVisible(false);
|
||
shutdownConfirmYes->setVisible(false);
|
||
shutdownConfirmNo->setVisible(false);
|
||
});
|
||
QObject::connect(shutdownConfirmNo, &QPushButton::clicked, &window,
|
||
[shutdownConfirmLabel, shutdownConfirmYes, shutdownConfirmNo]() {
|
||
shutdownConfirmLabel->setVisible(false);
|
||
shutdownConfirmYes->setVisible(false);
|
||
shutdownConfirmNo->setVisible(false);
|
||
});
|
||
|
||
// --- Wire up buttons ---
|
||
QObject::connect(connectBtn, &QPushButton::clicked, ctrl, &WebSocketController::startConnection);
|
||
QObject::connect(disconnectBtn, &QPushButton::clicked, ctrl, &WebSocketController::closeConnection);
|
||
|
||
QObject::connect(ctrl->socket(), &QWebSocket::connected, ctrl, &WebSocketController::onConnected);
|
||
QObject::connect(ctrl->socket(), &QWebSocket::disconnected, ctrl, &WebSocketController::onDisconnected);
|
||
QObject::connect(ctrl->socket(), &QWebSocket::textMessageReceived, ctrl, &WebSocketController::onTextMessageReceived);
|
||
QObject::connect(ctrl->socket(), &QWebSocket::errorOccurred, ctrl, &WebSocketController::onErrorOccurred);
|
||
|
||
QObject::connect(ctrl->socket(), &QWebSocket::connected, &window,
|
||
[connectBtn, disconnectBtn, shutdownBtn]() {
|
||
connectBtn->setEnabled(false);
|
||
disconnectBtn->setEnabled(true);
|
||
shutdownBtn->setEnabled(true);
|
||
});
|
||
QObject::connect(ctrl->socket(), &QWebSocket::disconnected, &window,
|
||
[connectBtn, disconnectBtn, shutdownBtn]() {
|
||
connectBtn->setEnabled(true);
|
||
disconnectBtn->setEnabled(false);
|
||
shutdownBtn->setEnabled(false);
|
||
});
|
||
|
||
window.resize(1050, 620);
|
||
window.show();
|
||
return app.exec();
|
||
}
|