719 lines
22 KiB
C++
719 lines
22 KiB
C++
#include "mainwindow.h"
|
|
#include "ui_mainwindow.h"
|
|
|
|
#include <QApplication>
|
|
#include <QBrush>
|
|
#include <QDateTime>
|
|
#include <QDir>
|
|
#include <QFileDialog>
|
|
#include <QGraphicsScene>
|
|
#include <QGraphicsView>
|
|
#include <QIcon>
|
|
#include <QListWidgetItem>
|
|
#include <QMetaObject>
|
|
#include <QPixmap>
|
|
#include <QPushButton>
|
|
#include <QStandardPaths>
|
|
#include <QThread>
|
|
#include <QVBoxLayout>
|
|
|
|
#include <algorithm>
|
|
#include <thread>
|
|
|
|
#include "IVrUtils.h"
|
|
#include "PathManager.h"
|
|
#include "SingleTargetResultWidget.h"
|
|
#include "StyledMessageBox.h"
|
|
#include "Version.h"
|
|
#include "VrDateUtils.h"
|
|
#include "VrLog.h"
|
|
|
|
namespace {
|
|
|
|
QString GuideStateName(ParkingGuideState state)
|
|
{
|
|
switch (state) {
|
|
case ParkingGuideState::DockingStarted:
|
|
return QStringLiteral("泊位引导启动");
|
|
case ParkingGuideState::Capturing:
|
|
return QStringLiteral("捕获");
|
|
case ParkingGuideState::Tracking:
|
|
return QStringLiteral("跟踪");
|
|
case ParkingGuideState::ApproachRate:
|
|
return QStringLiteral("接近率");
|
|
case ParkingGuideState::CenterLineAligned:
|
|
return QStringLiteral("对准中心线");
|
|
case ParkingGuideState::Slow:
|
|
return QStringLiteral("慢速");
|
|
case ParkingGuideState::AzimuthGuidance:
|
|
return QStringLiteral("方位引导");
|
|
case ParkingGuideState::StopPositionReached:
|
|
return QStringLiteral("到达停止位置");
|
|
case ParkingGuideState::DockingCompleted:
|
|
return QStringLiteral("泊位引导完成");
|
|
case ParkingGuideState::Overshot:
|
|
return QStringLiteral("越位");
|
|
case ParkingGuideState::StoppedShort:
|
|
return QStringLiteral("提前停止");
|
|
case ParkingGuideState::Waiting:
|
|
return QStringLiteral("等待");
|
|
case ParkingGuideState::SlowBadWeather:
|
|
return QStringLiteral("异常慢速-恶劣天气");
|
|
case ParkingGuideState::SlowAircraftLost:
|
|
return QStringLiteral("异常慢速-飞机丢失");
|
|
case ParkingGuideState::AircraftVerificationFailed:
|
|
return QStringLiteral("飞机验证失败");
|
|
case ParkingGuideState::GateBlocked:
|
|
return QStringLiteral("机位受阻");
|
|
case ParkingGuideState::ViewBlocked:
|
|
return QStringLiteral("视野受阻");
|
|
case ParkingGuideState::SbuStop:
|
|
return QStringLiteral("SBU停止");
|
|
case ParkingGuideState::TooFast:
|
|
return QStringLiteral("速度过快");
|
|
case ParkingGuideState::EmergencyStop:
|
|
return QStringLiteral("紧急停止");
|
|
case ParkingGuideState::ChocksOn:
|
|
return QStringLiteral("挡轮挡");
|
|
case ParkingGuideState::SystemError:
|
|
return QStringLiteral("系统错误");
|
|
case ParkingGuideState::SystemFailure:
|
|
return QStringLiteral("系统故障");
|
|
case ParkingGuideState::PowerFailure:
|
|
return QStringLiteral("电源故障");
|
|
case ParkingGuideState::Unknown:
|
|
default:
|
|
return QStringLiteral("未知");
|
|
}
|
|
}
|
|
|
|
QString FormatGuideState(const ParkingSpaceGuideInfo& info)
|
|
{
|
|
const ParkingGuideState state = ParkingGuideStateFromCode(info.guideStateCode);
|
|
const int displayCode = state == ParkingGuideState::Unknown
|
|
? info.guideStateCode
|
|
: static_cast<int>(state);
|
|
QString text = QStringLiteral("%1 %2").arg(displayCode).arg(GuideStateName(state));
|
|
|
|
const QString guideText = info.guideText.trimmed();
|
|
if (!guideText.isEmpty()) {
|
|
text += QStringLiteral(" / %1").arg(guideText);
|
|
}
|
|
return text;
|
|
}
|
|
|
|
QString FormatNumber(double value, const QString& unit, int precision = 2)
|
|
{
|
|
return QStringLiteral("%1%2").arg(value, 0, 'f', precision).arg(unit);
|
|
}
|
|
|
|
} // namespace
|
|
|
|
MainWindow::MainWindow(QWidget* parent)
|
|
: QMainWindow(parent)
|
|
, ui(new Ui::MainWindow)
|
|
{
|
|
ui->setupUi(this);
|
|
setWindowTitle(QStringLiteral("停车引导"));
|
|
if (ui->label) {
|
|
ui->label->setText(QStringLiteral("停车引导"));
|
|
}
|
|
|
|
#ifdef _WIN32
|
|
setWindowIcon(QIcon(":/common/resource/logo.ico"));
|
|
#else
|
|
setWindowIcon(QIcon(":/common/resource/logo.png"));
|
|
#endif
|
|
|
|
QFont statusFont = statusBar()->font();
|
|
statusFont.setPointSize(12);
|
|
statusBar()->setFont(statusFont);
|
|
statusBar()->setStyleSheet("QStatusBar { color: rgb(239, 241, 245); padding: 20px; }");
|
|
|
|
const QString versionWithBuildTime = QString("%1_%2%3%4%5%6%7")
|
|
.arg(GetParkingSpaceGuideFullVersion())
|
|
.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 = new QLabel(versionWithBuildTime);
|
|
m_versionLabel->setStyleSheet("color: rgb(239, 241, 245); font-size: 20px; margin-right: 16px;");
|
|
m_versionLabel->setCursor(Qt::PointingHandCursor);
|
|
m_versionLabel->installEventFilter(this);
|
|
statusBar()->addPermanentWidget(m_versionLabel);
|
|
|
|
setWindowFlags(Qt::FramelessWindowHint);
|
|
showMaximized();
|
|
|
|
ui->label_work->setVisible(false);
|
|
ui->detect_image->setScene(new QGraphicsScene(this));
|
|
|
|
m_logHelper = new DetectLogHelper(ui->detect_log, this);
|
|
|
|
qRegisterMetaType<DetectionResult>("DetectionResult");
|
|
qRegisterMetaType<WorkStatus>("WorkStatus");
|
|
qRegisterMetaType<ParkingSpaceGuidePosition>("ParkingSpaceGuidePosition");
|
|
|
|
connect(this, &MainWindow::workStatusUpdateRequested,
|
|
this, &MainWindow::updateWorkStatusLabel,
|
|
Qt::QueuedConnection);
|
|
connect(this, &MainWindow::detectionResultUpdateRequested,
|
|
this, &MainWindow::updateDetectionResultDisplay,
|
|
Qt::QueuedConnection);
|
|
|
|
setupContextMenu();
|
|
updateStatusLog(tr("设备初始化开始"));
|
|
Init();
|
|
}
|
|
|
|
MainWindow::~MainWindow()
|
|
{
|
|
if (m_initThread.joinable()) {
|
|
m_initThread.join();
|
|
}
|
|
if (m_testThread.joinable()) {
|
|
m_testThread.join();
|
|
}
|
|
|
|
if (m_presenter) {
|
|
m_presenter->DeinitApp();
|
|
m_presenter->SetStatusCallback(static_cast<IYParkingSpaceGuideStatus*>(nullptr));
|
|
delete m_presenter;
|
|
m_presenter = nullptr;
|
|
}
|
|
|
|
delete ui;
|
|
}
|
|
|
|
bool MainWindow::eventFilter(QObject* obj, QEvent* event)
|
|
{
|
|
if (obj == m_versionLabel && event->type() == QEvent::MouseButtonPress) {
|
|
const QString algoVersion = m_presenter ? m_presenter->GetAlgoVersion() : QString();
|
|
AboutDialog dlg(PARKINGSPACEGUIDE_APP_NAME, m_versionLabel->text(), algoVersion, this);
|
|
dlg.exec();
|
|
return true;
|
|
}
|
|
|
|
return QMainWindow::eventFilter(obj, event);
|
|
}
|
|
|
|
void MainWindow::updateStatusLog(const QString& message)
|
|
{
|
|
if (QThread::currentThread() != thread()) {
|
|
QMetaObject::invokeMethod(this, [this, message]() {
|
|
updateStatusLog(message);
|
|
}, Qt::QueuedConnection);
|
|
return;
|
|
}
|
|
|
|
if (m_logHelper) {
|
|
m_logHelper->appendLog(message);
|
|
}
|
|
}
|
|
|
|
void MainWindow::clearDetectionLog()
|
|
{
|
|
if (m_logHelper) {
|
|
m_logHelper->clearLog();
|
|
}
|
|
}
|
|
|
|
void MainWindow::Init()
|
|
{
|
|
m_presenter = new ParkingSpaceGuidePresenter();
|
|
m_presenter->SetStatusCallback<IYParkingSpaceGuideStatus>(this);
|
|
|
|
m_deviceStatusWidget = new DeviceStatusWidget(ui->frame_dev);
|
|
m_deviceStatusWidget->setCameraCount(2, true);
|
|
m_deviceStatusWidget->setCamera1Name(tr("平面相机"));
|
|
m_deviceStatusWidget->setCamera2Name(tr("雷达"));
|
|
m_deviceStatusWidget->setRobotVisible(false);
|
|
connect(m_deviceStatusWidget, SIGNAL(cameraClicked(int)), this, SLOT(onCameraClicked(int)));
|
|
|
|
auto* frameDevLayout = new QVBoxLayout(ui->frame_dev);
|
|
frameDevLayout->setContentsMargins(0, 0, 0, 0);
|
|
frameDevLayout->addWidget(m_deviceStatusWidget);
|
|
|
|
SingleTargetResultWidget::setupListWidget(ui->detect_result_list, QSize(520, 420));
|
|
|
|
setButtonsEnabled(false);
|
|
|
|
m_initThread = std::thread([this]() {
|
|
updateStatusLog(tr("系统初始化中..."));
|
|
|
|
const int result = m_presenter->Init();
|
|
if (result != 0) {
|
|
updateStatusLog(tr("初始化失败,错误码:%1").arg(result));
|
|
} else {
|
|
updateStatusLog(tr("初始化完成"));
|
|
}
|
|
});
|
|
}
|
|
|
|
void MainWindow::displayImage(const QImage& image)
|
|
{
|
|
if (image.isNull()) {
|
|
updateStatusLog(tr("无预览图像"));
|
|
return;
|
|
}
|
|
|
|
QGraphicsScene* scene = ui->detect_image->scene();
|
|
scene->clear();
|
|
scene->addPixmap(QPixmap::fromImage(image));
|
|
ui->detect_image->fitInView(scene->sceneRect(), Qt::KeepAspectRatio);
|
|
}
|
|
|
|
void MainWindow::addDetectionResult(const DetectionResult& result)
|
|
{
|
|
ui->detect_result_list->clear();
|
|
|
|
const int itemWidth = (std::max)(360, ui->detect_result_list->viewport()->width() - 8);
|
|
const int itemHeight = 420;
|
|
SingleTargetResultWidget::setupListWidget(ui->detect_result_list, QSize(itemWidth, itemHeight));
|
|
|
|
auto* resultWidget = new SingleTargetResultWidget();
|
|
resultWidget->setAutoFillBackground(true);
|
|
|
|
auto* item = new QListWidgetItem();
|
|
item->setBackground(QBrush(Qt::transparent));
|
|
item->setSizeHint(QSize(itemWidth, itemHeight));
|
|
item->setFlags(item->flags() & ~Qt::ItemIsDragEnabled & ~Qt::ItemIsDropEnabled);
|
|
ui->detect_result_list->addItem(item);
|
|
ui->detect_result_list->setItemWidget(item, resultWidget);
|
|
|
|
if (result.parkingSpaceInfoList.empty()) {
|
|
resultWidget->setTitle(tr("当前状态"));
|
|
resultWidget->setStatus(GuideStateName(ParkingGuideState::Unknown), false);
|
|
resultWidget->setEmptyText(tr("暂无停机状态结果"));
|
|
return;
|
|
}
|
|
|
|
const ParkingSpaceGuideInfo& info = result.parkingSpaceInfoList.front();
|
|
const ParkingGuideState guideState = ParkingGuideStateFromCode(info.guideStateCode);
|
|
resultWidget->setTitle(tr("当前状态"));
|
|
resultWidget->setStatus(GuideStateName(guideState), false);
|
|
resultWidget->setFields({
|
|
{tr("目标编号"), info.targetId},
|
|
{tr("停机位"), info.parkId},
|
|
{tr("机型"), info.modelType},
|
|
{tr("引导状态"), FormatGuideState(info)},
|
|
{tr("到停止线"), FormatNumber(info.distance, tr("毫米"))},
|
|
{tr("横向偏移"), FormatNumber(info.lateralOffset, tr("毫米"))},
|
|
{tr("偏转角"), FormatNumber(info.angle, tr("度"))},
|
|
{tr("速度"), FormatNumber(info.aircraftSpeed, tr("米/秒"), 2)}
|
|
});
|
|
}
|
|
|
|
void MainWindow::OnStatusUpdate(const std::string& statusMessage)
|
|
{
|
|
updateStatusLog(QString::fromStdString(statusMessage));
|
|
}
|
|
|
|
void MainWindow::OnDetectionResult(const DetectionResult& result)
|
|
{
|
|
emit detectionResultUpdateRequested(result);
|
|
}
|
|
|
|
void MainWindow::OnCamera1StatusChanged(bool isConnected)
|
|
{
|
|
if (QThread::currentThread() != thread()) {
|
|
QMetaObject::invokeMethod(this, [this, isConnected]() {
|
|
OnCamera1StatusChanged(isConnected);
|
|
}, Qt::QueuedConnection);
|
|
return;
|
|
}
|
|
|
|
if (m_deviceStatusWidget) {
|
|
m_deviceStatusWidget->updateCamera1Status(isConnected);
|
|
}
|
|
}
|
|
|
|
void MainWindow::OnCamera2StatusChanged(bool isConnected)
|
|
{
|
|
if (QThread::currentThread() != thread()) {
|
|
QMetaObject::invokeMethod(this, [this, isConnected]() {
|
|
OnCamera2StatusChanged(isConnected);
|
|
}, Qt::QueuedConnection);
|
|
return;
|
|
}
|
|
|
|
if (m_deviceStatusWidget) {
|
|
m_deviceStatusWidget->updateCamera2Status(isConnected);
|
|
}
|
|
}
|
|
|
|
void MainWindow::OnRobotConnectionChanged(bool isConnected)
|
|
{
|
|
Q_UNUSED(isConnected);
|
|
}
|
|
|
|
void MainWindow::OnSerialConnectionChanged(bool isConnected)
|
|
{
|
|
if (QThread::currentThread() != thread()) {
|
|
QMetaObject::invokeMethod(this, [this, isConnected]() {
|
|
OnSerialConnectionChanged(isConnected);
|
|
}, Qt::QueuedConnection);
|
|
return;
|
|
}
|
|
|
|
if (m_deviceStatusWidget) {
|
|
m_deviceStatusWidget->updateSerialStatus(isConnected);
|
|
}
|
|
}
|
|
|
|
void MainWindow::OnCameraCountChanged(int cameraCount)
|
|
{
|
|
Q_UNUSED(cameraCount);
|
|
if (QThread::currentThread() != thread()) {
|
|
QMetaObject::invokeMethod(this, [this]() {
|
|
OnCameraCountChanged(2);
|
|
}, Qt::QueuedConnection);
|
|
return;
|
|
}
|
|
|
|
if (m_deviceStatusWidget) {
|
|
m_deviceStatusWidget->setCameraCount(2, true);
|
|
m_deviceStatusWidget->setCamera1Name(tr("平面相机"));
|
|
m_deviceStatusWidget->setCamera2Name(tr("雷达"));
|
|
}
|
|
}
|
|
|
|
void MainWindow::OnWorkStatusChanged(WorkStatus status)
|
|
{
|
|
emit workStatusUpdateRequested(status);
|
|
}
|
|
|
|
void MainWindow::updateWorkStatusLabel(WorkStatus status)
|
|
{
|
|
if (status == WorkStatus::Working || status == WorkStatus::Detecting) {
|
|
clearDetectionLog();
|
|
}
|
|
|
|
if (!ui->label_work) {
|
|
return;
|
|
}
|
|
|
|
const QString statusText = QString::fromStdString(WorkStatusToString(status));
|
|
ui->label_work->setText(statusText);
|
|
updateStatusLog(tr("工作状态:%1").arg(statusText));
|
|
|
|
switch (status) {
|
|
case WorkStatus::Ready:
|
|
ui->label_work->setStyleSheet("color: green;");
|
|
setButtonsEnabled(true);
|
|
if (ui->btn_stop) ui->btn_stop->setEnabled(false);
|
|
break;
|
|
case WorkStatus::InitIng:
|
|
ui->label_work->setStyleSheet("color: blue;");
|
|
setButtonsEnabled(false);
|
|
break;
|
|
case WorkStatus::Working:
|
|
ui->label_work->setStyleSheet("color: blue;");
|
|
setButtonsEnabled(false);
|
|
if (ui->btn_stop) ui->btn_stop->setEnabled(true);
|
|
break;
|
|
case WorkStatus::Detecting:
|
|
ui->label_work->setStyleSheet("color: blue;");
|
|
setButtonsEnabled(false);
|
|
break;
|
|
case WorkStatus::Completed:
|
|
ui->label_work->setStyleSheet("color: green; font-weight: bold;");
|
|
setButtonsEnabled(true);
|
|
if (ui->btn_stop) ui->btn_stop->setEnabled(false);
|
|
break;
|
|
case WorkStatus::Error:
|
|
ui->label_work->setStyleSheet("color: red; font-weight: bold;");
|
|
setButtonsEnabled(true);
|
|
if (ui->btn_stop) ui->btn_stop->setEnabled(false);
|
|
break;
|
|
default:
|
|
ui->label_work->setStyleSheet("");
|
|
setButtonsEnabled(false);
|
|
break;
|
|
}
|
|
}
|
|
|
|
void MainWindow::updateDetectionResultDisplay(const DetectionResult& result)
|
|
{
|
|
if (!result.image.isNull()) {
|
|
displayImage(result.image);
|
|
}
|
|
addDetectionResult(result);
|
|
}
|
|
|
|
void MainWindow::on_btn_start_clicked()
|
|
{
|
|
if (!m_presenter) {
|
|
updateStatusLog(tr("系统未初始化"));
|
|
return;
|
|
}
|
|
|
|
clearDetectionLog();
|
|
updateStatusLog(tr("开始停车引导检测"));
|
|
if (!m_presenter->StartDetection(-1)) {
|
|
updateStatusLog(tr("启动检测失败"));
|
|
}
|
|
}
|
|
|
|
void MainWindow::on_btn_stop_clicked()
|
|
{
|
|
if (m_presenter) {
|
|
m_presenter->StopDetection();
|
|
}
|
|
}
|
|
|
|
void MainWindow::showParameterDialog(DialogAlgoArg::ConfigPage page, QPushButton* button)
|
|
{
|
|
if (m_selectedButton && m_selectedButton != button) {
|
|
updateStatusLog(tr("请先关闭当前参数窗口"));
|
|
return;
|
|
}
|
|
|
|
if (!m_presenter) {
|
|
updateStatusLog(tr("系统未初始化"));
|
|
return;
|
|
}
|
|
|
|
setButtonSelectedState(button, true);
|
|
|
|
if (!ui_dialogAlgoArg) {
|
|
ui_dialogAlgoArg = new DialogAlgoArg(this);
|
|
connect(ui_dialogAlgoArg, &QDialog::finished, this, [this]() {
|
|
if (m_selectedButton) {
|
|
setButtonSelectedState(m_selectedButton, false);
|
|
}
|
|
});
|
|
}
|
|
|
|
ui_dialogAlgoArg->SetPresenter(m_presenter);
|
|
ui_dialogAlgoArg->SetCurrentPage(page);
|
|
ui_dialogAlgoArg->show();
|
|
ui_dialogAlgoArg->raise();
|
|
ui_dialogAlgoArg->activateWindow();
|
|
}
|
|
|
|
void MainWindow::on_btn_camera_clicked()
|
|
{
|
|
updateStatusLog(tr("打开相机参数设置"));
|
|
showParameterDialog(DialogAlgoArg::ConfigPage::Camera, ui->btn_camera);
|
|
}
|
|
|
|
void MainWindow::on_btn_algo_config_clicked()
|
|
{
|
|
updateStatusLog(tr("打开检测参数设置"));
|
|
showParameterDialog(DialogAlgoArg::ConfigPage::Detection, ui->btn_algo_config);
|
|
}
|
|
|
|
void MainWindow::on_btn_camera_levelling_clicked()
|
|
{
|
|
updateStatusLog(tr("打开相机调平标定"));
|
|
showParameterDialog(DialogAlgoArg::ConfigPage::Calibration, ui->btn_camera_levelling);
|
|
}
|
|
|
|
void MainWindow::on_btn_hide_clicked()
|
|
{
|
|
showMinimized();
|
|
}
|
|
|
|
void MainWindow::on_btn_close_clicked()
|
|
{
|
|
close();
|
|
}
|
|
|
|
void MainWindow::on_btn_test_clicked()
|
|
{
|
|
if (!m_presenter) {
|
|
StyledMessageBox::warning(this, tr("错误"), tr("系统未初始化"));
|
|
return;
|
|
}
|
|
|
|
if (m_selectedButton && m_selectedButton != ui->btn_test) {
|
|
updateStatusLog(tr("请先关闭当前参数窗口"));
|
|
return;
|
|
}
|
|
|
|
setButtonSelectedState(ui->btn_test, true);
|
|
setButtonsEnabled(false);
|
|
clearDetectionLog();
|
|
updateStatusLog(tr("运行预留算法接口测试"));
|
|
|
|
if (m_testThread.joinable()) {
|
|
m_testThread.join();
|
|
}
|
|
m_testThread = std::thread([this]() {
|
|
const bool ok = m_presenter->TriggerDetection(-1);
|
|
updateStatusLog(ok ? tr("测试检测完成") : tr("测试检测失败"));
|
|
QMetaObject::invokeMethod(this, [this]() {
|
|
setButtonSelectedState(ui->btn_test, false);
|
|
const bool running = m_presenter && m_presenter->IsDetectionRunning();
|
|
setButtonsEnabled(!running);
|
|
if (ui->btn_stop) ui->btn_stop->setEnabled(running);
|
|
}, Qt::QueuedConnection);
|
|
});
|
|
}
|
|
|
|
void MainWindow::setButtonsEnabled(bool enabled)
|
|
{
|
|
if (ui->btn_start) ui->btn_start->setEnabled(enabled);
|
|
if (ui->btn_stop) ui->btn_stop->setEnabled(enabled);
|
|
if (ui->btn_camera) ui->btn_camera->setEnabled(enabled);
|
|
if (ui->btn_algo_config) ui->btn_algo_config->setEnabled(enabled);
|
|
if (ui->btn_camera_levelling) ui->btn_camera_levelling->setEnabled(enabled);
|
|
if (ui->btn_test) ui->btn_test->setEnabled(enabled);
|
|
}
|
|
|
|
void MainWindow::setButtonImage(QPushButton* button, const QString& imagePath)
|
|
{
|
|
if (button) {
|
|
button->setStyleSheet(QString("image: url(%1);background-color: rgb(38, 40, 47);border: none;")
|
|
.arg(imagePath));
|
|
}
|
|
}
|
|
|
|
void MainWindow::setButtonSelectedState(QPushButton* button, bool selected)
|
|
{
|
|
if (!button) {
|
|
return;
|
|
}
|
|
|
|
QString normalImage;
|
|
QString selectedImage;
|
|
if (button == ui->btn_camera) {
|
|
normalImage = ":/common/resource/config_camera.png";
|
|
selectedImage = ":/common/resource/config_camera_s.png";
|
|
} else if (button == ui->btn_algo_config) {
|
|
normalImage = ":/common/resource/config_algo.png";
|
|
selectedImage = ":/common/resource/config_algo_s.png";
|
|
} else if (button == ui->btn_camera_levelling) {
|
|
normalImage = ":/common/resource/config_camera_level.png";
|
|
selectedImage = ":/common/resource/config_camera_level_s.png";
|
|
} else if (button == ui->btn_test) {
|
|
normalImage = ":/common/resource/config_data_test.png";
|
|
selectedImage = ":/common/resource/config_data_test_s.png";
|
|
}
|
|
|
|
if (selected) {
|
|
setButtonImage(button, selectedImage);
|
|
m_selectedButton = button;
|
|
setOtherButtonsEnabled(button, false);
|
|
} else {
|
|
setButtonImage(button, normalImage);
|
|
if (m_selectedButton == button) {
|
|
m_selectedButton = nullptr;
|
|
setOtherButtonsEnabled(nullptr, true);
|
|
}
|
|
}
|
|
}
|
|
|
|
void MainWindow::restoreAllButtonStates()
|
|
{
|
|
setButtonSelectedState(ui->btn_camera, false);
|
|
setButtonSelectedState(ui->btn_algo_config, false);
|
|
setButtonSelectedState(ui->btn_camera_levelling, false);
|
|
setButtonSelectedState(ui->btn_test, false);
|
|
}
|
|
|
|
void MainWindow::setOtherButtonsEnabled(QPushButton* exceptButton, bool enabled)
|
|
{
|
|
const QList<QPushButton*> configButtons = {
|
|
ui->btn_camera,
|
|
ui->btn_algo_config,
|
|
ui->btn_camera_levelling,
|
|
ui->btn_test
|
|
};
|
|
|
|
for (QPushButton* button : configButtons) {
|
|
if (button && button != exceptButton) {
|
|
button->setEnabled(enabled);
|
|
}
|
|
}
|
|
}
|
|
|
|
void MainWindow::onCameraClicked(int cameraIndex)
|
|
{
|
|
if (m_presenter) {
|
|
m_presenter->SetDefaultCameraIndex(cameraIndex);
|
|
}
|
|
}
|
|
|
|
void MainWindow::setupContextMenu()
|
|
{
|
|
m_contextMenu = new QMenu(this);
|
|
m_saveDataAction = new QAction(tr("保存检测数据"), this);
|
|
m_contextMenu->addAction(m_saveDataAction);
|
|
|
|
connect(m_saveDataAction, &QAction::triggered, this, &MainWindow::onSaveDetectionData);
|
|
|
|
ui->detect_image->setContextMenuPolicy(Qt::CustomContextMenu);
|
|
connect(ui->detect_image, &QGraphicsView::customContextMenuRequested,
|
|
this, &MainWindow::showContextMenu);
|
|
}
|
|
|
|
void MainWindow::showContextMenu(const QPoint& pos)
|
|
{
|
|
if (!m_presenter) {
|
|
updateStatusLog(tr("系统未初始化,无法保存数据"));
|
|
return;
|
|
}
|
|
|
|
if (m_presenter->GetDetectionDataCacheSize() == 0) {
|
|
updateStatusLog(tr("没有可保存的检测数据"));
|
|
return;
|
|
}
|
|
|
|
m_contextMenu->exec(ui->detect_image->mapToGlobal(pos));
|
|
}
|
|
|
|
void MainWindow::onSaveDetectionData()
|
|
{
|
|
if (!m_presenter) {
|
|
updateStatusLog(tr("系统未初始化,无法保存数据"));
|
|
return;
|
|
}
|
|
|
|
const QString dirPath = QFileDialog::getExistingDirectory(
|
|
this,
|
|
tr("选择保存目录"),
|
|
QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation),
|
|
QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks);
|
|
|
|
if (dirPath.isEmpty()) {
|
|
updateStatusLog(tr("保存已取消"));
|
|
return;
|
|
}
|
|
|
|
const std::string timeStamp = CVrDateUtils::GetNowTime();
|
|
const QString fileName = QString("停车引导_%1_%2.txt")
|
|
.arg(m_presenter->GetDetectIndex())
|
|
.arg(QString::fromStdString(timeStamp));
|
|
const QString fullPath = QDir(dirPath).filePath(fileName);
|
|
|
|
if (saveDetectionDataToFile(fullPath)) {
|
|
updateStatusLog(tr("检测数据已保存:%1").arg(fileName));
|
|
} else {
|
|
updateStatusLog(tr("保存检测数据失败"));
|
|
}
|
|
}
|
|
|
|
bool MainWindow::saveDetectionDataToFile(const QString& filePath)
|
|
{
|
|
if (!m_presenter) {
|
|
return false;
|
|
}
|
|
|
|
try {
|
|
const int result = m_presenter->SaveDetectionDataToFile(filePath.toStdString());
|
|
if (result != 0) {
|
|
updateStatusLog(tr("保存数据失败,错误码:%1").arg(result));
|
|
return false;
|
|
}
|
|
return true;
|
|
} catch (const std::exception&) {
|
|
updateStatusLog(tr("保存数据异常"));
|
|
return false;
|
|
}
|
|
}
|