Panel circle for visual feedback

This commit is contained in:
Jon ESA
2026-04-01 22:08:46 +01:00
parent d75c80ef03
commit 81e8cf74c4
6 changed files with 305 additions and 285 deletions

View File

@@ -11,6 +11,7 @@ qt_add_executable(wsapp
main.cpp main.cpp
GamesPanel.cpp GamesPanel.h GamesPanel.cpp GamesPanel.h
LogPanel.cpp LogPanel.h LogPanel.cpp LogPanel.h
PanelsPanel.cpp PanelsPanel.h
PowerPanel.cpp PowerPanel.h PowerPanel.cpp PowerPanel.h
SettingsTree.cpp SettingsTree.h SettingsTree.cpp SettingsTree.h
VersionsPanel.cpp VersionsPanel.h VersionsPanel.cpp VersionsPanel.h
@@ -27,7 +28,7 @@ if(EMSCRIPTEN)
set_target_properties(wsapp PROPERTIES set_target_properties(wsapp PROPERTIES
WIN32_EXECUTABLE TRUE WIN32_EXECUTABLE TRUE
QT_WASM_INITIAL_MEMORY "50MB" QT_WASM_INITIAL_MEMORY "50MB"
QT_WASM_MAX_MEMORY "1GB" QT_WASM_MAX_MEMORY "4GB"
) )
target_link_options(wsapp PRIVATE target_link_options(wsapp PRIVATE
"SHELL:-s ASYNCIFY=1" "SHELL:-s ASYNCIFY=1"

106
PanelsPanel.cpp Normal file
View File

@@ -0,0 +1,106 @@
#include "PanelsPanel.h"
#include <QLabel>
#include <QPainter>
#include <QPainterPath>
#include <QVBoxLayout>
#include <QtMath>
PanelsPanel::PanelsPanel(QWidget *parent) : QWidget(parent)
{
auto *layout = new QVBoxLayout(this);
layout->setContentsMargins(4, 4, 4, 4);
m_statusLabel = new QLabel("Connect to load panels...", this);
m_statusLabel->setAlignment(Qt::AlignHCenter | Qt::AlignTop);
m_statusLabel->setStyleSheet("color: #888; font-style: italic;");
layout->addWidget(m_statusLabel);
layout->addStretch(1);
setMinimumSize(200, 200);
}
void PanelsPanel::setRnpCount(int count)
{
m_count = count;
m_colors.clear();
m_statusLabel->setText(count > 0
? QString("%1 panel%2").arg(count).arg(count == 1 ? "" : "s")
: "No panels reported");
update();
}
void PanelsPanel::setPanelColor(int index, const QColor &color)
{
m_colors[index] = color;
update();
}
void PanelsPanel::reset()
{
m_count = 0;
m_colors.clear();
m_statusLabel->setText("Connect to load panels...");
update();
}
void PanelsPanel::paintEvent(QPaintEvent *)
{
if (m_count <= 0) return;
QPainter p(this);
p.setRenderHint(QPainter::Antialiasing, true);
const QRectF bounds = rect();
const QRectF drawArea = bounds.adjusted(0, 28, 0, 0);
const double side = qMin(drawArea.width(), drawArea.height()) * 0.88;
const double cx = drawArea.center().x();
const double cy = drawArea.center().y();
const double outerR = side / 2.0;
const double innerR = outerR * 0.44;
const QRectF outerRect(cx - outerR, cy - outerR, side, side);
const QRectF innerRect(cx - innerR, cy - innerR, innerR * 2, innerR * 2);
const double gapDeg = (m_count > 1) ? 3.0 : 0.0;
const double segSpan = (360.0 - m_count * gapDeg) / m_count;
static const QColor kDefault(100, 140, 180);
for (int i = 0; i < m_count; ++i) {
const double startAngle = 90.0 - i * (segSpan + gapDeg);
const double sweep = -segSpan;
QPainterPath path;
path.arcMoveTo(outerRect, startAngle);
path.arcTo(outerRect, startAngle, sweep);
path.arcTo(innerRect, startAngle + sweep, -sweep);
path.closeSubpath();
p.setBrush(m_colors.value(i, kDefault));
p.setPen(QPen(Qt::white, 2));
p.drawPath(path);
// Label at segment midpoint
const double midAngle = startAngle + sweep / 2.0;
const double midAngleRad = qDegreesToRadians(midAngle);
const double midR = (outerR + innerR) / 2.0;
const QPointF tc(cx + midR * qCos(midAngleRad),
cy - midR * qSin(midAngleRad));
QFont font = p.font();
font.setBold(true);
font.setPointSize(qMax(7, qMin(12, static_cast<int>(outerR / (m_count * 0.55 + 2)))));
p.setFont(font);
p.setPen(Qt::white);
p.drawText(QRectF(tc.x() - 22, tc.y() - 11, 44, 22), Qt::AlignCenter, QString::number(i));
}
// Centre hole: total count
QFont cf = p.font();
cf.setBold(true);
cf.setPointSize(qMax(8, static_cast<int>(innerR * 0.45)));
p.setFont(cf);
p.setPen(palette().text().color());
p.drawText(innerRect, Qt::AlignCenter, QString::number(m_count));
}

25
PanelsPanel.h Normal file
View File

@@ -0,0 +1,25 @@
#pragma once
#include <QColor>
#include <QMap>
#include <QWidget>
class QLabel;
class PanelsPanel : public QWidget
{
Q_OBJECT
public:
explicit PanelsPanel(QWidget *parent = nullptr);
void setRnpCount(int count);
void setPanelColor(int index, const QColor &color);
void reset();
protected:
void paintEvent(QPaintEvent *event) override;
private:
int m_count = 0;
QMap<int,QColor> m_colors;
QLabel *m_statusLabel = nullptr;
};

View File

@@ -1,6 +1,7 @@
#include "WebSocketController.h" #include "WebSocketController.h"
#include "GamesPanel.h" #include "GamesPanel.h"
#include "LogPanel.h" #include "LogPanel.h"
#include "PanelsPanel.h"
#include "PowerPanel.h" #include "PowerPanel.h"
#include "SettingsTree.h" #include "SettingsTree.h"
#include "VersionsPanel.h" #include "VersionsPanel.h"
@@ -31,6 +32,7 @@ void WebSocketController::setGamesPanel(GamesPanel *panel) { m_gamesPanel =
void WebSocketController::setVersionsPanel(VersionsPanel *p) { m_versionsPanel = p; } void WebSocketController::setVersionsPanel(VersionsPanel *p) { m_versionsPanel = p; }
void WebSocketController::setPowerPanel(PowerPanel *panel) { m_powerPanel = panel; } void WebSocketController::setPowerPanel(PowerPanel *panel) { m_powerPanel = panel; }
void WebSocketController::setLogPanel(LogPanel *panel) { m_logPanel = panel; } void WebSocketController::setLogPanel(LogPanel *panel) { m_logPanel = panel; }
void WebSocketController::setPanelsPanel(PanelsPanel *panel) { m_panelsPanel = panel; }
bool WebSocketController::isConnected() const bool WebSocketController::isConnected() const
{ {
@@ -53,6 +55,7 @@ void WebSocketController::closeConnection()
m_rnpCount = -1; m_rnpCount = -1;
if (m_versionsPanel) m_versionsPanel->reset(); if (m_versionsPanel) m_versionsPanel->reset();
if (m_powerPanel) m_powerPanel->reset(); if (m_powerPanel) m_powerPanel->reset();
if (m_panelsPanel) m_panelsPanel->reset();
m_socket.close(); m_socket.close();
} }
@@ -71,7 +74,7 @@ void WebSocketController::onConnected()
sendCommand(QStringLiteral("GBL List")); sendCommand(QStringLiteral("GBL List"));
sendCommand(QStringLiteral("GAM list")); sendCommand(QStringLiteral("GAM list"));
sendCommand(QStringLiteral("GAM listall")); // <-- fetch full catalogue sendCommand(QStringLiteral("GAM listall"));
sendCommand(QStringLiteral("NAM")); sendCommand(QStringLiteral("NAM"));
sendCommand(QStringLiteral("VER")); sendCommand(QStringLiteral("VER"));
sendCommand(QStringLiteral("UID")); sendCommand(QStringLiteral("UID"));
@@ -80,6 +83,12 @@ void WebSocketController::onConnected()
sendCommand(QStringLiteral("#P0-P RTV")); sendCommand(QStringLiteral("#P0-P RTV"));
sendCommand(QStringLiteral("#P0-P VTG")); sendCommand(QStringLiteral("#P0-P VTG"));
sendCommand(QStringLiteral("LOG")); sendCommand(QStringLiteral("LOG"));
sendCommand(QStringLiteral("GBL brightnessMin"));
sendCommand(QStringLiteral("GBL brightnessMax"));
sendCommand(QStringLiteral("GBL brightness"));
sendCommand(QStringLiteral("GBL sound/volumeMin"));
sendCommand(QStringLiteral("GBL sound/volumeMax"));
sendCommand(QStringLiteral("GBL sound/volume"));
} }
void WebSocketController::onDisconnected() void WebSocketController::onDisconnected()
@@ -88,6 +97,7 @@ void WebSocketController::onDisconnected()
m_statusLabel->setText("Disconnected"); m_statusLabel->setText("Disconnected");
m_settingsKeys.clear(); m_settingsKeys.clear();
m_rnpCount = -1; m_rnpCount = -1;
if (m_panelsPanel) m_panelsPanel->reset();
} }
void WebSocketController::onTextMessageReceived(const QString &msg) void WebSocketController::onTextMessageReceived(const QString &msg)
@@ -114,7 +124,7 @@ void WebSocketController::handleProtocol(const QString &msg)
if (tokens.isEmpty()) return; if (tokens.isEmpty()) return;
const QString cmd = tokens[0]; const QString cmd = tokens[0];
// ---- Power: #P0-P STA/RTV/VTG ---- // ---- Power ----
if (cmd == "#P0-P" && tokens.size() >= 2 && m_powerPanel) { if (cmd == "#P0-P" && tokens.size() >= 2 && m_powerPanel) {
const QString sub = tokens[1]; const QString sub = tokens[1];
if (sub == "STA" && tokens.size() >= 3) m_powerPanel->setStatus(tokens[2]); if (sub == "STA" && tokens.size() >= 3) m_powerPanel->setStatus(tokens[2]);
@@ -123,7 +133,7 @@ void WebSocketController::handleProtocol(const QString &msg)
return; return;
} }
// ---- LOG channel list ---- // ---- LOG ----
if (cmd == "LOG" && tokens.size() > 1 && m_logPanel) { if (cmd == "LOG" && tokens.size() > 1 && m_logPanel) {
bool isList = true; bool isList = true;
for (int i = 1; i < tokens.size(); ++i) for (int i = 1; i < tokens.size(); ++i)
@@ -140,15 +150,13 @@ void WebSocketController::handleProtocol(const QString &msg)
// ---- VER ---- // ---- VER ----
if (cmd == "VER" && tokens.size() >= 3) { if (cmd == "VER" && tokens.size() >= 3) {
if (m_versionsPanel) if (m_versionsPanel) m_versionsPanel->setVersion(tokens[1], tokens.mid(2).join(' '));
m_versionsPanel->setVersion(tokens[1], tokens.mid(2).join(' '));
return; return;
} }
// ---- UID ---- // ---- UID ----
if (cmd == "UID" && tokens.size() >= 3) { if (cmd == "UID" && tokens.size() >= 3) {
if (m_versionsPanel) if (m_versionsPanel) m_versionsPanel->setUid(tokens[1], tokens.mid(2).join(' '));
m_versionsPanel->setUid(tokens[1], tokens.mid(2).join(' '));
return; return;
} }
@@ -159,6 +167,7 @@ void WebSocketController::handleProtocol(const QString &msg)
if (ok && count > 0) { if (ok && count > 0) {
m_rnpCount = count; m_rnpCount = count;
if (m_versionsPanel) m_versionsPanel->setRnpCount(count); if (m_versionsPanel) m_versionsPanel->setRnpCount(count);
if (m_panelsPanel) m_panelsPanel->setRnpCount(count);
for (int i = 0; i < count; ++i) { for (int i = 0; i < count; ++i) {
sendCommand(QString("VER %1").arg(i)); sendCommand(QString("VER %1").arg(i));
sendCommand(QString("UID %1").arg(i)); sendCommand(QString("UID %1").arg(i));
@@ -167,13 +176,13 @@ void WebSocketController::handleProtocol(const QString &msg)
return; return;
} }
// ---- GAM listall — full catalogue ---- // ---- GAM listall ----
if (cmd == "GAM" && tokens.size() >= 2 && tokens[1] == "listall") { if (cmd == "GAM" && tokens.size() >= 2 && tokens[1] == "listall") {
if (m_gamesPanel) m_gamesPanel->loadAllFromResponse(msg); if (m_gamesPanel) m_gamesPanel->loadAllFromResponse(msg);
return; return;
} }
// ---- GAM list — installed games ---- // ---- GAM list ----
if (cmd == "GAM" && tokens.size() >= 2 && tokens[1] == "list") { if (cmd == "GAM" && tokens.size() >= 2 && tokens[1] == "list") {
if (m_gamesPanel) m_gamesPanel->loadFromResponse(msg); if (m_gamesPanel) m_gamesPanel->loadFromResponse(msg);
return; return;

View File

@@ -1,14 +1,16 @@
#pragma once #pragma once
#include <QObject> #include <QObject>
#include <QString>
#include <QStringList> #include <QStringList>
#include <QWebSocket> #include <QWebSocket>
class GamesPanel;
class LogPanel;
class PanelsPanel;
class PowerPanel;
class QLabel; class QLabel;
class QLineEdit; class QLineEdit;
class QTextEdit; class QTextEdit;
class GamesPanel;
class LogPanel;
class PowerPanel;
class SettingsTree; class SettingsTree;
class VersionsPanel; class VersionsPanel;
@@ -16,43 +18,48 @@ class WebSocketController : public QObject
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit WebSocketController(QLineEdit *urlEdit, explicit WebSocketController(QLineEdit *urlEdit, QLabel *statusLabel,
QLabel *statusLabel,
QObject *parent = nullptr); QObject *parent = nullptr);
QWebSocket *socket(); QWebSocket *socket();
bool isConnected() const;
void addLogView(QTextEdit *log); void addLogView(QTextEdit *log);
void setSettingsTree(SettingsTree *tree); void setSettingsTree(SettingsTree *tree);
void setGamesPanel(GamesPanel *panel); void setGamesPanel(GamesPanel *panel);
void setVersionsPanel(VersionsPanel *panel); void setVersionsPanel(VersionsPanel *panel);
void setPowerPanel(PowerPanel *panel); void setPowerPanel(PowerPanel *panel);
void setLogPanel(LogPanel *panel); void setLogPanel(LogPanel *panel);
bool isConnected() const; void setPanelsPanel(PanelsPanel *panel);
public slots: public slots:
void startConnection(); void startConnection();
void closeConnection(); void closeConnection();
void sendCommand(const QString &cmd); void sendCommand(const QString &cmd);
void onConnected(); void onConnected();
void onDisconnected(); void onDisconnected();
void onTextMessageReceived(const QString &msg); void onTextMessageReceived(const QString &message);
void onErrorOccurred(QAbstractSocket::SocketError error); void onErrorOccurred(QAbstractSocket::SocketError error);
private slots:
void onValueEdited(const QString &key, const QString &newValue); void onValueEdited(const QString &key, const QString &newValue);
private: private:
void handleProtocol(const QString &msg); void handleProtocol(const QString &msg);
void broadcast(const QString &line); void broadcast(const QString &line);
QWebSocket m_socket;
QLineEdit *m_urlEdit = nullptr; QLineEdit *m_urlEdit = nullptr;
QLabel *m_statusLabel = nullptr; QLabel *m_statusLabel = nullptr;
QWebSocket m_socket;
QList<QTextEdit*> m_logs; QList<QTextEdit*> m_logs;
SettingsTree *m_settingsTree = nullptr; SettingsTree *m_settingsTree = nullptr;
GamesPanel *m_gamesPanel = nullptr; GamesPanel *m_gamesPanel = nullptr;
VersionsPanel *m_versionsPanel = nullptr; VersionsPanel *m_versionsPanel = nullptr;
PowerPanel *m_powerPanel = nullptr; PowerPanel *m_powerPanel = nullptr;
LogPanel *m_logPanel = nullptr; LogPanel *m_logPanel = nullptr;
PanelsPanel *m_panelsPanel = nullptr;
QStringList m_settingsKeys; QStringList m_settingsKeys;
int m_rnpCount = -1; int m_rnpCount = -1;
}; };

328
main.cpp
View File

@@ -1,12 +1,11 @@
#include <QApplication> #include <QApplication>
#include <QClipboard>
#include <QGuiApplication>
#include <QButtonGroup> #include <QButtonGroup>
#include <QCheckBox>
#include <QClipboard>
#include <QFont> #include <QFont>
#include <QGridLayout> #include <QGridLayout>
#include <QCheckBox> #include <QGuiApplication>
#include <QHBoxLayout> #include <QHBoxLayout>
#include <QHash>
#include <QLabel> #include <QLabel>
#include <QLineEdit> #include <QLineEdit>
#include <QPushButton> #include <QPushButton>
@@ -22,6 +21,7 @@
#include "GamesPanel.h" #include "GamesPanel.h"
#include "LogPanel.h" #include "LogPanel.h"
#include "PanelsPanel.h"
#include "PowerPanel.h" #include "PowerPanel.h"
#include "SettingsTree.h" #include "SettingsTree.h"
#include "VersionsPanel.h" #include "VersionsPanel.h"
@@ -32,9 +32,7 @@
#endif #endif
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// Copy text to the OS clipboard. // OS clipboard bridge (works from button clicks in WASM via navigator.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) static void copyToClipboard(const QString &text)
{ {
@@ -45,23 +43,15 @@ static void copyToClipboard(const QString &text)
if (navigator.clipboard && navigator.clipboard.writeText) { if (navigator.clipboard && navigator.clipboard.writeText) {
navigator.clipboard.writeText(txt).catch(function() { navigator.clipboard.writeText(txt).catch(function() {
var ta = document.createElement('textarea'); var ta = document.createElement('textarea');
ta.value = txt; ta.value = txt; ta.style.position='fixed'; ta.style.opacity='0';
ta.style.position = 'fixed'; document.body.appendChild(ta); ta.focus(); ta.select();
ta.style.opacity = '0'; document.execCommand('copy'); document.body.removeChild(ta);
document.body.appendChild(ta);
ta.focus(); ta.select();
document.execCommand('copy');
document.body.removeChild(ta);
}); });
} else { } else {
var ta = document.createElement('textarea'); var ta = document.createElement('textarea');
ta.value = txt; ta.value = txt; ta.style.position='fixed'; ta.style.opacity='0';
ta.style.position = 'fixed'; document.body.appendChild(ta); ta.focus(); ta.select();
ta.style.opacity = '0'; document.execCommand('copy'); document.body.removeChild(ta);
document.body.appendChild(ta);
ta.focus(); ta.select();
document.execCommand('copy');
document.body.removeChild(ta);
} }
}, utf8.constData(), utf8.size()); }, utf8.constData(), utf8.size());
#else #else
@@ -69,11 +59,24 @@ static void copyToClipboard(const QString &text)
#endif #endif
} }
// ---------------------------------------------------------------------------
// ICON number → IP address
// ---------------------------------------------------------------------------
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);
};
// ---------------------------------------------------------------------------
static QWidget *makeGamesTab(WebSocketController *ctrl, QWidget *parent) static QWidget *makeGamesTab(WebSocketController *ctrl, QWidget *parent)
{ {
auto *panel = new GamesPanel(parent); auto *panel = new GamesPanel(parent);
ctrl->setGamesPanel(panel); ctrl->setGamesPanel(panel);
// Route GAM add commands back through the controller
QObject::connect(panel, &GamesPanel::commandRequested, QObject::connect(panel, &GamesPanel::commandRequested,
ctrl, &WebSocketController::sendCommand); ctrl, &WebSocketController::sendCommand);
return panel; return panel;
@@ -93,25 +96,20 @@ static QWidget *makeSettingsTab(WebSocketController *ctrl, QWidget *parent)
layout->setContentsMargins(2, 2, 2, 2); layout->setContentsMargins(2, 2, 2, 2);
layout->setSpacing(4); layout->setSpacing(4);
// --- Sliders row: brightness and volume side by side (top) --- // --- Sliders row (top) ---
auto *slidersRow = new QHBoxLayout(); auto *slidersRow = new QHBoxLayout();
auto *brightnessLabel = new QLabel("Brightness:", page); auto *brightnessLabel = new QLabel("Brightness:", page);
auto *brightnessSlider = new QSlider(Qt::Horizontal, page); auto *brightnessSlider = new QSlider(Qt::Horizontal, page);
brightnessSlider->setMinimum(1); brightnessSlider->setMinimum(1); brightnessSlider->setMaximum(12);
brightnessSlider->setMaximum(12); brightnessSlider->setValue(1); brightnessSlider->setEnabled(false);
brightnessSlider->setValue(1); auto *brightnessVal = new QLabel("–", page);
brightnessSlider->setEnabled(false);
auto *brightnessVal = new QLabel("", page);
brightnessVal->setFixedWidth(28); brightnessVal->setFixedWidth(28);
auto *volumeLabel = new QLabel("Volume:", page); auto *volumeLabel = new QLabel("Volume:", page);
auto *volumeSlider = new QSlider(Qt::Horizontal, page); auto *volumeSlider = new QSlider(Qt::Horizontal, page);
volumeSlider->setMinimum(1); volumeSlider->setMinimum(1); volumeSlider->setMaximum(6);
volumeSlider->setMaximum(6); volumeSlider->setValue(1); volumeSlider->setEnabled(false);
volumeSlider->setValue(1); auto *volumeVal = new QLabel("–", page);
volumeSlider->setEnabled(false);
auto *volumeVal = new QLabel("", page);
volumeVal->setFixedWidth(28); volumeVal->setFixedWidth(28);
slidersRow->addWidget(brightnessLabel); slidersRow->addWidget(brightnessLabel);
@@ -123,14 +121,14 @@ static QWidget *makeSettingsTab(WebSocketController *ctrl, QWidget *parent)
slidersRow->addWidget(volumeVal); slidersRow->addWidget(volumeVal);
layout->addLayout(slidersRow); layout->addLayout(slidersRow);
// --- Tree (takes all spare vertical space) --- // --- Tree ---
auto *tree = new SettingsTree(page); auto *tree = new SettingsTree(page);
auto *ph = new QTreeWidgetItem(tree); auto *ph = new QTreeWidgetItem(tree);
ph->setText(0, "Connect to load settings..."); ph->setText(0, "Connect to load settings...");
layout->addWidget(tree, 1); layout->addWidget(tree, 1);
ctrl->setSettingsTree(tree); ctrl->setSettingsTree(tree);
// --- Single compact toolbar row: name input + 3 GBL buttons + checkbox (below tree) --- // --- Toolbar (below tree) ---
auto *toolbar = new QHBoxLayout(); auto *toolbar = new QHBoxLayout();
auto *nameEdit = new QLineEdit(page); auto *nameEdit = new QLineEdit(page);
nameEdit->setPlaceholderText("Config name..."); nameEdit->setPlaceholderText("Config name...");
@@ -139,41 +137,29 @@ static QWidget *makeSettingsTab(WebSocketController *ctrl, QWidget *parent)
auto *loadBtn = new QPushButton("Restore from Device", page); auto *loadBtn = new QPushButton("Restore from Device", page);
auto *resetBtn = new QPushButton("Restore Defaults", page); auto *resetBtn = new QPushButton("Restore Defaults", page);
resetBtn->setStyleSheet( resetBtn->setStyleSheet(
"QPushButton { color: white; background-color: #c62828; border-radius: 4px; padding: 3px 8px; }" "QPushButton { color:white; background:#c62828; border-radius:4px; padding:3px 8px; }"
"QPushButton:hover { background-color: #b71c1c; }" "QPushButton:hover { background:#b71c1c; }"
"QPushButton:disabled { background-color: #888888; color: #cccccc; }"); "QPushButton:disabled { background:#888; color:#ccc; }");
auto *autoPowerOff = new QCheckBox("Auto Power Off", page); auto *autoPowerOff = new QCheckBox("Auto Power Off", page);
toolbar->addWidget(nameEdit); toolbar->addWidget(nameEdit); toolbar->addWidget(saveBtn);
toolbar->addWidget(saveBtn); toolbar->addWidget(loadBtn); toolbar->addWidget(resetBtn);
toolbar->addWidget(loadBtn); toolbar->addStretch(1); toolbar->addWidget(autoPowerOff);
toolbar->addWidget(resetBtn);
toolbar->addStretch(1);
toolbar->addWidget(autoPowerOff);
layout->addLayout(toolbar); layout->addLayout(toolbar);
// --- Reset to defaults (inline confirm row — no QMessageBox::exec on WASM) --- // --- Reset confirm row ---
auto *confirmRow = new QHBoxLayout(); auto *confirmRow = new QHBoxLayout();
auto *confirmLabel = new QLabel(page); auto *confirmLabel = new QLabel("Click again to confirm reset:", page);
confirmLabel->setText("Click again to confirm reset:"); confirmLabel->setStyleSheet("color:#c62828;"); confirmLabel->setVisible(false);
confirmLabel->setStyleSheet("color: #c62828;");
confirmLabel->setVisible(false);
auto *confirmYesBtn = new QPushButton("Yes, Reset", page); auto *confirmYesBtn = new QPushButton("Yes, Reset", page);
confirmYesBtn->setStyleSheet( confirmYesBtn->setStyleSheet("QPushButton{color:white;background:#c62828;border-radius:4px;padding:2px 8px;}");
"QPushButton { color: white; background-color: #c62828; border-radius: 4px; padding: 2px 8px; }");
confirmYesBtn->setVisible(false); confirmYesBtn->setVisible(false);
auto *confirmNoBtn = new QPushButton("Cancel", page); auto *confirmNoBtn = new QPushButton("Cancel", page);
confirmNoBtn->setVisible(false); confirmNoBtn->setVisible(false);
confirmRow->addWidget(confirmLabel); confirmRow->addWidget(confirmLabel); confirmRow->addWidget(confirmYesBtn);
confirmRow->addWidget(confirmYesBtn); confirmRow->addWidget(confirmNoBtn); confirmRow->addStretch(1);
confirmRow->addWidget(confirmNoBtn);
confirmRow->addStretch(1);
layout->addLayout(confirmRow); layout->addLayout(confirmRow);
// ---------------------------------------------------------------- // Save
// Connections
// ----------------------------------------------------------------
// Save config
auto doSave = [ctrl, nameEdit]() { auto doSave = [ctrl, nameEdit]() {
QString name = nameEdit->text().trimmed(); QString name = nameEdit->text().trimmed();
name.remove(QRegularExpression("[^A-Za-z0-9]")); name.remove(QRegularExpression("[^A-Za-z0-9]"));
@@ -183,8 +169,6 @@ static QWidget *makeSettingsTab(WebSocketController *ctrl, QWidget *parent)
}; };
QObject::connect(saveBtn, &QPushButton::clicked, page, doSave); QObject::connect(saveBtn, &QPushButton::clicked, page, doSave);
QObject::connect(nameEdit, &QLineEdit::returnPressed, page, doSave); QObject::connect(nameEdit, &QLineEdit::returnPressed, page, doSave);
// Restore from file
QObject::connect(loadBtn, &QPushButton::clicked, page, [ctrl, nameEdit]() { QObject::connect(loadBtn, &QPushButton::clicked, page, [ctrl, nameEdit]() {
QString name = nameEdit->text().trimmed(); QString name = nameEdit->text().trimmed();
name.remove(QRegularExpression("[^A-Za-z0-9]")); name.remove(QRegularExpression("[^A-Za-z0-9]"));
@@ -192,35 +176,24 @@ static QWidget *makeSettingsTab(WebSocketController *ctrl, QWidget *parent)
ctrl->sendCommand(QString("GBL LoadFromFile %1").arg(name)); ctrl->sendCommand(QString("GBL LoadFromFile %1").arg(name));
nameEdit->clear(); nameEdit->clear();
}); });
// Reset confirm
QObject::connect(resetBtn, &QPushButton::clicked, page, QObject::connect(resetBtn, &QPushButton::clicked, page,
[confirmLabel, confirmYesBtn, confirmNoBtn]() { [confirmLabel, confirmYesBtn, confirmNoBtn]() {
confirmLabel->setVisible(true); confirmLabel->setVisible(true); confirmYesBtn->setVisible(true); confirmNoBtn->setVisible(true);
confirmYesBtn->setVisible(true);
confirmNoBtn->setVisible(true);
}); });
QObject::connect(confirmYesBtn, &QPushButton::clicked, page, QObject::connect(confirmYesBtn, &QPushButton::clicked, page,
[ctrl, confirmLabel, confirmYesBtn, confirmNoBtn]() { [ctrl, confirmLabel, confirmYesBtn, confirmNoBtn]() {
ctrl->sendCommand(QStringLiteral("GBL ResetAllToDefaults")); ctrl->sendCommand(QStringLiteral("GBL ResetAllToDefaults"));
confirmLabel->setVisible(false); confirmLabel->setVisible(false); confirmYesBtn->setVisible(false); confirmNoBtn->setVisible(false);
confirmYesBtn->setVisible(false);
confirmNoBtn->setVisible(false);
}); });
QObject::connect(confirmNoBtn, &QPushButton::clicked, page, QObject::connect(confirmNoBtn, &QPushButton::clicked, page,
[confirmLabel, confirmYesBtn, confirmNoBtn]() { [confirmLabel, confirmYesBtn, confirmNoBtn]() {
confirmLabel->setVisible(false); confirmLabel->setVisible(false); confirmYesBtn->setVisible(false); confirmNoBtn->setVisible(false);
confirmYesBtn->setVisible(false);
confirmNoBtn->setVisible(false);
}); });
// Auto power off
QObject::connect(autoPowerOff, &QCheckBox::toggled, page, [ctrl](bool checked) { QObject::connect(autoPowerOff, &QCheckBox::toggled, page, [ctrl](bool checked) {
ctrl->sendCommand(checked ? QStringLiteral("POW EnableAutoOff") ctrl->sendCommand(checked ? QStringLiteral("POW EnableAutoOff") : QStringLiteral("POW KeepOn"));
: QStringLiteral("POW KeepOn"));
}); });
// Query brightness/volume ranges+values on connect; disable on disconnect // Slider: query ranges on connect, disable on disconnect
QObject::connect(ctrl->socket(), &QWebSocket::connected, page, [ctrl]() { QObject::connect(ctrl->socket(), &QWebSocket::connected, page, [ctrl]() {
ctrl->sendCommand(QStringLiteral("GBL brightnessMin")); ctrl->sendCommand(QStringLiteral("GBL brightnessMin"));
ctrl->sendCommand(QStringLiteral("GBL brightnessMax")); ctrl->sendCommand(QStringLiteral("GBL brightnessMax"));
@@ -231,57 +204,28 @@ static QWidget *makeSettingsTab(WebSocketController *ctrl, QWidget *parent)
}); });
QObject::connect(ctrl->socket(), &QWebSocket::disconnected, page, QObject::connect(ctrl->socket(), &QWebSocket::disconnected, page,
[brightnessSlider, brightnessVal, volumeSlider, volumeVal]() { [brightnessSlider, brightnessVal, volumeSlider, volumeVal]() {
brightnessSlider->setEnabled(false); brightnessSlider->setEnabled(false); brightnessVal->setText("–");
brightnessVal->setText(QStringLiteral("")); volumeSlider->setEnabled(false); volumeVal->setText("–");
volumeSlider->setEnabled(false);
volumeVal->setText(QStringLiteral(""));
}); });
// Parse incoming GBL brightness / sound/volume responses
QObject::connect(ctrl->socket(), &QWebSocket::textMessageReceived, page, QObject::connect(ctrl->socket(), &QWebSocket::textMessageReceived, page,
[brightnessSlider, brightnessVal, volumeSlider, volumeVal](const QString &msg) { [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> { auto parseGbl = [&](const QString &key) -> std::pair<bool,int> {
const QString prefix = QString("GBL %1=").arg(key); const QString prefix = QString("GBL %1=").arg(key);
if (!msg.startsWith(prefix)) return {false,0}; if (!msg.startsWith(prefix)) return {false,0};
bool ok = false; bool ok=false; int v=msg.mid(prefix.length()).toInt(&ok);
int v = msg.mid(prefix.length()).toInt(&ok);
return {ok,v}; return {ok,v};
}; };
if (auto [ok,v]=parseGbl("brightness"); ok) { brightnessSlider->setValue(v); brightnessVal->setText(QString::number(v)); brightnessSlider->setEnabled(true); }
if (auto [ok, v] = parseGbl("brightness"); ok) { else if (auto [ok,v]=parseGbl("brightnessMin"); ok) { brightnessSlider->setMinimum(v); }
brightnessSlider->setValue(v); else if (auto [ok,v]=parseGbl("brightnessMax"); ok) { brightnessSlider->setMaximum(v); }
brightnessVal->setText(QString::number(v)); else if (auto [ok,v]=parseGbl("sound/volume"); ok) { volumeSlider->setValue(v); volumeVal->setText(QString::number(v)); volumeSlider->setEnabled(true); }
brightnessSlider->setEnabled(true); else if (auto [ok,v]=parseGbl("sound/volumeMin"); ok) { volumeSlider->setMinimum(v); }
} else if (auto [ok, v] = parseGbl("brightnessMin"); ok) { else if (auto [ok,v]=parseGbl("sound/volumeMax"); ok) { volumeSlider->setMaximum(v); }
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()));
}); });
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; return page;
} }
@@ -293,13 +237,7 @@ static QWidget *makeManualTab(WebSocketController *ctrl, QWidget *parent)
layout->setContentsMargins(2, 2, 2, 2); layout->setContentsMargins(2, 2, 2, 2);
layout->setSpacing(4); 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..."};
const QStringList placeholders = {
"Command 1...",
"Command 2...",
"Command 3...",
"Command 4...",
};
auto *inputGrid = new QGridLayout(); auto *inputGrid = new QGridLayout();
inputGrid->setSpacing(4); inputGrid->setSpacing(4);
for (int i = 0; i < 4; ++i) { for (int i = 0; i < 4; ++i) {
@@ -314,27 +252,21 @@ static QWidget *makeManualTab(WebSocketController *ctrl, QWidget *parent)
} }
layout->addLayout(inputGrid); layout->addLayout(inputGrid);
// Log view + action buttons
auto *log = new QTextEdit(page); auto *log = new QTextEdit(page);
log->setReadOnly(true); log->setReadOnly(true);
log->setFont(QFont("Courier", 9)); log->setFont(QFont("Courier", 9));
auto *logBtnRow = new QHBoxLayout(); auto *logBtnRow = new QHBoxLayout();
auto *copyLogBtn = new QPushButton("Copy Log", page); auto *copyLogBtn = new QPushButton("Copy Log", page);
auto *clearBtn = new QPushButton("Clear Log", page); auto *clearBtn = new QPushButton("Clear Log", page);
copyLogBtn->setMaximumWidth(110); copyLogBtn->setMaximumWidth(110);
clearBtn->setMaximumWidth(100); clearBtn->setMaximumWidth(100);
logBtnRow->addWidget(copyLogBtn); logBtnRow->addWidget(copyLogBtn); logBtnRow->addWidget(clearBtn); logBtnRow->addStretch(1);
logBtnRow->addWidget(clearBtn);
logBtnRow->addStretch(1);
layout->addWidget(log, 1); layout->addWidget(log, 1);
layout->addLayout(logBtnRow); layout->addLayout(logBtnRow);
ctrl->addLogView(log); ctrl->addLogView(log);
QObject::connect(clearBtn, &QPushButton::clicked, log, &QTextEdit::clear); QObject::connect(clearBtn, &QPushButton::clicked, log, &QTextEdit::clear);
QObject::connect(copyLogBtn, &QPushButton::clicked, page, QObject::connect(copyLogBtn, &QPushButton::clicked, page, [log](){ copyToClipboard(log->toPlainText()); });
[log]() { copyToClipboard(log->toPlainText()); });
return page; return page;
} }
@@ -354,13 +286,9 @@ static QWidget *makeLogsTab(WebSocketController *ctrl, QWidget *parent)
static QWidget *makePanelsTab(WebSocketController *ctrl, QWidget *parent) static QWidget *makePanelsTab(WebSocketController *ctrl, QWidget *parent)
{ {
auto *page = new QWidget(parent); auto *panel = new PanelsPanel(parent);
auto *layout = new QVBoxLayout(page); ctrl->setPanelsPanel(panel);
auto *log = new QTextEdit(page); return panel;
log->setReadOnly(true);
layout->addWidget(log, 1);
ctrl->addLogView(log);
return page;
} }
int main(int argc, char *argv[]) int main(int argc, char *argv[])
@@ -374,108 +302,66 @@ int main(int argc, char *argv[])
mainLayout->setContentsMargins(6, 6, 6, 6); mainLayout->setContentsMargins(6, 6, 6, 6);
mainLayout->setSpacing(4); mainLayout->setSpacing(4);
// --- ICON → IP helper (formula + hardcoded overrides) --- // --- Hidden urlEdit used by WebSocketController ---
// 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); auto *urlEdit = new QLineEdit(&window);
urlEdit->setVisible(false); urlEdit->setVisible(false);
auto *statusLabel = new QLabel("Disconnected", &window); auto *statusLabel = new QLabel("Disconnected", &window);
// --- Network connection row --- // --- Network connection row ---
auto *headerRow = new QHBoxLayout(); auto *headerRow = new QHBoxLayout();
headerRow->addWidget(new QLabel("Network connection:", &window)); headerRow->addWidget(new QLabel("Network connection:", &window));
// Option 1 fixed IP
auto *radioFixed = new QRadioButton("10.110.110.10", &window); auto *radioFixed = new QRadioButton("10.110.110.10", &window);
// Option 2 ICON number → derived IP
auto *radioIcon = new QRadioButton(&window); auto *radioIcon = new QRadioButton(&window);
auto *iconSpin = new QSpinBox(&window); auto *iconSpin = new QSpinBox(&window);
iconSpin->setRange(1, 9999); iconSpin->setRange(1, 9999); iconSpin->setValue(280);
iconSpin->setValue(280); iconSpin->setFixedWidth(68); iconSpin->setAlignment(Qt::AlignRight);
iconSpin->setFixedWidth(68);
iconSpin->setAlignment(Qt::AlignRight);
auto *iconIpLabel = new QLabel(iconToIp(280), &window); auto *iconIpLabel = new QLabel(iconToIp(280), &window);
iconIpLabel->setStyleSheet("color:#555; font-style:italic;"); iconIpLabel->setStyleSheet("color:#555; font-style:italic;");
// Option 3 free text (hostname or raw IP)
auto *radioOther = new QRadioButton("other:", &window); auto *radioOther = new QRadioButton("other:", &window);
auto *otherEdit = new QLineEdit(&window); auto *otherEdit = new QLineEdit(&window);
otherEdit->setText("ftsDevkit4.local"); otherEdit->setText("ftsDevkit4.local"); otherEdit->setFixedWidth(160);
otherEdit->setFixedWidth(160); otherEdit->setEnabled(false);
otherEdit->setEnabled(false); // only active when radioOther selected
auto *btnGroup = new QButtonGroup(&window); auto *btnGroup = new QButtonGroup(&window);
btnGroup->addButton(radioFixed, 0); btnGroup->addButton(radioFixed, 0);
btnGroup->addButton(radioIcon, 1); btnGroup->addButton(radioIcon, 1);
btnGroup->addButton(radioOther, 2); btnGroup->addButton(radioOther, 2);
radioIcon->setChecked(true); // default selection radioIcon->setChecked(true);
headerRow->addWidget(radioFixed); headerRow->addWidget(radioFixed);
headerRow->addWidget(radioIcon); headerRow->addWidget(radioIcon); headerRow->addWidget(iconSpin); headerRow->addWidget(iconIpLabel);
headerRow->addWidget(iconSpin);
headerRow->addWidget(iconIpLabel);
headerRow->addSpacing(8); headerRow->addSpacing(8);
headerRow->addWidget(radioOther); headerRow->addWidget(radioOther); headerRow->addWidget(otherEdit);
headerRow->addWidget(otherEdit);
headerRow->addStretch(1); headerRow->addStretch(1);
// Buttons
auto *connectBtn = new QPushButton("Connect", &window); auto *connectBtn = new QPushButton("Connect", &window);
auto *disconnectBtn = new QPushButton("Disconnect", &window); auto *disconnectBtn = new QPushButton("Disconnect", &window);
auto *shutdownBtn = new QPushButton("Shutdown", &window); auto *shutdownBtn = new QPushButton("Shutdown", &window);
disconnectBtn->setEnabled(false); disconnectBtn->setEnabled(false); shutdownBtn->setEnabled(false);
shutdownBtn->setEnabled(false);
shutdownBtn->setStyleSheet( shutdownBtn->setStyleSheet(
"QPushButton { color: white; background-color: #c62828;" "QPushButton{color:white;background:#c62828;border-radius:4px;padding:3px 10px;}"
" border-radius: 4px; padding: 3px 10px; }" "QPushButton:hover{background:#b71c1c;}"
"QPushButton:hover { background-color: #b71c1c; }" "QPushButton:disabled{background:#888;color:#ccc;}");
"QPushButton:disabled { background-color: #888888; color: #cccccc; }"); headerRow->addWidget(connectBtn); headerRow->addWidget(disconnectBtn);
headerRow->addWidget(connectBtn); headerRow->addWidget(shutdownBtn); headerRow->addWidget(statusLabel);
headerRow->addWidget(disconnectBtn);
headerRow->addWidget(shutdownBtn);
headerRow->addWidget(statusLabel);
mainLayout->addLayout(headerRow); mainLayout->addLayout(headerRow);
// --- Build URL from current selection into the hidden urlEdit ---
auto updateUrl = [=]() { auto updateUrl = [=]() {
const int port = 5424; const int port = 5424;
QString host; QString host;
if (radioFixed->isChecked()) { if (radioFixed->isChecked()) host = QStringLiteral("10.110.110.10");
host = QStringLiteral("10.110.110.10"); else if (radioIcon->isChecked()) host = iconToIp(iconSpin->value());
} else if (radioIcon->isChecked()) { else { host = otherEdit->text().trimmed(); if (host.isEmpty()) host = "127.0.0.1"; }
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)); urlEdit->setText(QString("ws://%1:%2/").arg(host).arg(port));
}; };
updateUrl(); // set initial value updateUrl();
// Keep iconIpLabel in sync and rebuild URL whenever ICON changes
QObject::connect(iconSpin, QOverload<int>::of(&QSpinBox::valueChanged), &window, QObject::connect(iconSpin, QOverload<int>::of(&QSpinBox::valueChanged), &window,
[=](int v){ iconIpLabel->setText(iconToIp(v)); updateUrl(); }); [=](int v){ iconIpLabel->setText(iconToIp(v)); updateUrl(); });
QObject::connect(btnGroup, QOverload<int>::of(&QButtonGroup::idClicked), &window, QObject::connect(btnGroup, QOverload<int>::of(&QButtonGroup::idClicked), &window,
[=](int) { [=](int){ otherEdit->setEnabled(radioOther->isChecked()); updateUrl(); });
otherEdit->setEnabled(radioOther->isChecked()); QObject::connect(otherEdit, &QLineEdit::textChanged, &window,
updateUrl(); [=](){ if (radioOther->isChecked()) updateUrl(); });
});
QObject::connect(otherEdit, &QLineEdit::textChanged, &window, [=]() {
if (radioOther->isChecked()) updateUrl();
});
// --- Controller --- // --- Controller ---
auto *ctrl = new WebSocketController(urlEdit, statusLabel, &window); auto *ctrl = new WebSocketController(urlEdit, statusLabel, &window);
@@ -491,41 +377,31 @@ int main(int argc, char *argv[])
tabs->addTab(makePanelsTab (ctrl, &window), "Panels"); tabs->addTab(makePanelsTab (ctrl, &window), "Panels");
mainLayout->addWidget(tabs, 1); mainLayout->addWidget(tabs, 1);
// --- Shutdown: inline confirm (no QMessageBox::exec on WASM) --- // --- Shutdown inline confirm ---
auto *shutdownConfirmLabel = new QLabel("Confirm shutdown:", &window); auto *shutdownConfirmLabel = new QLabel("Confirm shutdown:", &window);
auto *shutdownConfirmYes = new QPushButton("Yes, Shutdown", &window); auto *shutdownConfirmYes = new QPushButton("Yes, Shutdown", &window);
auto *shutdownConfirmNo = new QPushButton("Cancel", &window); auto *shutdownConfirmNo = new QPushButton("Cancel", &window);
shutdownConfirmLabel->setStyleSheet("color:#c62828; font-weight:bold;"); shutdownConfirmLabel->setStyleSheet("color:#c62828; font-weight:bold;");
shutdownConfirmYes->setStyleSheet( shutdownConfirmYes->setStyleSheet("QPushButton{color:white;background:#c62828;border-radius:4px;padding:2px 8px;}");
"QPushButton { color: white; background-color: #c62828; border-radius: 4px; padding: 2px 8px; }"); shutdownConfirmLabel->setVisible(false); shutdownConfirmYes->setVisible(false); shutdownConfirmNo->setVisible(false);
shutdownConfirmLabel->setVisible(false);
shutdownConfirmYes->setVisible(false);
shutdownConfirmNo->setVisible(false);
headerRow->addWidget(shutdownConfirmLabel); headerRow->addWidget(shutdownConfirmLabel);
headerRow->addWidget(shutdownConfirmYes); headerRow->addWidget(shutdownConfirmYes);
headerRow->addWidget(shutdownConfirmNo); headerRow->addWidget(shutdownConfirmNo);
QObject::connect(shutdownBtn, &QPushButton::clicked, &window, QObject::connect(shutdownBtn, &QPushButton::clicked, &window,
[shutdownConfirmLabel, shutdownConfirmYes, shutdownConfirmNo](){ [shutdownConfirmLabel, shutdownConfirmYes, shutdownConfirmNo](){
shutdownConfirmLabel->setVisible(true); shutdownConfirmLabel->setVisible(true); shutdownConfirmYes->setVisible(true); shutdownConfirmNo->setVisible(true);
shutdownConfirmYes->setVisible(true);
shutdownConfirmNo->setVisible(true);
}); });
QObject::connect(shutdownConfirmYes, &QPushButton::clicked, &window, QObject::connect(shutdownConfirmYes, &QPushButton::clicked, &window,
[ctrl, shutdownConfirmLabel, shutdownConfirmYes, shutdownConfirmNo](){ [ctrl, shutdownConfirmLabel, shutdownConfirmYes, shutdownConfirmNo](){
ctrl->sendCommand(QStringLiteral("POW ShutDown")); ctrl->sendCommand(QStringLiteral("POW ShutDown"));
shutdownConfirmLabel->setVisible(false); shutdownConfirmLabel->setVisible(false); shutdownConfirmYes->setVisible(false); shutdownConfirmNo->setVisible(false);
shutdownConfirmYes->setVisible(false);
shutdownConfirmNo->setVisible(false);
}); });
QObject::connect(shutdownConfirmNo, &QPushButton::clicked, &window, QObject::connect(shutdownConfirmNo, &QPushButton::clicked, &window,
[shutdownConfirmLabel, shutdownConfirmYes, shutdownConfirmNo](){ [shutdownConfirmLabel, shutdownConfirmYes, shutdownConfirmNo](){
shutdownConfirmLabel->setVisible(false); shutdownConfirmLabel->setVisible(false); shutdownConfirmYes->setVisible(false); shutdownConfirmNo->setVisible(false);
shutdownConfirmYes->setVisible(false);
shutdownConfirmNo->setVisible(false);
}); });
// --- Wire up buttons ---
QObject::connect(connectBtn, &QPushButton::clicked, ctrl, &WebSocketController::startConnection); QObject::connect(connectBtn, &QPushButton::clicked, ctrl, &WebSocketController::startConnection);
QObject::connect(disconnectBtn, &QPushButton::clicked, ctrl, &WebSocketController::closeConnection); QObject::connect(disconnectBtn, &QPushButton::clicked, ctrl, &WebSocketController::closeConnection);
@@ -536,15 +412,11 @@ int main(int argc, char *argv[])
QObject::connect(ctrl->socket(), &QWebSocket::connected, &window, QObject::connect(ctrl->socket(), &QWebSocket::connected, &window,
[connectBtn, disconnectBtn, shutdownBtn](){ [connectBtn, disconnectBtn, shutdownBtn](){
connectBtn->setEnabled(false); connectBtn->setEnabled(false); disconnectBtn->setEnabled(true); shutdownBtn->setEnabled(true);
disconnectBtn->setEnabled(true);
shutdownBtn->setEnabled(true);
}); });
QObject::connect(ctrl->socket(), &QWebSocket::disconnected, &window, QObject::connect(ctrl->socket(), &QWebSocket::disconnected, &window,
[connectBtn, disconnectBtn, shutdownBtn](){ [connectBtn, disconnectBtn, shutdownBtn](){
connectBtn->setEnabled(true); connectBtn->setEnabled(true); disconnectBtn->setEnabled(false); shutdownBtn->setEnabled(false);
disconnectBtn->setEnabled(false);
shutdownBtn->setEnabled(false);
}); });
window.resize(1050, 620); window.resize(1050, 620);