weld_measure/main_window.cpp

173 lines
6.5 KiB
C++

#include "main_window.h"
#include <QFileDialog>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QGroupBox>
#include <QFormLayout>
#include <QStyle>
#include <QMessageBox>
#include <QPainter>
#include <QtMath>
#include <QTabWidget>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
setWindowTitle("Sistema de Inspección y Medición de Soldaduras (Línea Única)");
resize(1200, 800);
createUI();
}
void MainWindow::createUI()
{
QWidget *centralWidget = new QWidget(this);
setCentralWidget(centralWidget);
QHBoxLayout *mainLayout = new QHBoxLayout(centralWidget);
mainLayout->setContentsMargins(8, 8, 8, 8);
mainLayout->setSpacing(8);
// Left sidebar panel
QWidget *panel = new QWidget(centralWidget);
panel->setFixedWidth(320);
QVBoxLayout *panelLayout = new QVBoxLayout(panel);
panelLayout->setContentsMargins(4, 4, 4, 4);
// Image loading section
QGroupBox *grpFile = new QGroupBox("1. Imagen de Inspección", panel);
QVBoxLayout *fileLayout = new QVBoxLayout(grpFile);
QPushButton *btnOpen = new QPushButton("Cargar Imagen...", grpFile);
btnOpen->setIcon(style()->standardIcon(QStyle::SP_DialogOpenButton));
btnOpen->setFixedHeight(36);
fileLayout->addWidget(btnOpen);
panelLayout->addWidget(grpFile);
// Calibration setup section
QGroupBox *grpCalib = new QGroupBox("2. Calibración", panel);
QVBoxLayout *calibLayout = new QVBoxLayout(grpCalib);
QFormLayout *formGrid = new QFormLayout();
m_spinSquareSize = new QDoubleSpinBox(grpCalib);
m_spinSquareSize->setRange(0.1, 1000.0);
m_spinSquareSize->setValue(30.0);
m_spinSquareSize->setSuffix(" mm");
m_spinSquareSize->setDecimals(1);
formGrid->addRow("Lado Cuadrado (Ajedrez):", m_spinSquareSize);
calibLayout->addLayout(formGrid);
QPushButton *btnCalibChessboard = new QPushButton("Autocalibrar Ajedrez", grpCalib);
btnCalibChessboard->setFixedHeight(30);
btnCalibChessboard->setStyleSheet("font-weight: bold; background-color: #b71c1c; color: white; border-radius: 4px;");
calibLayout->addWidget(btnCalibChessboard);
panelLayout->addWidget(grpCalib);
// Measurement readout section
QGroupBox *grpMeas = new QGroupBox("3. Medición en Vivo", panel);
QVBoxLayout *measLayout = new QVBoxLayout(grpMeas);
m_lblMeasurement = new QLabel("Medida: -\nDistancia: - px", grpMeas);
m_lblMeasurement->setStyleSheet("font-size: 14px; font-weight: bold; color: #ff5555; background: #1e1e24; padding: 10px; border-radius: 4px;");
measLayout->addWidget(m_lblMeasurement);
panelLayout->addWidget(grpMeas);
panelLayout->addStretch();
// OpenGL Central Viewport Widget
m_glWidget = new MeasurementWidget(centralWidget);
mainLayout->addWidget(panel);
mainLayout->addWidget(m_glWidget, 1);
// Connect signals & slots
connect(btnOpen, &QPushButton::clicked, this, &MainWindow::openImage);
connect(m_glWidget, &MeasurementWidget::measurementUpdated, this, &MainWindow::updateMeasurementInfo);
// Connect progress signal to dynamically update the gradient color of the button!
connect(m_glWidget, &MeasurementWidget::calibrationProgress, this, [btnCalibChessboard](int percent) {
double ratio = percent / 100.0;
btnCalibChessboard->setStyleSheet(QString(
"font-weight: bold; color: white; border-radius: 4px;"
"background: qlineargradient(x1:0, y1:0, x2:1, y2:0, stop:0 #2e7d32, stop:%1 #2e7d32, stop:%2 #b71c1c, stop:1 #b71c1c);"
).arg(ratio).arg(qMin(1.0, ratio + 0.001)));
});
// Autocalibrate using chessboard
connect(btnCalibChessboard, &QPushButton::clicked, this, [this, btnCalibChessboard, btnOpen]() {
btnCalibChessboard->setEnabled(false);
btnOpen->setEnabled(false);
int gx = 0; // Pass 0 to auto-detect
int gy = 0; // Pass 0 to auto-detect
double sqSize = m_spinSquareSize->value();
bool success = m_glWidget->calibrateWithChessboard(gx, gy, sqSize);
if (success) {
// Keep green when calibrated successfully
btnCalibChessboard->setStyleSheet("font-weight: bold; background-color: #2e7d32; color: white; border-radius: 4px;");
} else {
// Return to red if calibration failed
btnCalibChessboard->setStyleSheet("font-weight: bold; background-color: #b71c1c; color: white; border-radius: 4px;");
}
btnCalibChessboard->setEnabled(true);
btnOpen->setEnabled(true);
if (success) {
int squaresX = gx + 1;
int squaresY = gy + 1;
QMessageBox::information(this, "Calibración Exitosa",
QString("Se detectó automáticamente un tablero de ajedrez.\n\n"
"Dimensiones identificadas:\n"
"- Intersecciones internas: %1 x %2\n"
"- Cuadrados totales: %3 x %4\n"
"- Medida del lado: %5 mm\n\n"
"La distorsión del lente y la perspectiva han sido calibradas con éxito.")
.arg(gx).arg(gy).arg(squaresX).arg(squaresY).arg(sqSize, 0, 'f', 1));
} else {
QMessageBox::warning(this, "Error de Calibración",
QString("No se pudo detectar automáticamente ningún tablero de ajedrez en la imagen.\n\n"
"Por favor verifica:\n"
"1. Que el tablero esté bien iluminado y plano.\n"
"2. Que el tablero esté completamente visible en la foto."));
}
});
// Reset calibration button color to red when a new image is loaded
connect(m_glWidget, &MeasurementWidget::imageLoaded, this, [btnCalibChessboard]() {
btnCalibChessboard->setStyleSheet("font-weight: bold; background-color: #b71c1c; color: white; border-radius: 4px;");
});
}
void MainWindow::openImage()
{
QString fileName = QFileDialog::getOpenFileName(this, "Abrir Imagen de Inspección", "", "Imágenes (*.png *.jpg *.jpeg *.bmp *.tif *.tiff)");
if (!fileName.isEmpty()) {
if (!m_glWidget->loadImage(fileName)) {
QMessageBox::warning(this, "Error", "No se pudo cargar la imagen seleccionada.");
}
}
}
void MainWindow::updateMeasurementInfo(double px, double mm)
{
Q_UNUSED(px);
if (m_glWidget->isCalibrated()) {
m_lblMeasurement->setText(QString("Medida: %1 mm").arg(mm, 0, 'f', 2));
} else {
m_lblMeasurement->setText("Medida: Sin Calibrar");
}
}