#include "mainwindow.h" #include "ui_mainwindow.h" #include "Version.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include "IVrUtils.h" #include "VrLog.h" MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) , ui(new Ui::MainWindow) { ui->setupUi(this); // 设置窗口图标 this->setWindowIcon(QIcon(":/common/resource/logo.png")); // 设置状态栏字体 QFont statusFont = statusBar()->font(); statusFont.setPointSize(12); statusBar()->setFont(statusFont); // 设置状态栏颜色和padding statusBar()->setStyleSheet("QStatusBar { color: rgb(239, 241, 245); padding: 20px; }"); // 隐藏标题栏 setWindowFlags(Qt::FramelessWindowHint); // 启动后自动最大化显示 this->showMaximized(); // 初始化时隐藏label_work ui->label_work->setVisible(false); ui->btn_start->setVisible(false); ui->btn_stop->setVisible(false); // 创建组合控件 // m_gridWithTable = new ImageGridWithTableWidget(); m_gridView = new ImageGridWidget(); m_deviceStatusWidget = new DeviceStatusWidget(); m_tearingDataTableWidget = new TearingDataTableWidget(); // 将设备状态widget添加到frame_dev中 QVBoxLayout* frameResultImageLayout = new QVBoxLayout(ui->detect_result); frameResultImageLayout->setContentsMargins(0, 0, 0, 0); frameResultImageLayout->addWidget(m_gridView); // 将TearingDataTableWidget添加到detect_data中 QVBoxLayout* frameDataLayout = new QVBoxLayout(ui->detect_data); frameDataLayout->setContentsMargins(0, 0, 0, 0); frameDataLayout->addWidget(m_tearingDataTableWidget); QVBoxLayout* frameDevLayout = new QVBoxLayout(ui->device_status); frameDevLayout->setContentsMargins(0, 0, 0, 0); frameDevLayout->addWidget(m_deviceStatusWidget); // 初始化Presenter m_presenter = new BeltTearingPresenter(); // 将设备状态控件与Presenter关联 m_presenter->setStatusUpdate(this); // 连接服务器数据接收信号 connect(m_presenter, &BeltTearingPresenter::serverDataReceived, this, &MainWindow::onServerDataReceived); // 连接配置更新信号 connect(m_presenter, &BeltTearingPresenter::configUpdated, this, &MainWindow::onConfigSaved); // 连接设备点击信号到重新检测槽函数 connect(m_deviceStatusWidget, &DeviceStatusWidget::deviceClicked, this, &MainWindow::onDeviceClicked); // 设置版本信息显示 setupVersionDisplay(); // 设置表格最大行数限制,防止内存占用过大 if (m_tearingDataTableWidget) { m_tearingDataTableWidget->setMaximumRows(100); } m_presenter->Init(); } MainWindow::~MainWindow() { if(m_gridWithTable){ delete m_gridWithTable; m_gridWithTable = nullptr; } if (m_deviceStatusWidget) { delete m_deviceStatusWidget; m_deviceStatusWidget = nullptr; } if (m_tearingDataTableWidget) { delete m_tearingDataTableWidget; m_tearingDataTableWidget = nullptr; } if (m_versionLabel) { delete m_versionLabel; m_versionLabel = nullptr; } if (m_dialogAlgoarg) { delete m_dialogAlgoarg; m_dialogAlgoarg = nullptr; } if (m_presenter) { delete m_presenter; m_presenter = nullptr; } delete ui; } void MainWindow::resizeEvent(QResizeEvent* event) { QMainWindow::resizeEvent(event); // 获取窗口大小 QSize size = event->size(); int width = size.width(); int height = size.height(); // 调整title_group (groupBox) 宽度 ui->title_group->setGeometry(0, 0, width, 120); // 调整btn_hide和btn_close位置 ui->btn_hide->move(width - 158, 32); ui->btn_close->move(width - 79, 32); // 调整detect_result控件 int detectResultWidth = width - 560 - 40 - 10; // 为两侧控件留出空间 int detectResultHeight = height - 160; // 减去标题栏高度 ui->detect_result->setGeometry(20, 140, detectResultWidth, detectResultHeight); // 调整detect_data控件 int detectDataWidth = 560; // 保持宽度不变 int detectDataHeight = height - 140 - 160 - 10; // 减去标题栏和底部控件高度 ui->detect_data->setGeometry(20 + detectResultWidth + 10, 140, detectDataWidth, detectDataHeight); // 调整device_status控件 int deviceStatusWidth = 560; // 保持宽度不变 int deviceStatusHeight = 140; // 保持高度不变 ui->device_status->setGeometry(20 + detectResultWidth + 10, height - 160, deviceStatusWidth, deviceStatusHeight); } void MainWindow::resizeToFitContent() { if (!m_gridWithTable || m_gridWithTable->columnCount() == 0) { return; } // 计算网格总宽度(列数 * 格子宽度 + 边距) int gridWidth = m_gridWithTable->columnCount() * m_gridWithTable->tileBaseSize().width() + 32; // 加上表格宽度 int totalWidth = gridWidth + 260; // 计算总高度(行数 * 格子高度 + 边距) int totalHeight = m_gridWithTable->rowCount() * m_gridWithTable->tileBaseSize().height() + 32; // 设置窗口大小 resize(totalWidth, totalHeight); } void MainWindow::on_btn_hide_clicked() { // 最小化窗口 this->showMinimized(); } void MainWindow::on_btn_close_clicked() { // 关闭应用程序 this->close(); } void MainWindow::on_btn_test_clicked() { } void MainWindow::on_btn_camera_clicked() { if(nullptr == ui_dialognetconfig){ ui_dialognetconfig = new DialogNetConfig(this); // 连接信号 connect(ui_dialognetconfig, &DialogNetConfig::configSaved, this, &MainWindow::onConfigSaved); } ui_dialognetconfig->show(); } void MainWindow::on_btn_algo_config_clicked() { if (!m_presenter) { QMessageBox::warning(this, "错误", "系统未初始化完成!"); return; } auto serverInfos = m_presenter->getServerInfos(); auto beltTearingConfig = m_presenter->getBeltTearingConfig(); if (serverInfos.isEmpty() || !beltTearingConfig) { QMessageBox::warning(this, "错误", "无可用服务器或配置接口!"); return; } if (!m_dialogAlgoarg) { m_dialogAlgoarg = new DialogAlgoarg(beltTearingConfig, serverInfos, this); // 连接参数变化信号 connect(m_dialogAlgoarg, &DialogAlgoarg::parametersChanged, this, &MainWindow::onParametersChanged); // 连接服务器数据请求信号 connect(m_dialogAlgoarg, &DialogAlgoarg::requestServerData, this, &MainWindow::onRequestServerData); } m_dialogAlgoarg->Init(); m_dialogAlgoarg->show(); } void MainWindow::onParametersChanged(const QString& serverName, const QByteArray& paramData) { if (m_presenter) { m_presenter->sendParametersToServer(ByteDataType::WriteConfig, serverName, paramData); } // 添加空指针检查,防止在m_tearingDataTableWidget为nullptr时崩溃 if (m_tearingDataTableWidget) { m_tearingDataTableWidget->clearData(); } } void MainWindow::onRequestServerData(const QString& serverName) { if (!m_presenter) { return; } // 通过Presenter发送请求到服务器 bool success = m_presenter->sendParametersToServer(ByteDataType::ReadConfig, serverName, QByteArray()); if (success) { statusBar()->showMessage("已向服务器 " + serverName + " 发送数据请求"); } else { statusBar()->showMessage("向服务器 " + serverName + " 发送请求失败"); } } void MainWindow::onServerDataReceived(const QString& serverName, const QJsonObject& data) { // 如果算法参数对话框存在,将数据传递给它 if (m_dialogAlgoarg) { m_dialogAlgoarg->onServerDataReceived(serverName, data); } // 更新状态栏 statusBar()->showMessage("从服务器 " + serverName + " 获取参数完成"); } // 设备点击事件处理槽函数 void MainWindow::onDeviceClicked(const QString& deviceAlias) { // 获取设备显示名称 QString deviceName = deviceAlias; if (m_presenter) { deviceName = m_presenter->getServerDisplayName(deviceAlias); if (deviceName.isEmpty()) { deviceName = deviceAlias; } } // 创建自定义的确认对话框 QMessageBox msgBox(this); msgBox.setWindowTitle("重新检测确认"); msgBox.setText(QString("确定要对设备 \"%1\" 进行重新检测吗?").arg(deviceName)); msgBox.setIcon(QMessageBox::Question); // 设置白色字体样式 msgBox.setStyleSheet("QLabel { color: white; } QPushButton { color: white; }"); // 添加中文按钮 QPushButton *yesButton = msgBox.addButton("是", QMessageBox::YesRole); QPushButton *noButton = msgBox.addButton("否", QMessageBox::NoRole); // 显示对话框并获取用户选择 msgBox.exec(); // 如果用户确认重新检测 if (msgBox.clickedButton() == yesButton) { // 调用Presenter的ResetDetect方法进行重新检测,传递设备别名 if (m_presenter) { m_presenter->ResetDetect(deviceAlias); } // 清空检测数据表格 if (m_tearingDataTableWidget) { m_tearingDataTableWidget->clearData(); } // 更新状态栏信息 statusBar()->showMessage(QString("已启动对设备 \"%1\" 的重新检测").arg(deviceName)); } } void MainWindow::onConfigSaved() { // 重新初始化Presenter if (m_presenter) { m_presenter->Init(); } // 如果 DialogAlgoarg 已经创建,更新其服务器列表 if (m_dialogAlgoarg && m_presenter) { auto serverInfos = m_presenter->getServerInfos(); m_dialogAlgoarg->updateServerInfos(serverInfos); } } // IStatusUpdate接口方法实现 void MainWindow::OnStatusUpdate(const QString &statusMessage) { statusBar()->showMessage(statusMessage); LOG_DEBUG("Status update: %s \n", statusMessage.toStdString().c_str()); } // 回调需要显示几个图像 void MainWindow::OnNeedShowImageCount(const QStringList &deviceAliases) { // Handle the case when count is 0 (no images to show) if (deviceAliases.isEmpty()) { // Display a message in the grid view when there are no images to show m_gridView->initImages(0); LOG_DEBUG("No images to display\n"); } else { m_gridView->initImages(deviceAliases.size()); // 为每个tile设置别名 for (int i = 0; i < deviceAliases.size(); ++i) { m_gridView->setTileAlias(i, deviceAliases.at(i)); } // 初始化设备状态列表 if (m_deviceStatusWidget && m_presenter) { QList devices; for (const QString& alias : deviceAliases) { QString displayName = m_presenter->getServerDisplayName(alias); QString ip = m_presenter->getServerIp(alias); devices.append(DeviceInfo(displayName.isEmpty() ? alias : displayName, alias, ip, DeviceStatus::Offline, true)); } m_deviceStatusWidget->setDevices(devices); } } } void MainWindow::OnTearingResult(const BeltTearingResult &result) { // 如果图像有效,显示在网格控件中 if (result.bImageValid && !result.image.isNull()) { // 使用服务器名称作为别名 m_gridView->setImages(result.aliasName, result.image); } else if (result.bResultVaild) { // 直接处理std::vector m_tearingDataTableWidget->addDataBatch(result.serverName, result.result); } } void MainWindow::OnServerConnected(const QString &serverName) { QString message = QString("已连接到服务器: %1").arg(serverName); statusBar()->showMessage(message); LOG_DEBUG("%s \n", message.toStdString().c_str()); } void MainWindow::OnServerDisconnected(const QString &serverName) { QString message = QString("与服务器断开连接: %1").arg(serverName); statusBar()->showMessage(message); LOG_DEBUG("%s \n", message.toStdString().c_str()); } void MainWindow::OnWorkStatusChanged(BeltTearingWorkStatus status) { QString statusStr; switch (status) { case BeltTearingWorkStatus::InitIng: statusStr = "初始化中"; break; case BeltTearingWorkStatus::Ready: statusStr = "准备就绪"; break; case BeltTearingWorkStatus::Working: statusStr = "正在检测"; break; case BeltTearingWorkStatus::Completed: statusStr = "检测完成"; break; case BeltTearingWorkStatus::Error: statusStr = "设备异常"; break; case BeltTearingWorkStatus::Disconnected: statusStr = "连接断开"; break; default: statusStr = "未知状态"; break; } QString message = QString("工作状态: %1").arg(statusStr); statusBar()->showMessage(message); LOG_DEBUG("%s \n", message.toStdString().c_str()); } void MainWindow::OnErrorOccurred(const QString &errorMessage) { statusBar()->showMessage("错误: " + errorMessage); LOG_ERROR("Error occurred: %s \n", errorMessage.toStdString().c_str()); } void MainWindow::OnDeviceStatusChanged(const QString &deviceName, int deviceStatus) { if (m_deviceStatusWidget) { m_deviceStatusWidget->updateDeviceStatus(deviceName, static_cast(deviceStatus)); } } void MainWindow::OnClearTearingData() { if (m_tearingDataTableWidget) { m_tearingDataTableWidget->clearData(); } } void MainWindow::setupVersionDisplay() { // 创建版本信息标签 m_versionLabel = new QLabel(this); // 设置版本信息文本:版本号 + 编译时间 QString versionText = QString("%1_%2_%3%4%5%6%7%8") .arg(BELT_TEARING_APP_VERSION_STRING) .arg(BELT_TEARING_APP_VERSION_BUILD) .arg(YEAR) .arg(MONTH, 2, 10, QChar('0')) .arg(DAY, 2, 10, QChar('0')) .arg(HOUR, 2, 10, QChar('0')) .arg(MINUTE, 2, 10, QChar('0')) .arg(SECOND, 2, 10, QChar('0')); m_versionLabel->setText(versionText); m_versionLabel->setAlignment(Qt::AlignRight | Qt::AlignVCenter); // 设置样式使其看起来更美观 m_versionLabel->setStyleSheet("QLabel { color: rgb(239, 241, 245); font-size: 12px; margin-right: 10px; }"); // 将版本标签添加到状态栏的右侧 statusBar()->addPermanentWidget(m_versionLabel); LOG_INFO("Version display initialized: %s\n", versionText.toStdString().c_str()); }