VHFMill/mainwindow.cpp
2023-01-29 18:45:42 +01:00

553 lines
18 KiB
C++

#include "mainwindow.h"
#include "./ui_mainwindow.h"
#include <QMessageBox>
#include <QInputDialog>
#include <QFileDialog>
#include "gcodetovhf.h"
MainWindow::MainWindow(VhfMill* mill, QWidget *parent)
: mill_(mill), QMainWindow(parent),
ui(new Ui::MainWindow),
viewTopAction(QKeySequence(Qt::Key_7), this, 0, 0, Qt::ApplicationShortcut),
viewFrontAction(QKeySequence(Qt::Key_1), this, 0, 0, Qt::ApplicationShortcut),
viewLeftAction(QKeySequence(Qt::Key_9), this, 0, 0, Qt::ApplicationShortcut),
viewRightAction(QKeySequence(Qt::Key_3), this, 0, 0, Qt::ApplicationShortcut)
{
installEventFilter(this);
ui->setupUi(this);
checkBlocks();
int splitHight = ui->splitter->size().height();
ui->splitter->setSizes({3*splitHight/4, splitHight/4});
ui->horizontalSlider->setTracking(false);
ui->plainTextEdit_compiled->setVisible(false);
ui->plainTextEdit_compiled->setWordWrapMode(QTextOption::NoWrap);
ui->plainTextEdit->setWordWrapMode(QTextOption::NoWrap);
connect(mill_, &VhfMill::raiseError, this, &MainWindow::raiseError);
connect(mill_, &VhfMill::positionUpdate, this, &MainWindow::positionUpdate);
connect(mill_, &VhfMill::gotToolNum, ui->lcd_tool, QOverload<int>::of(&QLCDNumber::display));
connect(mill_, &VhfMill::gotOutputs, this, &MainWindow::gotOutputs);
connect(mill_, &VhfMill::gotSindleSpeed, this, &MainWindow::gotSpindleSpeed);
connect(mill_, &VhfMill::gotProbeState, ui->led_probe, &Led::setLit);
connect(mill_, &VhfMill::gotPressureState, this, &MainWindow::gotPressureState);
connect(mill_, &VhfMill::initDone, this, &MainWindow::checkBlocks);
connect(mill_, &VhfMill::isHomed, this, &MainWindow::isHomed);
connect(mill_, &VhfMill::toolChangeDone, this, &MainWindow::toolChangeDone);
connect(mill_, &VhfMill::touchoffChanged, this, &MainWindow::touchoffChanged);
connect(mill_, &VhfMill::positionUpdate, ui->backPlot, &BackPlotWidget::positionUpdate);
connect(ui->checkBox_oe1, &QCheckBox::toggled, mill_,
[this](bool checked)
{
QMetaObject::invokeMethod(mill_, "setOutput", Qt::QueuedConnection, Q_ARG(int, 1), Q_ARG(bool, checked));
});
connect(ui->checkBox_oe2, &QCheckBox::toggled, mill_,
[this](bool checked)
{
QMetaObject::invokeMethod(mill_, "setOutput", Qt::QueuedConnection, Q_ARG(int, 2), Q_ARG(bool, checked));
});
connect(ui->checkBox_oe3, &QCheckBox::toggled, mill_,
[this](bool checked)
{
QMetaObject::invokeMethod(mill_, "setOutput", Qt::QueuedConnection, Q_ARG(int, 3), Q_ARG(bool, checked));
});
connect(ui->checkBox_oe4, &QCheckBox::toggled, mill_,
[this](bool checked)
{
QMetaObject::invokeMethod(mill_, "setOutput", Qt::QueuedConnection, Q_ARG(int, 4), Q_ARG(bool, checked));
});
connect(ui->checkBox_oe5, &QCheckBox::toggled, mill_,
[this](bool checked)
{
QMetaObject::invokeMethod(mill_, "setOutput", Qt::QueuedConnection, Q_ARG(int, 5), Q_ARG(bool, checked));
});
connect(ui->checkBox_oe6, &QCheckBox::toggled, mill_,
[this](bool checked)
{
QMetaObject::invokeMethod(mill_, "setOutput", Qt::QueuedConnection, Q_ARG(int, 6), Q_ARG(bool, checked));
});
connect(ui->checkBox_oe7, &QCheckBox::toggled, mill_,
[this](bool checked)
{
QMetaObject::invokeMethod(mill_, "setOutput", Qt::QueuedConnection, Q_ARG(int, 7), Q_ARG(bool, checked));
});
connect(ui->pushButton_home, &QPushButton::clicked, this, &MainWindow::home);
connect(ui->pushButton_homeAll, &QPushButton::clicked, this, [this](){QMetaObject::invokeMethod(mill_, [this]() {mill_->home(VhfMill::AXIS_ALL);}, Qt::QueuedConnection);});
connect(ui->pushButton_stopSpindle, &QPushButton::clicked, this, &MainWindow::stopSpindle);
connect(ui->horizontalSlider, &QSlider::valueChanged, mill_, &VhfMill::setSpindleSpeed);
connect(ui->pushButton_init, &QPushButton::clicked, mill_, &VhfMill::init);
connect(ui->pushButton_run, &QPushButton::clicked, this, &MainWindow::run);
connect(ui->pushButton_toolUnload, &QPushButton::clicked, this, &MainWindow::toolUnload);
connect(ui->pushButton_toolSwitch, &QPushButton::clicked, this, &MainWindow::toolSwitch);
connect(ui->pushButton_touchoff, &QPushButton::clicked, this, &MainWindow::touchoff);
connect(ui->pushButton_touchoffAll, &QPushButton::clicked, this, &MainWindow::touchoffAll);
connect(ui->pushButton_touchoffRst, &QPushButton::clicked, this, &MainWindow::touchoffRst);
connect(ui->pushButton_stop, &QPushButton::released, mill_, &VhfMill::stop);
connect(ui->actionOpen_Gcode, &QAction::triggered, this, &MainWindow::openGcode);
connect(ui->actionOpen, &QAction::triggered, this, &MainWindow::openVhfCode);
connect(ui->plainTextEdit, &QPlainTextEdit::textChanged, this, &MainWindow::textChanged);
connect(ui->radioButton_gcode, &QRadioButton::toggled, ui->plainTextEdit_compiled, &QPlainTextEdit::setVisible);
connect(ui->radioButton_gcode, &QRadioButton::toggled, this, &MainWindow::textChanged);
connect(ui->comboBox_jogStep, &QComboBox::currentIndexChanged, this, &MainWindow::selectedJogStepChanged);
connect(ui->pushButton_jogXp, &QPushButton::pressed, this, [this](){jog(VhfMill::AXIS_X, 1);});
connect(ui->pushButton_jogXn, &QPushButton::pressed, this, [this](){jog(VhfMill::AXIS_X, -1);});
connect(ui->pushButton_jogYp, &QPushButton::pressed, this, [this](){jog(VhfMill::AXIS_Y, -1);});
connect(ui->pushButton_jogYn, &QPushButton::pressed, this, [this](){jog(VhfMill::AXIS_Y, 1);});
connect(ui->pushButton_jogUp, &QPushButton::pressed, this, [this](){jog(VhfMill::AXIS_Z, 1);});
connect(ui->pushButton_jogDown, &QPushButton::pressed, this, [this](){jog(VhfMill::AXIS_Z, -1);});
connect(ui->pushButton_jogAp, &QPushButton::pressed, this, [this](){jog(VhfMill::AXIS_A, 1);});
connect(ui->pushButton_jogAn, &QPushButton::pressed, this, [this](){jog(VhfMill::AXIS_A, -1);});
connect(ui->pushButton_jogXp, &QPushButton::released, this, [this](){jog(VhfMill::AXIS_X, 0);});
connect(ui->pushButton_jogXn, &QPushButton::released, this, [this](){jog(VhfMill::AXIS_X, 0);});
connect(ui->pushButton_jogYp, &QPushButton::released, this, [this](){jog(VhfMill::AXIS_Y, 0);});
connect(ui->pushButton_jogYn, &QPushButton::released, this, [this](){jog(VhfMill::AXIS_Y, 0);});
connect(ui->pushButton_jogUp, &QPushButton::released, this, [this](){jog(VhfMill::AXIS_Z, 0);});
connect(ui->pushButton_jogDown, &QPushButton::released, this, [this](){jog(VhfMill::AXIS_Z, 0);});
connect(ui->pushButton_jogAp, &QPushButton::released, this, [this](){jog(VhfMill::AXIS_A, 0);});
connect(ui->pushButton_jogAn, &QPushButton::released, this, [this](){jog(VhfMill::AXIS_A, 0);});
BackPlotWidget* backplot = ui->backPlot;
connect(&viewTopAction, &QShortcut::activated, backplot, [backplot](){backplot->showView(BackPlotWidget::VIEW_TOP);});
connect(&viewFrontAction, &QShortcut::activated, backplot, [backplot](){backplot->showView(BackPlotWidget::VIEW_FRONT);});
connect(&viewLeftAction, &QShortcut::activated, backplot, [backplot](){backplot->showView(BackPlotWidget::VIEW_LEFT);});
connect(&viewRightAction, &QShortcut::activated, backplot, [backplot](){backplot->showView(BackPlotWidget::VIEW_RIGHT);});
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::selectedJogStepChanged(int index)
{
switch(index)
{
case 0:
QMetaObject::invokeMethod(mill_, [this](){mill_->setjogStep(-1);}, Qt::QueuedConnection);
break;
case 1:
QMetaObject::invokeMethod(mill_, [this](){mill_->setjogStep(5000);}, Qt::QueuedConnection);
break;
case 2:
QMetaObject::invokeMethod(mill_, [this](){mill_->setjogStep(1000);}, Qt::QueuedConnection);
break;
case 3:
QMetaObject::invokeMethod(mill_, [this](){mill_->setjogStep(250);}, Qt::QueuedConnection);
break;
case 4:
QMetaObject::invokeMethod(mill_, [this](){mill_->setjogStep(100);}, Qt::QueuedConnection);
break;
case 5:
QMetaObject::invokeMethod(mill_, [this](){mill_->setjogStep(50);}, Qt::QueuedConnection);
break;
default:
QMetaObject::invokeMethod(mill_, [this](){mill_->setjogStep(0);}, Qt::QueuedConnection);
break;
}
}
void MainWindow::jog(VhfMill::Axis axis, int jogDirection)
{
QMetaObject::invokeMethod(mill_, [this, axis, jogDirection](){mill_->jog(axis, jogDirection);}, Qt::QueuedConnection);
}
bool MainWindow::eventFilter(QObject *object, QEvent *event)
{
if(jogEnabled)
{
if(event->type() == QEvent::KeyPress)
{
QKeyEvent *ke = static_cast<QKeyEvent *>(event);
switch(ke->key())
{
case Qt::Key_Up:
if(!ke->isAutoRepeat())
jog(VhfMill::AXIS_Y, -1);
event->setAccepted(true);
return true;
case Qt::Key_Left:
if(!ke->isAutoRepeat())
jog(VhfMill::AXIS_X, -1);
event->setAccepted(true);
return true;
case Qt::Key_Right:
if(!ke->isAutoRepeat())
jog(VhfMill::AXIS_X, 1);
event->setAccepted(true);
return true;
case Qt::Key_Down:
if(!ke->isAutoRepeat())
jog(VhfMill::AXIS_Y, 1);
event->setAccepted(true);
return true;
case Qt::Key_PageUp:
if(!ke->isAutoRepeat())
jog(VhfMill::AXIS_Z, 1);
event->setAccepted(true);
return true;
case Qt::Key_PageDown:
if(!ke->isAutoRepeat())
jog(VhfMill::AXIS_Z, -1);
event->setAccepted(true);
return true;
default:
break;
}
}
else if(event->type() == QEvent::KeyRelease)
{
QKeyEvent *ke = static_cast<QKeyEvent *>(event);
switch(ke->key())
{
case Qt::Key_Up:
if(!ke->isAutoRepeat())
jog(VhfMill::AXIS_Y, 0);
event->setAccepted(true);
return true;
case Qt::Key_Left:
if(!ke->isAutoRepeat())
jog(VhfMill::AXIS_X, 0);
event->setAccepted(true);
return true;
case Qt::Key_Right:
if(!ke->isAutoRepeat())
jog(VhfMill::AXIS_X, 0);
event->setAccepted(true);
return true;
case Qt::Key_Down:
if(!ke->isAutoRepeat())
jog(VhfMill::AXIS_Y, 0);
event->setAccepted(true);
return true;
case Qt::Key_PageUp:
if(!ke->isAutoRepeat())
jog(VhfMill::AXIS_Z, 0);
event->setAccepted(true);
return true;
case Qt::Key_PageDown:
if(!ke->isAutoRepeat())
jog(VhfMill::AXIS_Z, 0);
event->setAccepted(true);
return true;
default:
break;
}
}
}
return false;
}
void MainWindow::textChanged()
{
bool ok = true;
QByteArray programm = ui->plainTextEdit->toPlainText().toLatin1();
if(ui->radioButton_gcode->isChecked())
{
QList<QString> errors;
programm = gcodeToVhf(programm, &ok, &errors);
if(!ok)
ui->statusbar->showMessage(errors.back());
ui->plainTextEdit_compiled->setPlainText(programm);
}
ui->backPlot->programChanged(programm);
}
void MainWindow::home()
{
VhfMill::Axis axis = comboBoxToAxis(*ui->comboBox_homeAxis);
qDebug()<<__func__<<axis;
QMetaObject::invokeMethod(mill_, [this, axis](){mill_->home(axis);}, Qt::QueuedConnection);
}
void MainWindow::toolUnload()
{
QMetaObject::invokeMethod(mill_, [this](){mill_->setTool(0);}, Qt::QueuedConnection);
}
void MainWindow::gotSpindleSpeed(int speed)
{
ui->lcd_spindle->display(speed);
}
void MainWindow::stopSpindle()
{
QMetaObject::invokeMethod(mill_, [this](){mill_->setSpindleSpeed(0);}, Qt::QueuedConnection);
ui->horizontalSlider->setValue(0);
}
void MainWindow::isHomed(VhfMill::Axis axis)
{
ui->led_homeX->setLit(axis & VhfMill::AXIS_X);
ui->led_homeY->setLit(axis & VhfMill::AXIS_Y);
ui->led_homeZ->setLit(axis & VhfMill::AXIS_Z);
ui->led_homeA->setLit(axis & VhfMill::AXIS_A);
checkBlocks();
}
VhfMill::Axis MainWindow::comboBoxToAxis(const QComboBox& box)
{
switch(box.currentIndex())
{
case 0:
return VhfMill::AXIS_X;
case 1:
return VhfMill::AXIS_Y;
case 2:
return VhfMill::AXIS_Z;
case 3:
return VhfMill::AXIS_A;
case 4:
return VhfMill::AXIS_B;
default:
return VhfMill::AXIS_NONE;
}
}
void MainWindow::run()
{
QByteArray programm = ui->plainTextEdit->toPlainText().toLatin1();
if(ui->radioButton_gcode->isChecked())
{
bool ok;
programm = gcodeToVhf(programm, &ok);
if(!ok)
{
QMessageBox::critical(this, "Error", "failed to parse gcode");
return;
}
}
QMetaObject::invokeMethod(mill_, [programm, this](){mill_->send(programm);}, Qt::QueuedConnection);
}
void MainWindow::toolSwitch()
{
QMetaObject::invokeMethod(mill_, [this](){mill_->setTool(ui->comboBox_tool->currentIndex()+1);}, Qt::QueuedConnection);
}
void MainWindow::touchoff()
{
bool ok;
double offset = QInputDialog::getDouble(this, "Offset", "offset in mm", 0, -1000, 1000, 2, &ok);
if(ok)
QMetaObject::invokeMethod(mill_, [this, offset](){mill_->touchOff(comboBoxToAxis(*ui->comboBox_TouchoffAxis), offset*1000);}, Qt::QueuedConnection);
}
void MainWindow::touchoffAll()
{
QMetaObject::invokeMethod(mill_, [this](){mill_->touchOff(VhfMill::AXIS_ALL, 0);}, Qt::QueuedConnection);
}
void MainWindow::touchoffRst()
{
QMetaObject::invokeMethod(mill_, [this](){mill_->touchOffAbsolute({0,0,0,0});}, Qt::QueuedConnection);
}
void MainWindow::toolChangeDone()
{
QMetaObject::invokeMethod(mill_, &VhfMill::reqTool, Qt::QueuedConnection);
setToolchangeBlocked(false);
}
void MainWindow::raiseError(int errorNum)
{
QMessageBox::critical(this, "Error", VhfMill::textForErrno(errorNum));
checkBlocks();
}
void MainWindow::positionUpdate(std::vector<int> position)
{
if(position.size() < 4)
return;
std::vector<int> touchoff;
if(ui->radioButton->isChecked())
touchoff.assign(position.size(), 0);
else
touchoff = mill_->getLastTouchoffPosition();
size_t xIndex = VhfMill::axisToIndex(VhfMill::AXIS_X);
size_t yIndex = VhfMill::axisToIndex(VhfMill::AXIS_Y);
size_t zIndex = VhfMill::axisToIndex(VhfMill::AXIS_Z);
size_t aIndex = VhfMill::axisToIndex(VhfMill::AXIS_A);
double xDpl = position[xIndex] - touchoff[xIndex];
double yDpl = position[yIndex] - touchoff[yIndex];
double zDpl = position[zIndex] - touchoff[zIndex];
double aDpl = position[aIndex] - touchoff[aIndex];
ui->lcd_x->display(xDpl/1000.0);
ui->lcd_y->display(yDpl/1000.0);
ui->lcd_z->display(zDpl/1000.0);
ui->lcd_a->display(aDpl/1000.0);
}
void MainWindow::openVhfCode()
{
QString fileName = QFileDialog::getOpenFileName(this, "Open File", "~", "VhfCode (*.vhf)");
if(!fileName.isEmpty())
{
QFile gcodeFile(fileName);
if(!gcodeFile.open(QIODeviceBase::ReadOnly))
{
QMessageBox::critical(this, "Error", "Could not open " + fileName + " for reading");
return;
}
QByteArray vhfCode = gcodeFile.readAll();
ui->radioButton_vhfCode->setChecked(true);
ui->plainTextEdit->setPlainText(vhfCode);
}
}
void MainWindow::openGcode()
{
QString fileName = QFileDialog::getOpenFileName(this, "Open File", "~", "Gcode (*.ngc *.nc)");
if(!fileName.isEmpty())
{
QFile gcodeFile(fileName);
if(!gcodeFile.open(QIODeviceBase::ReadOnly))
{
QMessageBox::critical(this, "Error", "Could not open " + fileName + " for reading");
return;
}
bool ok;
QByteArray gcode = gcodeFile.readAll();
gcodeToVhf(gcode, &ok);
if(!ok)
{
QMessageBox::critical(this, "Error", "failed to parse gcode");
return;
}
ui->radioButton_gcode->setChecked(true);
ui->radioButton_vhfCode->setChecked(false);
ui->plainTextEdit->setPlainText(gcode);
}
}
void MainWindow::touchoffChanged(std::vector<int> position)
{
if(position.size() < 4)
return;
ui->lcd_touchX->display(static_cast<double>(position[VhfMill::axisToIndex(VhfMill::AXIS_X)])/1000.0);
ui->lcd_touchY->display(static_cast<double>(position[VhfMill::axisToIndex(VhfMill::AXIS_Y)])/1000.0);
ui->lcd_touchZ->display(static_cast<double>(position[VhfMill::axisToIndex(VhfMill::AXIS_Z)])/1000.0);
ui->lcd_touchA->display(static_cast<double>(position[VhfMill::axisToIndex(VhfMill::AXIS_A)])/1000.0);
positionUpdate(mill_->getLastKnownPosition());
ui->backPlot->touchoffUpdate(position);
textChanged();
}
void MainWindow::checkBlocks()
{
setAllBlocked(true);
if(mill_->isInitDone())
{
qDebug()<<__func__<<"unblocking home and spindle";
setSpindleBlocked(false);
setHomeingBlocked(false);
setOutputsBlocked(false);
if(mill_->allHomed())
{
qDebug()<<__func__<<"unblocking jog";
setJogBlocked(false);
ui->pushButton_run->setEnabled(true);
if(mill_->presureReady())
{
qDebug()<<__func__<<"unblocking tool change";
setToolchangeBlocked(false);
}
}
}
}
void MainWindow::gotOutputs(uint8_t outputs)
{
ui->checkBox_oe1->setChecked(outputs & 1<<0);
ui->checkBox_oe2->setChecked(outputs & 1<<1);
ui->checkBox_oe3->setChecked(outputs & 1<<2);
ui->checkBox_oe4->setChecked(outputs & 1<<3);
ui->checkBox_oe5->setChecked(outputs & 1<<4);
ui->checkBox_oe6->setChecked(outputs & 1<<5);
ui->checkBox_oe7->setChecked(outputs & 1<<6);
}
void MainWindow::gotPressureState(bool state)
{
ui->led_pressure->setLit(!state);
checkBlocks();
}
void MainWindow::setAllBlocked(bool blocked)
{
setOutputsBlocked(blocked);
setJogBlocked(blocked);
setToolchangeBlocked(blocked);
setSpindleBlocked(blocked);
setHomeingBlocked(blocked);
ui->pushButton_run->setEnabled(!blocked);
}
void MainWindow::setOutputsBlocked(bool block)
{
ui->checkBox_oe1->setEnabled(!block);
ui->checkBox_oe2->setEnabled(!block);
ui->checkBox_oe3->setEnabled(!block);
ui->checkBox_oe4->setEnabled(!block);
ui->checkBox_oe5->setEnabled(!block);
ui->checkBox_oe6->setEnabled(!block);
ui->checkBox_oe7->setEnabled(!block);
}
void MainWindow::setJogBlocked(bool block)
{
jogEnabled = !block;
ui->pushButton_jogDown->setEnabled(!block);
ui->pushButton_jogUp->setEnabled(!block);
ui->pushButton_jogXp->setEnabled(!block);
ui->pushButton_jogXn->setEnabled(!block);
ui->pushButton_jogYp->setEnabled(!block);
ui->pushButton_jogYn->setEnabled(!block);
ui->pushButton_jogAp->setEnabled(!block);
ui->pushButton_jogAn->setEnabled(!block);
ui->comboBox_jogStep->setEnabled(!block);
}
void MainWindow::setToolchangeBlocked(bool block)
{
ui->pushButton_toolSwitch->setEnabled(!block);
ui->pushButton_toolUnload->setEnabled(!block);
ui->comboBox_tool->setEnabled(!block);
}
void MainWindow::setSpindleBlocked(bool block)
{
ui->pushButton_stopSpindle->setEnabled(!block);
ui->horizontalSlider->setEnabled(!block);
}
void MainWindow::setHomeingBlocked(bool block)
{
ui->pushButton_home->setEnabled(!block);
ui->pushButton_homeAll->setEnabled(!block);
ui->comboBox_homeAxis->setEnabled(!block);
}
void MainWindow::setTouchoffBlocked(bool block)
{
ui->comboBox_TouchoffAxis->setEnabled(!block);
ui->pushButton_touchoff->setEnabled(!block);
ui->pushButton_touchoffAll->setEnabled(!block);
}