562 lines
18 KiB
C++
Raw Permalink 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.

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "Version.h"
#include "widgets/ImageGridWidget.h"
#include "widgets/DeviceStatusWidget.h"
#include "widgets/MeasureResultListWidget.h"
#include "dialogcameralevel.h"
#include "dialogalgoarg.h"
#include "dialogcamera.h"
#include <QImage>
#include <QStringList>
#include <QDebug>
#include <QVBoxLayout>
#include <QMessageBox>
#include <QStatusBar>
#include <QLabel>
#include <QDateTime>
#include <QFileDialog>
#include <thread>
#include "VrLog.h"
#include "IVrUtils.h"
#include "StyledMessageBox.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();
// 初始化时隐藏工作状态标签
ui->label_work->setVisible(false);
// 创建组合控件
m_gridView = new ImageGridWidget();
m_deviceStatusWidget = new DeviceStatusWidget();
m_measureResultWidget = new MeasureResultListWidget();
// 将设备状态widget添加到frame_dev中
QVBoxLayout* frameResultImageLayout = new QVBoxLayout(ui->detect_result);
frameResultImageLayout->setContentsMargins(0, 0, 0, 0);
frameResultImageLayout->addWidget(m_gridView);
// 将MeasureResultListWidget添加到detect_data中
QVBoxLayout* frameDataLayout = new QVBoxLayout(ui->detect_data);
frameDataLayout->setContentsMargins(0, 0, 0, 0);
frameDataLayout->addWidget(m_measureResultWidget);
QVBoxLayout* frameDevLayout = new QVBoxLayout(ui->device_status);
frameDevLayout->setContentsMargins(0, 0, 0, 0);
frameDevLayout->addWidget(m_deviceStatusWidget);
// 初始化Presenter
m_presenter = new WheelMeasurePresenter();
// 将设备状态控件与Presenter关联
m_presenter->setStatusUpdate(this);
// 连接配置更新信号
connect(m_presenter, &WheelMeasurePresenter::configUpdated, this, &MainWindow::onConfigSaved);
// 连接设备点击信号到重新检测槽函数
connect(m_deviceStatusWidget, &DeviceStatusWidget::deviceClicked, this, &MainWindow::onDeviceClicked);
// 连接图像右键点击信号到保存数据槽函数
connect(m_gridView, &ImageGridWidget::tileRightClicked, this, &MainWindow::onTileRightClicked);
// 设置版本信息显示
setupVersionDisplay();
// 初始化日志辅助类
m_logHelper = new DetectLogHelper(ui->detect_log, this);
m_presenter->Init();
}
MainWindow::~MainWindow()
{
// 先清除回调,防止后台线程继续调用
if (m_presenter) {
m_presenter->setStatusUpdate(nullptr);
}
if (m_gridView) {
delete m_gridView;
m_gridView = nullptr;
}
if (m_deviceStatusWidget) {
delete m_deviceStatusWidget;
m_deviceStatusWidget = nullptr;
}
if (m_measureResultWidget) {
delete m_measureResultWidget;
m_measureResultWidget = nullptr;
}
if (m_versionLabel) {
delete m_versionLabel;
m_versionLabel = nullptr;
}
if (m_dialogAlgoArg) {
delete m_dialogAlgoArg;
m_dialogAlgoArg = nullptr;
}
if (m_dialogCamera) {
delete m_dialogCamera;
m_dialogCamera = nullptr;
}
if (m_dialogCameraLevel) {
delete m_dialogCameraLevel;
m_dialogCameraLevel = nullptr;
}
if (m_presenter) {
delete m_presenter;
m_presenter = nullptr;
}
delete ui;
LOG_DEBUG("~MainWindow finish \n");
}
void MainWindow::resizeEvent(QResizeEvent* event)
{
QMainWindow::resizeEvent(event);
}
void MainWindow::on_btn_hide_clicked()
{
this->showMinimized();
}
void MainWindow::on_btn_close_clicked()
{
this->close();
}
void MainWindow::on_btn_test_clicked()
{
if (!m_presenter) {
QMessageBox::warning(this, "错误", "系统未初始化完成!");
return;
}
// 设置选中状态
ui->btn_test->setStyleSheet(
"QPushButton { image: url(:/common/resource/config_data_test_s.png); background-color: rgb(38, 40, 47); border: none; }"
);
// 打开文件选择对话框
QString fileName = QFileDialog::getOpenFileName(
this,
tr("选择调试数据文件"),
QString(),
tr("激光数据文件 (*.txt);;所有文件 (*.*)")
);
// 恢复未选中状态
ui->btn_test->setStyleSheet(
"QPushButton { image: url(:/common/resource/config_data_test.png); background-color: rgb(38, 40, 47); border: none; }"
"QPushButton:pressed { image: url(:/common/resource/config_data_test_s.png); }"
);
if (fileName.isEmpty()) {
return;
}
// 清空当前检测数据列表
if (m_measureResultWidget) {
m_measureResultWidget->clearAllResults();
}
// if (m_logHelper) m_logHelper->appendLog(QString("正在加载调试数据: %1").arg(fileName));
// 在后台线程中执行加载和检测
std::thread t([this, fileName]() {
int result = m_presenter->LoadDebugDataAndDetect(fileName.toStdString());
if (result == 0) {
QMetaObject::invokeMethod(this, [this]() {
if (m_logHelper) m_logHelper->appendLog("调试数据加载和检测成功");
}, Qt::QueuedConnection);
} else {
QMetaObject::invokeMethod(this, [this, result]() {
if (m_logHelper) m_logHelper->appendLog(QString("调试数据复检失败: %1").arg(result));
}, Qt::QueuedConnection);
}
});
t.detach();
}
void MainWindow::on_btn_start_clicked()
{
if (!m_presenter) {
QMessageBox::warning(this, "错误", "系统未初始化完成!");
return;
}
// 启动所有相机的检测
m_presenter->StartAllDetection();
if (m_logHelper) m_logHelper->appendLog("已启动所有相机检测");
}
void MainWindow::on_btn_stop_clicked()
{
if (!m_presenter) {
return;
}
// 停止所有相机的检测
m_presenter->StopAllDetection();
if (m_logHelper) m_logHelper->appendLog("已停止所有相机检测");
}
void MainWindow::on_btn_camera_config_clicked()
{
if (!m_presenter) {
QMessageBox::warning(this, "错误", "系统未初始化完成!");
return;
}
if (!m_dialogCamera) {
m_dialogCamera = new DialogCamera(this);
m_dialogCamera->SetPresenter(m_presenter);
connect(m_dialogCamera, &DialogCamera::configSaved, this, &MainWindow::onConfigSaved);
// 连接关闭信号恢复按钮状态
connect(m_dialogCamera, &QDialog::finished, this, [this]() {
ui->btn_camera_config->setStyleSheet(
"QPushButton { image: url(:/common/resource/config_camera.png); background-color: rgb(38, 40, 47); border: none; }"
"QPushButton:pressed { image: url(:/common/resource/config_camera_s.png); }"
);
});
}
// 设置选中状态
ui->btn_camera_config->setStyleSheet(
"QPushButton { image: url(:/common/resource/config_camera_s.png); background-color: rgb(38, 40, 47); border: none; }"
);
m_dialogCamera->show();
}
void MainWindow::on_btn_algo_config_clicked()
{
if (!m_presenter) {
QMessageBox::warning(this, "错误", "系统未初始化完成!");
return;
}
if (!m_dialogAlgoArg) {
m_dialogAlgoArg = new DialogAlgoArg(m_presenter->GetConfig(),
m_presenter->GetConfigResult(), this);
// 连接关闭信号恢复按钮状态
connect(m_dialogAlgoArg, &QDialog::finished, this, [this]() {
ui->btn_algo_config->setStyleSheet(
"QPushButton { image: url(:/common/resource/config_algo.png); background-color: rgb(38, 40, 47); border: none; }"
"QPushButton:pressed { image: url(:/common/resource/config_algo_s.png); }"
);
});
}
// 设置选中状态
ui->btn_algo_config->setStyleSheet(
"QPushButton { image: url(:/common/resource/config_algo_s.png); background-color: rgb(38, 40, 47); border: none; }"
);
m_dialogAlgoArg->Init();
m_dialogAlgoArg->show();
}
void MainWindow::on_btn_camera_level_clicked()
{
if (!m_presenter) {
QMessageBox::warning(this, "错误", "系统未初始化完成!");
return;
}
if (!m_dialogCameraLevel) {
m_dialogCameraLevel = new DialogCameraLevel(this);
// 连接关闭信号恢复按钮状态
connect(m_dialogCameraLevel, &QDialog::finished, this, [this]() {
ui->btn_camera_level->setStyleSheet(
"QPushButton { image: url(:/common/resource/config_camera_level.png); background-color: rgb(38, 40, 47); border: none; }"
"QPushButton:pressed { image: url(:/common/resource/config_camera_level_s.png); }"
);
});
}
// 设置相机列表
m_dialogCameraLevel->setCameraList(m_presenter->GetCameraList(), m_presenter);
// 设置配置对象
m_dialogCameraLevel->setConfig(m_presenter->GetConfig(), m_presenter->GetConfigResult());
// 设置选中状态
ui->btn_camera_level->setStyleSheet(
"QPushButton { image: url(:/common/resource/config_camera_level_s.png); background-color: rgb(38, 40, 47); border: none; }"
);
m_dialogCameraLevel->show();
}
void MainWindow::onDeviceClicked(const QString& deviceName)
{
if (!m_presenter) {
QMessageBox::warning(this, "错误", "系统未初始化完成!");
return;
}
// 查找相机索引
auto cameraList = m_presenter->GetCameraList();
int foundIndex = -1;
for (int i = 0; i < static_cast<int>(cameraList.size()); ++i) {
if (QString::fromStdString(cameraList[i].first) == deviceName) {
foundIndex = i;
break;
}
}
if (foundIndex < 0) {
if (m_logHelper) m_logHelper->appendLog(QString("未找到相机: %1").arg(deviceName));
return;
}
// 清空指定设备的检测结果
if (m_measureResultWidget) {
m_measureResultWidget->clearDeviceResult(deviceName);
}
// 直接开始检测
m_presenter->ResetDetect(foundIndex);
if (m_logHelper) m_logHelper->appendLog(QString("已启动相机 \"%1\" 的检测").arg(deviceName));
}
void MainWindow::onConfigSaved()
{
// 配置已在 WheelMeasurePresenter::OnConfigChanged 中更新
// 算法参数和调平参数的修改不需要重新初始化相机
LOG_INFO("Config saved, configuration updated in memory\n");
}
void MainWindow::onTileRightClicked(int index, const QString& alias)
{
if (!m_presenter) {
StyledMessageBox::warning(this, "错误", "系统未初始化完成!");
return;
}
// 获取当前检测的相机索引0-based
int currentDetectIndex = m_presenter->GetDetectIndex() - 1; // 转换为0-based
// 检查点击的是否是当前检测的相机
if (index != currentDetectIndex) {
if (m_logHelper) m_logHelper->appendLog(QString("设备 \"%1\" 无缓存数据").arg(alias));
StyledMessageBox::information(this, "提示",
QString("设备 \"%1\" 无缓存数据\n\n当前缓存的是设备 %2 的数据")
.arg(alias)
.arg(currentDetectIndex >= 0 ? m_gridView->getAlias(currentDetectIndex) : ""));
return;
}
// 检查是否有缓存数据
int cacheSize = m_presenter->GetDetectionDataCacheSize();
if (cacheSize <= 0) {
if (m_logHelper) m_logHelper->appendLog(QString("设备 \"%1\" 无缓存数据").arg(alias));
StyledMessageBox::information(this, "提示", QString("设备 \"%1\" 无缓存数据").arg(alias));
return;
}
// 弹出文件保存对话框
QString defaultFileName = QString("%1_%2.txt")
.arg(alias)
.arg(QDateTime::currentDateTime().toString("yyyyMMdd_HHmmss"));
QString filePath = QFileDialog::getSaveFileName(
this,
tr("保存检测数据"),
defaultFileName,
tr("文本文件 (*.txt);;所有文件 (*.*)")
);
if (filePath.isEmpty()) {
return;
}
// 调用Presenter保存数据
int result = m_presenter->SaveDetectionDataToFile(filePath.toStdString());
if (result == 0) {
if (m_logHelper) m_logHelper->appendLog(QString("检测数据已保存: %1").arg(filePath));
StyledMessageBox::information(this, "成功", QString("检测数据已保存到:\n%1").arg(filePath));
} else {
if (m_logHelper) m_logHelper->appendLog(QString("保存检测数据失败: %1").arg(result));
StyledMessageBox::warning(this, "失败", QString("保存检测数据失败,错误码: %1").arg(result));
}
}
// IWheelMeasureStatus接口方法实现
void MainWindow::OnStatusUpdate(const QString &statusMessage)
{
if (m_logHelper) m_logHelper->appendLog(statusMessage);
LOG_DEBUG("Status update: %s \n", statusMessage.toStdString().c_str());
}
void MainWindow::OnNeedShowImageCount(const QStringList &cameraNames)
{
if (cameraNames.isEmpty()) {
m_gridView->initImages(0);
LOG_DEBUG("No images to display\n");
} else {
m_gridView->initImages(cameraNames.size());
// 为每个tile设置别名
for (int i = 0; i < cameraNames.size(); ++i) {
m_gridView->setTileAlias(i, cameraNames.at(i));
}
// 初始化设备状态列表
if (m_deviceStatusWidget && m_presenter) {
QList<WheelDeviceDisplayInfo> devices;
for (const QString& name : cameraNames) {
devices.append(WheelDeviceDisplayInfo(name, name, "", DeviceStatus::Offline, true));
}
m_deviceStatusWidget->setDevices(devices);
}
// 初始化检测结果列表
if (m_measureResultWidget) {
m_measureResultWidget->setDeviceList(cameraNames);
}
}
}
void MainWindow::OnMeasureResult(const WheelMeasureResult &result)
{
// 直接调用处理方法Presenter在后台线程需要使用invokeMethod确保线程安全
QMetaObject::invokeMethod(this, [this, result]() {
// 如果图像有效,显示在网格控件中
if (result.bImageValid && !result.image.isNull()) {
m_gridView->setImages(result.aliasName, result.image);
}
// 更新设备检测结果列表
if (m_measureResultWidget) {
// 获取第一个结果数据(如果有的话)
WheelMeasureData data;
if (!result.result.empty()) {
data = result.result[0];
}
m_measureResultWidget->updateDeviceResult(result.cameraName, data, result.bResultValid);
}
}, Qt::QueuedConnection);
}
void MainWindow::OnCameraConnected(const QString &cameraName)
{
QString message = QString("相机已连接: %1").arg(cameraName);
if (m_logHelper) m_logHelper->appendLog(message);
LOG_DEBUG("%s \n", message.toStdString().c_str());
}
void MainWindow::OnCameraDisconnected(const QString &cameraName)
{
QString message = QString("相机断开连接: %1").arg(cameraName);
if (m_logHelper) m_logHelper->appendLog(message);
LOG_DEBUG("%s \n", message.toStdString().c_str());
}
void MainWindow::OnWorkStatusChangedImpl(WorkStatus status)
{
QString statusStr;
switch (status) {
case WorkStatus::InitIng:
statusStr = "初始化中";
break;
case WorkStatus::Ready:
statusStr = "准备就绪";
break;
case WorkStatus::Working:
statusStr = "正在检测";
break;
case WorkStatus::Detecting:
statusStr = "正在检测";
break;
case WorkStatus::Completed:
statusStr = "检测完成";
break;
case WorkStatus::Error:
statusStr = "设备异常";
break;
default:
statusStr = "未知状态";
break;
}
QString message = QString("工作状态: %1").arg(statusStr);
if (m_logHelper) m_logHelper->appendLog(message);
LOG_DEBUG("%s \n", message.toStdString().c_str());
}
void MainWindow::OnErrorOccurred(const QString &errorMessage)
{
if (m_logHelper) m_logHelper->appendLog("错误: " + 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>(deviceStatus));
}
}
void MainWindow::OnClearMeasureData()
{
if (m_measureResultWidget) {
m_measureResultWidget->clearAllResults();
}
}
void MainWindow::setupVersionDisplay()
{
m_versionLabel = new QLabel(this);
// 使用与 Workpiece 一致的版本格式
QString versionText = QString("%1_%2%3%4%5%6%7")
.arg(GetWheelMeasureFullVersion())
.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: 24px; margin-right: 10px; }");
statusBar()->addPermanentWidget(m_versionLabel);
LOG_INFO("Version display initialized: %s\n", versionText.toStdString().c_str());
}