SL100_FactoryTestTool/FactoryTestTool/SourceCode/Widget/MainWidget.cpp

1028 lines
41 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// MainWidget.cpp
#include "MainWidget.h"
#include "../RecvDataHandler/RecvDataHandler.h"
#include "../Json/readJsonFile.h"
#include "../LicenseGenerate/LicenseGenerate.h"
void onThreadFinished(QThread* thread, ClientHandler* handler)
{
qDebug() << "Thread finished. Deleting handler and thread.";
handler->deleteLater();
thread->deleteLater();
}
// 初始化 UI 组件和服务器
MainWidget::MainWidget(QWidget* parent) :
QWidget(parent),
nextClientId(1),
manualSend(false),
isSendingAll(false),
lastClickedGetPicCamIndex(-1),
lastClickedGetPicDevIndex(-1),
lastClickedGetVideoCamIndex(-1),
lastClickedGetVideoDevIndex(-1)
{
leftLens_imageLabel = new QLabel(this);
rightLens_imageLabel = new QLabel(this);
videoLabel = new QLabel(this);
funcConfigLineEdit = new QLineEdit(this);
setupUI();
// 打印线程池状态信息
setupTimerForThreadPoolInfo();
server = new QTcpServer(this);
connect(server, &QTcpServer::newConnection, this, [this]() {
// 检查是否有挂起的连接
while (server->hasPendingConnections()) {
QTcpSocket* socket = server->nextPendingConnection();
int clientId = nextClientId ++;
qDebug() << ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>";
qDebug() << "> A client is connected. ID:" << clientId;
qDebug() << ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>";
// 更新连接数量并更新按键文本
connectedClientsCount ++;
updateServerButtonText();
// 创建新的定时器
QTimer* timer = new QTimer(this);
timer->setSingleShot(true);
clientTimers[clientId] = timer;
// 连接定时器超时信号到槽函数
connect(timer, &QTimer::timeout, this, [this, clientId]() {
//qDebug() << "Timeout occurred for client ID:" << clientId;
for (ClientHandler* handler : clients) {
if (handler->getClientId() == clientId) {
bool invoked = QMetaObject::invokeMethod(handler, "onTimeout", Qt::DirectConnection);
if (!invoked) {
qWarning() << "Failed to invoke onTimeout for client ID:" << clientId;
}
}
}
});
QThread* thread = new QThread(this);
ClientHandler* handler = new ClientHandler(socket, frontBoardOneClickTest, frontBoardTest, frontBoardFuncConfig,
frontBoardDevInfoJson, frontBoardLicenseJson, backBoardDevInfoJson,
getPicJson, getVideoJson, clientId, nullptr);
// 将 ClientHandler 移动到线程池中的线程
handler->moveToThread(thread);
// 当线程结束时删除 handler
//connect(thread, &QThread::finished, handler, &QObject::deleteLater);
//connect(thread, &QThread::finished, thread, &QObject::deleteLater);
connect(thread, &QThread::finished, this, [=]() {
onThreadFinished(thread, handler);
});
// 将sendData信号连接到主线程中的槽上
connect(handler, &ClientHandler::sendData, this, [socket](const QByteArray& data) {
socket->write(data);
socket->flush();
});
connect(handler, &ClientHandler::startTimeout, this, [this, clientId](int timeout) {
this->onStartTimeout(clientId, timeout);
});
// 启动新的线程
thread->start();
clients.append(handler);
clients_1[clientId] = handler;
clientThreads[clientId] = thread;
connect(handler, &ClientHandler::statusUpdated, this, &MainWidget::onStatusUpdated);
//connect(handler, &ClientHandler::clientDisconnected, this, &MainWidget::onClientDisconnected);
connect(handler, &ClientHandler::allItemsProcessed, this, &MainWidget::onAllItemsProcessed);
connect(handler, &ClientHandler::selectClientDisconnected, this, &MainWidget::onDisconnectClient);
// 创建 DataHandler 对象并连接信号
DataHandler* dataHandler = new DataHandler(leftLens_imageLabel, rightLens_imageLabel, videoLabel, this);
connect(handler, &ClientHandler::dataReceived, dataHandler, &DataHandler::handleData);
connect(dataHandler, &DataHandler::statusUpdated, this, &MainWidget::onStatusUpdated);
connect(handler, &ClientHandler::startReadTimer, this, &MainWidget::startClientReadTimer);
connect(handler, &ClientHandler::stopReadTimer, this, &MainWidget::stopClientReadTimer);
// 创建和管理定时器
QTimer* readTimer = new QTimer(this);
connect(readTimer, &QTimer::timeout, handler, &ClientHandler::onTimeoutRead);
// readTimer->start(10); // 每 10ms 触发一次
// 将定时器存储到哈希表中,方便管理
clientReadTimers[clientId] = readTimer;
}
});
threadStatusTimer = new QTimer(this);
connect(threadStatusTimer, &QTimer::timeout, this, &MainWidget::onCheckThreadStatus);
//threadStatusTimer->start(100); // 每100ms检查一次线程状态
connectionStatusCheckTimer = new QTimer(this);
connect(connectionStatusCheckTimer, &QTimer::timeout, this, &MainWidget::onCheckConnectionStatus);
//connectionStatusCheckTimer->start(100); // 每100ms检查一次连接状态
}
MainWidget::~MainWidget() {
for (auto timer : clientReadTimers) {
timer->stop();
delete timer;
}
clientReadTimers.clear();
for (ClientHandler* handler : clients) {
handler->deleteLater();
}
server->close();
for (auto thread : clientThreads) {
thread->quit();
thread->wait();
delete thread;
}
clientThreads.clear();
for (auto handler : clients_1) {
handler->deleteLater();
}
clients_1.clear();
for (auto timer : clientTimers) {
timer->stop();
delete timer;
}
clientTimers.clear();
if (server->isListening()) {
server->close();
}
qDebug() << "MainWidget destroyed";
}
void MainWidget::startClientReadTimer(int clientId) {
qDebug() << "------ startClientReadTimer clientId:" << clientId;
if (clientReadTimers.contains(clientId)) {
clientReadTimers[clientId]->start(10);
}
}
void MainWidget::stopClientReadTimer(int clientId) {
qDebug() << "------ stopClientReadTimer clientId:" << clientId;
if (clientReadTimers.contains(clientId)) {
clientReadTimers[clientId]->stop();
}
}
void MainWidget::onCheckConnectionStatus()
{
int activeThreadCount = clients_1.size();
//qDebug() << "------Number of active threads:" << activeThreadCount;
for (auto it = clients_1.begin(); it != clients_1.end(); ++it) {
int clientId = it.key();
ClientHandler* handler = it.value();
QTcpSocket* socket = handler->getSocket();
if (socket->state() != QTcpSocket::ConnectedState) {
qCritical() << "--------------Connection lost for clientId:" << clientId << ". Socket state:" << socket->state();
emit handler->clientDisconnected(handler);
}
else {
qDebug() << "Connection for clientId:" << clientId << "is active.";
}
}
}
void MainWidget::onCheckThreadStatus()
{
//qDebug() << "Checking thread status...";
int activeThreadCount = clientThreads.size();
//qDebug() << "Number of active threads:" << activeThreadCount;
for (auto it = clientThreads.begin(); it != clientThreads.end(); ++it) {
int clientId = it.key();
QThread* thread = it.value();
ClientHandler* handler = nullptr;
for (ClientHandler* h : clients) {
if (h->getClientId() == clientId) {
handler = h;
break;
}
}
if (handler && handler->isData_Stuck()) {
qDebug() << "Thread for clientId:" << clientId << "is stuck.";
// 处理线程卡住的情况,比如重启线程或记录更多日志
}
else if (thread->isRunning()) {
qDebug() << "isData_Stuck = :" << handler->isData_Stuck();
qDebug() << "Thread for clientId:" << clientId << "is running.";
}
else {
qDebug() << "Thread for clientId:" << clientId << "is not running.";
// 处理线程意外停止的情况
}
}
}
// 打印线程池信息
void MainWidget::printThreadPoolInfo()
{
QThreadPool* threadPool = QThreadPool::globalInstance();
//qDebug() << "Active threads:" << threadPool->activeThreadCount();
//qDebug() << "Max threads:" << threadPool->maxThreadCount();
}
void MainWidget::setupTimerForThreadPoolInfo()
{
QTimer* timer = new QTimer(this);
connect(timer, &QTimer::timeout, this, &MainWidget::printThreadPoolInfo);
timer->start(5000); // 每5秒打印一次线程池信息
}
// 设置 UI
void MainWidget::setupUI()
{
startServerButton = new QPushButton("开始监听\n(Start Listening...)", this);
startServerButton->setFixedSize(190, 70); // 设置宽度为 190 像素,高度为 70 像素
sendAllButton = new QPushButton("一键功能测试", this);
sendAllButton->setFixedSize(190, 70); // 设置宽度为 190 像素,高度为 70 像素
sendAllButton->setEnabled(false);
statusListWidget = new QListWidget(this);
//statusListWidget->setMinimumSize(350, 880);
statusListWidget->setMinimumSize(350, 680);
statusListWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); // 设置大小策略为扩展
QHBoxLayout* buttonLayout = new QHBoxLayout;
buttonLayout->addWidget(startServerButton);
buttonLayout->addWidget(sendAllButton);
buttonLayout->addStretch();
QVBoxLayout* leftLayout = new QVBoxLayout;
leftLayout->addLayout(buttonLayout);
leftLayout->setStretch(0, 1);
leftLayout->addWidget(statusListWidget);
leftLayout->setStretch(1, 200);
saveCheckBox = new QCheckBox("", this);
selectFileButton = new QPushButton("Save", this);
selectFileButton->setFixedSize(45, 28);
clearLogButton = new QPushButton("Clear", this);
clearLogButton->setFixedSize(55, 28);
filePathLineEdit = new QLineEdit(this);
filePathLineEdit->setFixedSize(250, 28);
filePathLineEdit->setReadOnly(true);
QHBoxLayout* fileLayout = new QHBoxLayout;
fileLayout->addWidget(saveCheckBox);
fileLayout->addWidget(selectFileButton);
fileLayout->addWidget(filePathLineEdit);
fileLayout->addWidget(clearLogButton);
leftLayout->addLayout(fileLayout);
leftLayout->setStretch(2, 1);
// 读取 JSON 配置文件
readJsonConfig();
QGroupBox* groupBox = new QGroupBox("算法 license", this);
QHBoxLayout* buttonRowLayout = new QHBoxLayout;
for (int i = 0; i < frontBoardLicenseJson.size(); ++i) {
QJsonObject item = frontBoardLicenseJson[i].toObject();
QString buttonText = item["lable"].toString();
QPushButton* button = new QPushButton(buttonText, this);
button->setProperty("licenseIndex", i);
buttonRowLayout->addWidget(button);
connect(button, &QPushButton::clicked, this, &MainWidget::onLicenseButtonClicked);
}
QLineEdit* readOnlyLineEdit = new QLineEdit(this);
readOnlyLineEdit->setReadOnly(true);
readOnlyLineEdit->setText("This is a read-only text");
readOnlyLineEdit->setFixedHeight(80);
QVBoxLayout* groupBoxLayout_license = new QVBoxLayout;
groupBoxLayout_license->addLayout(buttonRowLayout);
groupBoxLayout_license->addWidget(readOnlyLineEdit);
groupBox->setLayout(groupBoxLayout_license);
leftLayout->addWidget(groupBox);
leftLayout->setStretch(3, 1);
QWidget* leftContainer = new QWidget(this);
leftContainer->setLayout(leftLayout);
leftContainer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
QTabWidget* tabWidget = new QTabWidget(this);
tabWidget->setFixedSize(900, 315); // 设置 QTabWidget 的固定大小
QGroupBox* frontDeviceInfoGroupBox = new QGroupBox("前板设备信息", this);
QVBoxLayout* frontDeviceInfoLayout = new QVBoxLayout(frontDeviceInfoGroupBox);
QVBoxLayout* frontDeviceLabelsLayout = new QVBoxLayout;
for (const QJsonValue& value : frontBoardDevInfoJson) {
QJsonObject item = value.toObject();
QString label = item["lable"].toString();
QLabel* itemLabel = new QLabel(label, this);
QLineEdit* itemLineEdit = new QLineEdit(this);
itemLineEdit->setReadOnly(true);
QHBoxLayout* itemLayout = new QHBoxLayout;
itemLayout->addWidget(itemLabel);
itemLayout->addWidget(itemLineEdit);
frontDeviceLabelsLayout->addLayout(itemLayout);
}
frontDeviceInfoLayout->addLayout(frontDeviceLabelsLayout);
frontDeviceInfoLayout->addStretch();
QGroupBox* backDeviceInfoGroupBox = new QGroupBox("后板设备信息", this);
QVBoxLayout* backDeviceInfoLayout = new QVBoxLayout(backDeviceInfoGroupBox);
QVBoxLayout* backDeviceLabelsLayout = new QVBoxLayout;
for (const QJsonValue& value : backBoardDevInfoJson) {
QJsonObject item = value.toObject();
QString label = item["lable"].toString();
QLabel* itemLabel = new QLabel(label, this);
QLineEdit* itemLineEdit = new QLineEdit(this);
itemLineEdit->setReadOnly(true);
QHBoxLayout* itemLayout = new QHBoxLayout;
itemLayout->addWidget(itemLabel);
itemLayout->addWidget(itemLineEdit);
backDeviceLabelsLayout->addLayout(itemLayout);
}
backDeviceInfoLayout->addLayout(backDeviceLabelsLayout);
backDeviceInfoLayout->addStretch();
QHBoxLayout* groupBoxLayout = new QHBoxLayout;
groupBoxLayout->addWidget(frontDeviceInfoGroupBox, 1);
groupBoxLayout->addWidget(backDeviceInfoGroupBox, 1);
QWidget* functionTestTab = new QWidget;
QVBoxLayout* functionTestLayout = new QVBoxLayout(functionTestTab);
functionTestTab->setLayout(functionTestLayout);
tabWidget->addTab(functionTestTab, "功能测试区");
QGridLayout* buttonGridLayout = new QGridLayout();
int buttonsPerRow = 7; // 每行显示的按键数量,根据需要调整
// 为每个 JSON 项目创建按键,并添加到 rightLayout
// 先总共放 77 个按键
//qDebug() << "testJsonConfig.size():" << testJsonConfig.size();
for (int i = 0; i < frontBoardTest.size() + (77 - frontBoardTest.size()); ++i) {
QJsonObject item = frontBoardTest[i].toObject();
QString buttonText = item["lable"].toString();
// 判断 buttonText 是否为空或者只有空白字符
if (buttonText.isEmpty()) {
//qDebug() << "buttonText.isEmpty():" << buttonText.isEmpty();
buttonText = QString("Send Item %1").arg(i + 1);
}
QPushButton* button = new QPushButton(buttonText, this);
button->setProperty("frontBoardTest", i);
button->setFixedSize(110, 35); // 设置按键宽度和高度
connect(button, &QPushButton::clicked, this, &MainWidget::onSendItemClicked);
int row = i / buttonsPerRow;
int col = i % buttonsPerRow;
buttonGridLayout->addWidget(button, row, col, Qt::AlignLeft);
itemButtons.append(button);
}
QWidget* buttonContainer = new QWidget;
buttonContainer->setLayout(buttonGridLayout);
QScrollArea* scrollArea = new QScrollArea;
scrollArea->setWidget(buttonContainer);
scrollArea->setWidgetResizable(true);
functionTestLayout->addWidget(scrollArea);
QWidget* functionConfigTab = new QWidget;
QVBoxLayout* functionConfigLayout = new QVBoxLayout(functionConfigTab);
functionConfigTab->setLayout(functionConfigLayout);
tabWidget->addTab(functionConfigTab, "功能配置区");
funcConfigLineEdit->setPlaceholderText("请输入配置参数...");
functionConfigLayout->addWidget(funcConfigLineEdit);
QGridLayout* configButtonGridLayout = new QGridLayout();
for (int i = 0; i < frontBoardFuncConfig.size() + (77 - frontBoardFuncConfig.size()); ++i) {
QJsonObject item = frontBoardFuncConfig[i].toObject();
QString buttonText = item["lable"].toString();
// 判断 buttonText 是否为空或者只有空白字符
if (buttonText.isEmpty()) {
//qDebug() << "buttonText.isEmpty():" << buttonText.isEmpty();
buttonText = QString("Cfg Item %1").arg(i + 1);
}
QPushButton* button = new QPushButton(buttonText, this);
button->setProperty("frontBoardFuncConfig", i);
button->setFixedSize(110, 35); // 设置按键宽度和高度
connect(button, &QPushButton::clicked, this, &MainWidget::onSendFuncItemClicked);
int row = i / buttonsPerRow;
int col = i % buttonsPerRow;
configButtonGridLayout->addWidget(button, row, col, Qt::AlignLeft);
funcItemButtons.append(button);
}
QWidget* configButtonContainer = new QWidget;
configButtonContainer->setLayout(configButtonGridLayout);
QScrollArea* configScrollArea = new QScrollArea;
configScrollArea->setWidget(configButtonContainer);
configScrollArea->setWidgetResizable(true);
functionConfigLayout->addWidget(configScrollArea);
QTabWidget* tabWidget_media = new QTabWidget(this);
QWidget* imageDisplayTab = new QWidget;
QVBoxLayout* imageDisplayLayout = new QVBoxLayout(imageDisplayTab);
imageDisplayTab->setLayout(imageDisplayLayout);
tabWidget_media->addTab(imageDisplayTab, "图像显示区");
QVBoxLayout* imageButtonsColumnLayout = new QVBoxLayout;
for (int i = 0; i < 5; ++i) {
QHBoxLayout* imageButtonsRowLayout = new QHBoxLayout;
for (int j = 0; j < 2; ++j) {
QPushButton* button;
if (i == 0 && j == 0) {
button = new QPushButton(QString("IR"), this);
button->setFixedSize(73, 50);
imageButtonsRowLayout->addWidget(button);
button->setProperty("getPicIndex", i * 2 + j);
connect(button, &QPushButton::clicked, this, &MainWidget::onSendGetPicClicked);
getPicButtons.append(button);
continue;
}
else if (i == 0 && j == 1) {
button = new QPushButton(QString("RGB"), this);
button->setFixedSize(73, 50);
imageButtonsRowLayout->addWidget(button);
button->setProperty("getPicIndex", i * 2 + j);
connect(button, &QPushButton::clicked, this, &MainWidget::onSendGetPicClicked);
getPicButtons.append(button);
continue;
}
button = new QPushButton(QString("Device %1").arg(i * 2 + j - 1), this);
button->setFixedSize(73, 50);
imageButtonsRowLayout->addWidget(button);
button->setProperty("getPicIndex", i * 2 + j);
connect(button, &QPushButton::clicked, this, &MainWidget::onSendGetPicClicked);
getPicButtons.append(button);
}
imageButtonsColumnLayout->addLayout(imageButtonsRowLayout);
}
QHBoxLayout* lensesLayout = new QHBoxLayout;
leftLens_imageLabel = new QLabel(this);
rightLens_imageLabel = new QLabel(this);
lensesLayout->addWidget(leftLens_imageLabel);
lensesLayout->addWidget(rightLens_imageLabel);
QHBoxLayout* imageAndButtonsLayout = new QHBoxLayout;
imageAndButtonsLayout->addLayout(imageButtonsColumnLayout, 1);
imageAndButtonsLayout->addLayout(lensesLayout, 4);
imageDisplayLayout->addLayout(imageAndButtonsLayout);
QWidget* videoDisplayTab = new QWidget;
QVBoxLayout* videoDisplayLayout = new QVBoxLayout(videoDisplayTab);
videoDisplayTab->setLayout(videoDisplayLayout);
tabWidget_media->addTab(videoDisplayTab, "视频显示区");
QVBoxLayout* videoButtonsColumnLayout = new QVBoxLayout;
for (int i = 0; i < 6; ++i) {
QHBoxLayout* videoButtonsRowLayout = new QHBoxLayout;
for (int j = 0; j < 2; ++j) {
QPushButton* button;
if (i == 0 && j == 0) {
button = new QPushButton(QString("IR"), this);
button->setFixedSize(73, 50);
videoButtonsRowLayout->addWidget(button);
button->setProperty("getVideoIndex", i * 2 + j);
connect(button, &QPushButton::clicked, this, &MainWidget::onSendGetVideoClicked);
getVideoButtons.append(button);
continue;
}
else if (i == 0 && j == 1) {
button = new QPushButton(QString("RGB"), this);
button->setFixedSize(73, 50);
videoButtonsRowLayout->addWidget(button);
button->setProperty("getVideoIndex", i * 2 + j);
connect(button, &QPushButton::clicked, this, &MainWidget::onSendGetVideoClicked);
getVideoButtons.append(button);
continue;
}
// 调价调焦窗口按键
if (i == 1 && j == 0) {
button = new QPushButton(QString("大窗口播放视频"), this);
button->setFixedSize(150, 50);
button->setEnabled(false);
videoButtonsRowLayout->addWidget(button);
button->setProperty("getVideoIndex", i * 2 + j);
connect(button, &QPushButton::clicked, this, &MainWidget::onOpenFocusWindowClicked);
getVideoButtons.append(button);
break; // 跳出内层循环,只添加一个按键
}
//int adjustedIndex = (i > 1) ? i * 2 + j - 1 : i * 2 + j;
button = new QPushButton(QString("Device %1").arg(i * 2 + j - 3), this);
//button = new QPushButton(QString("Device %1").arg(adjustedIndex), this);
button->setFixedSize(73, 50);
videoButtonsRowLayout->addWidget(button);
button->setProperty("getVideoIndex", i * 2 + j + 1);
//button->setProperty("getVideoIndex", adjustedIndex);
connect(button, &QPushButton::clicked, this, &MainWidget::onSendGetVideoClicked);
getVideoButtons.append(button);
}
videoButtonsColumnLayout->addLayout(videoButtonsRowLayout);
}
QHBoxLayout* videoAndButtonsLayout = new QHBoxLayout;
videoLabel = new QLabel(this);
//videoLabel->setFixedSize(640, 480);
videoAndButtonsLayout->addLayout(videoButtonsColumnLayout, 1);
videoAndButtonsLayout->addWidget(videoLabel, 6);
videoDisplayLayout->addLayout(videoAndButtonsLayout);
QVBoxLayout* rightVerticalLayout = new QVBoxLayout;
rightVerticalLayout->addLayout(groupBoxLayout, 2);
rightVerticalLayout->addWidget(tabWidget, 2, Qt::AlignTop | Qt::AlignLeft);
rightVerticalLayout->addWidget(tabWidget_media, 5);
QHBoxLayout* mainLayout = new QHBoxLayout;
// 参数二伸缩因子leftContainer1/3 rightLayout2/3
mainLayout->addWidget(leftContainer, 1, Qt::AlignTop | Qt::AlignLeft); // 设置 leftContainer 左上对齐
mainLayout->addLayout(rightVerticalLayout, 3);
setLayout(mainLayout);
setWindowTitle("SL100 工厂产测工具 - V0.0.1");
resize(1340, 1000); // 设置宽度为 1440 像素,高度为 900 像素
connect(startServerButton, &QPushButton::clicked, this, &MainWidget::onStartServerClicked);
connect(sendAllButton, &QPushButton::clicked, this, &MainWidget::onSendAllClicked);
connect(statusListWidget, &QListWidget::itemChanged, this, &MainWidget::scrollToBottom);
connect(selectFileButton, &QPushButton::clicked, this, &MainWidget::onSelectFileButtonClicked);
connect(clearLogButton, &QPushButton::clicked, this, &MainWidget::onclearLogButtonClicked);
connect(saveCheckBox, &QCheckBox::stateChanged, this, &MainWidget::onSaveCheckBoxStateChanged);
}
void MainWidget::onSelectFileButtonClicked()
{
QString filePath = QFileDialog::getSaveFileName(this, tr("选择文件路径"), "", tr("Text Files (*.txt);;All Files (*)"));
if (!filePath.isEmpty()) {
filePathLineEdit->setText(filePath);
}
}
void MainWidget::onclearLogButtonClicked()
{
statusListWidget->clear();
}
void MainWidget::onSaveCheckBoxStateChanged(int state)
{
if (state == Qt::Checked) {
saveStatusListToFile(filePathLineEdit->text());
}
}
void MainWidget::saveStatusListToFile(const QString& filePath)
{
if (filePath.isEmpty()) {
return;
}
QFile file(filePath);
if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
return;
}
QTextStream out(&file);
for (int i = 0; i < statusListWidget->count(); ++i) {
QListWidgetItem* item = statusListWidget->item(i);
out << item->text() << "\n";
}
file.close();
}
void MainWidget::onStartTimeout(int clientId, int timeout)
{
//qDebug() << "---------------> onStartTimeout :" << clientId << "timeout :" << timeout;
if (clientTimers.contains(clientId)) {
QTimer* timer = clientTimers[clientId];
if (timeout > 0) {
timer->start(timeout);
}
else {
timer->stop();
}
}
}
void MainWidget::scrollToBottom()
{
statusListWidget->scrollToBottom();
}
void MainWidget::readJsonConfig()
{
frontBoardOneClickTest = readJson_frontBoardOneClickTest();
frontBoardTest = readJson_frontBoardTest();
frontBoardFuncConfig = readJson_frontBoardFuncConfig();
frontBoardDevInfoJson = readJson_frontDevInfo();
frontBoardLicenseJson = readJson_frontLicense();
backBoardDevInfoJson = readJson_backDevInfo();
testJsonConfig = readJson_testConfig();
funcJsonConfig = readJson_funcConfig();
getPicJson = readJson_getPic();
getVideoJson = readJson_getVideo();
}
void MainWidget::onDisconnectClient(int clientId)
{
for (ClientHandler* handler : clients) {
if (handler->getClientId() == clientId) {
// 断开与该客户端的连接
handler->getSocket()->disconnectFromHost();
handler->getSocket()->waitForDisconnected();
clients.removeOne(handler);
if (clientTimers.contains(clientId)) {
QTimer* timer = clientTimers[clientId];
timer->stop();
delete timer;
clientTimers.remove(clientId);
}
handler->deleteLater();
// 更新连接数并更新按键文本
connectedClientsCount --;
updateServerButtonText();
break;
}
}
}
// 处理客户端断开连接信号
void MainWidget::onClientDisconnected(ClientHandler* handler)
{
int clientId = handler->getClientId();
if (clientTimers.contains(clientId)) {
QTimer* timer = clientTimers[clientId];
timer->stop();
delete timer;
clientTimers.remove(clientId);
}
clients.removeOne(handler);
/*
将 ClientHandler 对象的删除操作放入事件队列中,等待事件循环处理。
在事件循环执行时,会安全地删除 ClientHandler 对象,这包括释放其占用的资源和内存
*/
handler->deleteLater(); // 延迟删除 ClientHandler 对象
// 更新连接数并更新按键文本
connectedClientsCount --;
if(nextClientId <= 2) nextClientId --;
deviceConnected = true;
updateServerButtonText();
}
// 更新按键文本的函数
void MainWidget::updateServerButtonText()
{
if (deviceConnected) {
deviceConnected = false;
startServerButton->setText(tr("正在监听(Listening)"));
}
else if (connectedClientsCount == 0) {
startServerButton->setText(tr("开始监听\n(Start Listening...)"));
}
else {
startServerButton->setText(tr("正在监听(Listening)\n%1 台设备连接").arg(connectedClientsCount));
}
}
// 处理 License 按键点击事件
void MainWidget::onLicenseButtonClicked()
{
if (connectedClientsCount) {
QPushButton* button = qobject_cast<QPushButton*>(sender());
if (button) {
int index = button->property("licenseIndex").toInt();
if (index >= 0 && index < frontBoardLicenseJson.size()) {
QJsonObject jsonObject = frontBoardLicenseJson[index].toObject();
QString jsonString = QJsonDocument(jsonObject).toJson(QJsonDocument::Compact);
//qDebug() << "license Button clicked, sending JSON:" << jsonString;
for (ClientHandler* handler : clients) {
handler->sendLicenseItem(index);
}
}
}
}
else {
QListWidgetItem* listItem = new QListWidgetItem(QString("No device is connected !!!"), statusListWidget);
listItem->setBackground(Qt::red);
}
}
// 处理开始服务器按键点击事件
void MainWidget::onStartServerClicked()
{
if (!server->isListening()) {
// 根据需要修改
//QHostAddress specifiedIpAddress("10.10.10.253");
quint16 specifiedPort = 12412;
qDebug() << "" << specifiedPort;
if (server->listen(QHostAddress::Any, specifiedPort)) {
startServerButton->setText(tr("正在监听(Listening)"));
// 设置按钮背景色为绿色
startServerButton->setStyleSheet("background-color: green;");
sendAllButton->setEnabled(true);
}
else {
qDebug() << "Failed to start server. Error:" << server->errorString();
}
}
else {
server->close();
startServerButton->setText(tr("开始监听\n(Start Listening...)"));
startServerButton->setStyleSheet("");
sendAllButton->setEnabled(false);
}
}
// 处理发送获取设备信息按键点击事件
void MainWidget::onSendGetDevInfoClicked()
{
if (connectedClientsCount) {
QPushButton* button = qobject_cast<QPushButton*>(sender());
int itemIndex = button->property("deviceInfoIndex").toInt();
if (itemIndex + 1 > connectedClientsCount) {
QListWidgetItem* listItem = new QListWidgetItem(QString("No device %1 is connected !!!").arg(itemIndex + 1), statusListWidget);
listItem->setBackground(Qt::red);
}
else {
for (ClientHandler* handler : clients) {
handler->sendGetDevInfoItem(itemIndex);
}
}
}
else {
QListWidgetItem* listItem = new QListWidgetItem(QString("No device is connected !!!"), statusListWidget);
listItem->setBackground(Qt::red);
}
}
// 处理发送取图按键点击事件
void MainWidget::onSendGetPicClicked()
{
if (connectedClientsCount) {
QPushButton* button = qobject_cast<QPushButton*>(sender());
int itemIndex = button->property("getPicIndex").toInt();
if (itemIndex < 2) {
button->setStyleSheet("background-color: green;");
if (lastClickedGetPicCamIndex != -1 && lastClickedGetPicCamIndex != itemIndex) {
getPicButtons[lastClickedGetPicCamIndex]->setStyleSheet("");
}
lastClickedGetPicCamIndex = itemIndex;
}
else {
if (lastClickedGetPicCamIndex == -1) {
QListWidgetItem* listItem = new QListWidgetItem(QString("Please select IR or RGB lens to get image!!!"), statusListWidget);
listItem->setBackground(Qt::red);
}
else {
if (itemIndex - 2 >= connectedClientsCount) {
QListWidgetItem* listItem = new QListWidgetItem(QString("No device %1 is connected !!!").arg(itemIndex - 1), statusListWidget);
listItem->setBackground(Qt::red);
}
else {
button->setStyleSheet("background-color: green;");
if (lastClickedGetPicDevIndex != -1 && lastClickedGetPicDevIndex != itemIndex) {
getPicButtons[lastClickedGetPicDevIndex]->setStyleSheet("");
}
lastClickedGetPicDevIndex = itemIndex;
//QMutexLocker locker(&mutex);
for (ClientHandler* handler : clients) {
handler->sendGetPicItem(itemIndex - 2);
}
}
}
}
}
else {
QListWidgetItem* listItem = new QListWidgetItem(QString("No device is connected !!!"), statusListWidget);
listItem->setBackground(Qt::red);
}
}
// 处理发送拉视频流按键点击事件
void MainWidget::onSendGetVideoClicked()
{
if (connectedClientsCount) {
QPushButton* button = qobject_cast<QPushButton*>(sender());
int itemIndex = button->property("getVideoIndex").toInt();
if (itemIndex < 2) {
button->setStyleSheet("background-color: green;");
if (lastClickedGetVideoCamIndex != -1 && lastClickedGetVideoCamIndex != itemIndex) {
getVideoButtons[lastClickedGetVideoCamIndex]->setStyleSheet("");
}
lastClickedGetVideoCamIndex = itemIndex;
}
else {
if (lastClickedGetVideoCamIndex == -1) {
QListWidgetItem* listItem = new QListWidgetItem(QString("Please select IR or RGB lens to get video!!!"), statusListWidget);
listItem->setBackground(Qt::red);
}
else {
if (itemIndex - 5 >= connectedClientsCount) {
QListWidgetItem* listItem = new QListWidgetItem(QString("No device %1 is connected !!!").arg(itemIndex - 4), statusListWidget);
listItem->setBackground(Qt::red);
}
else {
button->setStyleSheet("background-color: green;");
if (lastClickedGetVideoDevIndex != -1 && lastClickedGetVideoDevIndex != itemIndex) {
getVideoButtons[lastClickedGetVideoDevIndex]->setStyleSheet("");
}
lastClickedGetVideoDevIndex = itemIndex;
//QMutexLocker locker(&mutex);
for (ClientHandler* handler : clients) {
// 发送当前设备取图的指令
handler->sendGetVideoItem(itemIndex - 5, 1);
}
getVideoButtons[2]->setEnabled(true);
}
}
}
}
else {
QListWidgetItem* listItem = new QListWidgetItem(QString("No device is connected !!!"), statusListWidget);
listItem->setBackground(Qt::red);
}
}
void MainWidget::onOpenFocusWindowClicked()
{
QPushButton* button = qobject_cast<QPushButton*>(sender());
if (button) {
int itemIndex = button->property("getVideoIndex").toInt();
//qDebug() << "New Button clicked with itemIndex:" << itemIndex;
if (itemIndex == 2) {
// 创建并显示新窗口
NewButtonDialog dialog(this);
dialog.exec();
}
}
}
//void MainWidget::onPowerOnSend()
//{
//
//}
// 处理一键发送按键点击事件
void MainWidget::onSendAllClicked()
{
if (connectedClientsCount) {
QMutexLocker locker(&mutex);
isSendingAll = !isSendingAll;
if (isSendingAll) {
sendAllButton->setText("一键功能测试中...\n再次点击取消");
sendAllButton->setStyleSheet("background-color: green;");
manualSend = true;
for (ClientHandler* handler : clients) {
// 重置索引
handler->resetCurrentItemIndex();
//handler->sendNextItem();
handler->sendDevInfoItem();
//licenseGenerate();
}
}
else {
sendAllButton->setText("一键功能测试");
sendAllButton->setStyleSheet("background-color: white;");
manualSend = false;
for (ClientHandler* handler : clients) {
handler->resetCurrentItemIndex();
}
}
}
else {
QListWidgetItem* listItem = new QListWidgetItem(QString("No device is connected !!!"), statusListWidget);
listItem->setBackground(Qt::red);
}
}
// 处理单独发送功能项按键点击事件
void MainWidget::onSendFuncItemClicked()
{
if (connectedClientsCount) {
QPushButton* button = qobject_cast<QPushButton*>(sender());
int itemIndex = button->property("frontBoardFuncConfig").toInt();
for (ClientHandler* handler : clients) {
QString text = funcConfigLineEdit->text();
qDebug() << "Text in funcConfigLineEdit:" << text;
handler->sendFuncItem(itemIndex, text);
}
}
else {
QListWidgetItem* listItem = new QListWidgetItem(QString("No device is connected !!!"), statusListWidget);
listItem->setBackground(Qt::red);
}
}
// 处理单独发送项按键点击事件
void MainWidget::onSendItemClicked()
{
if (connectedClientsCount) {
QPushButton* button = qobject_cast<QPushButton*>(sender());
int itemIndex = button->property("frontBoardTest").toInt();
for (ClientHandler* handler : clients) {
handler->sendItem(itemIndex);
}
}
else {
QListWidgetItem* listItem = new QListWidgetItem(QString("No device is connected !!!"), statusListWidget);
listItem->setBackground(Qt::red);
}
}
// 处理状态更新信号
void MainWidget::onStatusUpdated(const QString& client, int itemIndex, int FuncItemIndex,
bool success, const QString& itemData, const QString& funcItemData)
{
int clientId = -1;
// 遍历所有的 ClientHandler找到匹配的 client
for (ClientHandler* handler : clients) {
if (handler->getClientAddress() == client) {
clientId = handler->getClientId();
QString lable = handler->getCurrentItemLable();
lable = handler->getCurrentFuncItemLable();
break;
}
else
{
//qDebug() << "" << __FUNCTION__ << "handler->getClientAddress() != client" ;
}
}
//qDebug() << "itemIndex :" << itemIndex;
//qDebug() << "FuncItemIndex:" << FuncItemIndex;
if (itemIndex > 0) {
QListWidgetItem* listItem = new QListWidgetItem(QString("device ID: %1 - Item %2: %3 ---> %4")
.arg(clientId)
.arg(itemIndex)
.arg(itemData) // data 字段
.arg(success ? "OK" : "NG"), statusListWidget);
listItem->setBackground(success ? Qt::green : Qt::red);
statusListWidget->addItem(listItem);
}
else if (FuncItemIndex > 0) {
QListWidgetItem* listItem = new QListWidgetItem(QString("device ID: %1 - funcItem %2: %3 ---> %4")
.arg(clientId)
.arg(FuncItemIndex)
.arg(funcItemData) // data 字段
.arg(success ? "OK" : "NG"), statusListWidget);
listItem->setBackground(success ? Qt::green : Qt::red);
statusListWidget->addItem(listItem);
}
statusListWidget->scrollToBottom();
}
// json文件里面的配置项都测试结束
void MainWidget::onAllItemsProcessed(const QString& client, int itemsProcessedCount)
{
isSendingAll = false;
sendAllButton->setText("一键功能测试");
sendAllButton->setStyleSheet("background-color: white;");
//qDebug() << "onAllItemsProcessed called for client:" << client << "itemsProcessedCount:" << itemsProcessedCount;
int clientId = -1;
for (ClientHandler* handler : clients) {
if (handler->getClientAddress() == client) {
clientId = handler->getClientId();
qDebug() << "Current clientId:" << clientId;
break;
}
else
{
//qDebug() << "" << __FUNCTION__ << "handler->getClientAddress() != client";
}
}
QListWidgetItem* listItem = new QListWidgetItem(QString("device ID:-%1 ---> All %2 items test completed !!!")
.arg(clientId)
.arg(itemsProcessedCount), statusListWidget);
statusListWidget->addItem(listItem);
statusListWidget->scrollToBottom();
}