DSCAnalysisTool/src/mainwindow.cpp
2025-06-06 17:17:31 +08:00

798 lines
23 KiB
C++

#include <qmessagebox.h>
#include "lowesssmoother.h"
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "global.h"
#include "serialport.h"
#include "dataparser.h"
#include "filemanager.h"
#include "logger.h"
#include "xlsxhandler.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent),
ui(new Ui::MainWindow),
_centralWidget(new CentralWidget(this)),
_leftWidget(new LeftWidget(this)),
_expertmentSettingForm(new ExperimentSettingForm(this)),
_realTimeDataForm(new RealTimeDataForm(this)),
_rightWidget(new QDockWidget(this))
,_analysisSettingWidget(new AnalysisSettingForm(this))
,_contextMenu(new QMenu(this))
,_specificHeatComparisonMethodForm(new SpecificHeatComparisonMethodForm(this))
,_instrumentCoefficientForm(new InstrumentCoefficientForm(this))
,_degreeOfCureForm(new DegreeOfCureForm(this))
,_OITAutoAnalysisParamForm(new OITAutoAnalysisParamForm(this))
,_degreeOfCrystallinityForm(new DegreeOfCrystallinityForm(this))
,_aboutForm(new AboutForm(this))
,_enthalpyDataCorrectionForm(new EnthalpyDataCorrectionForm(this))
,_coefficientSelectionForm(new CoefficientSelectionForm(this))
,_printPreviewForm(new PrintPreviewForm(this))
,_axisSettingForm(new AxisSettingForm(this))
,_manuallyStopTheExperimentFlag(false)
{
ui->setupUi(this);
this->setToolTip(".....");
ui->actionSaveas->setVisible(false);
setCentralWidget(_centralWidget);
addDockWidget(Qt::LeftDockWidgetArea, _leftWidget);
addDockWidget(Qt::RightDockWidgetArea, _rightWidget);
_rightWidget->setWidget(_analysisSettingWidget);
_rightWidget->hide();
//
ui->statusbar->showMessage("showMessage show temp message!");
// permenent show
QLabel *permenentLabel = new QLabel(this);
permenentLabel->setText("Software Ver:" + qApp->applicationVersion());
ui->statusbar->addPermanentWidget(permenentLabel);
ui->actionTimeAxisAnalysisPCTMode->setCheckable(true);
//
setSubWidgetAttribute(_expertmentSettingForm);
setSubWidgetAttribute(_specificHeatComparisonMethodForm);
setSubWidgetAttribute(_realTimeDataForm);
setSubWidgetAttribute(_degreeOfCureForm);
setSubWidgetAttribute(_instrumentCoefficientForm);
setSubWidgetAttribute(_OITAutoAnalysisParamForm);
setSubWidgetAttribute(_degreeOfCrystallinityForm);
setSubWidgetAttribute(_aboutForm);
setSubWidgetAttribute(_enthalpyDataCorrectionForm);
setSubWidgetAttribute(_coefficientSelectionForm);
setSubWidgetAttribute(_printPreviewForm);
setSubWidgetAttribute(_axisSettingForm);
//
setActionEnable(true);
_eventHandler = _centralWidget->getEvnetHandler();
//
connections();
//
// ui->actionStop->setEnabled(false);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::slotContextMenuShow(const QPoint point)
{
_contextMenu->exec(point);
}
void MainWindow::slotUpdateStatusbarMsg(const QString msg)
{
ui->statusbar->showMessage(msg);
}
void MainWindow::closeEvent(QCloseEvent *event)
{
// 弹出确认对话框
QMessageBox::StandardButton reply;
reply = QMessageBox::question(this, "确认退出", "你确定要退出吗?",
QMessageBox::Yes | QMessageBox::No);
if (reply == QMessageBox::Yes) {
event->accept(); // 接受关闭事件,关闭窗口
} else {
event->ignore(); // 忽略关闭事件,不关闭窗口
}
}
void MainWindow::connections()
{
// ui
connect(_expertmentSettingForm, &ExperimentSettingForm::sigDeliverData,
SerialPort::instance(), &SerialPort::slotDeliverData);
#if 1
// SerialPort.
connect(SerialPort::instance(), &SerialPort::sigSendCommonData,
_centralWidget, &CentralWidget::slotRecvCommonData);
connect(SerialPort::instance(), &SerialPort::sigSendCommonData,
_realTimeDataForm, &RealTimeDataForm::slotRevCommonData);
connect(SerialPort::instance(), &SerialPort::sigSendCommonDataToRealDataForm,
_realTimeDataForm, &RealTimeDataForm::slotRevCommonData);
connect(SerialPort::instance(), &SerialPort::sigSendPhaseInfo,
_expertmentSettingForm, &ExperimentSettingForm::slotRecvPhaseInfo);
connect(SerialPort::instance(), &SerialPort::sigAxisModify,
_centralWidget, &CentralWidget::slotAxisModify);
connect(SerialPort::instance(), &SerialPort::sigUpdateStatusbarMsg,
this,&MainWindow::slotUpdateStatusbarMsg);
connect(SerialPort::instance(), &SerialPort::sigSaveExperimentalDataMsgBox,
this,&MainWindow::slotSaveExperimentalDataMsgBox);
#endif
// mode
// connect(Global::instance(), &Global::sigModeModify,
// _centralWidget, &CentralWidget::slotModeModify);
//analysis
connect(_leftWidget,&LeftWidget::sigSendAnalysisFileName,
_centralWidget,&CentralWidget::slotRecvAnalysisFileName);
connect(_centralWidget,&CentralWidget::sigSendLineXCoord,
_analysisSettingWidget,&AnalysisSettingForm::slotRecvLineXCoord);
connect(_analysisSettingWidget,&AnalysisSettingForm::sigApply,
_centralWidget,&CentralWidget::slotAnalysisSettingApply);
connect(_analysisSettingWidget,&AnalysisSettingForm::sigUndo,
_centralWidget,&CentralWidget::slotAnalysisSettingUndo);
connect(_analysisSettingWidget,&AnalysisSettingForm::sigConfirm,
_centralWidget,&CentralWidget::slotAnalysisSettingConfirm);
connect(_analysisSettingWidget,&AnalysisSettingForm::sigCancel,
_centralWidget,&CentralWidget::slotAnalysisSettingCancel);
connect(_centralWidget,&CentralWidget::sigRightDockWidgetHide,
[&](){ _rightWidget->hide(); });
connect(_degreeOfCrystallinityForm,&DegreeOfCrystallinityForm::sigDrawCustomText,
_centralWidget,&CentralWidget::slotDrawCustomText);
connect(_specificHeatComparisonMethodForm,&SpecificHeatComparisonMethodForm::sigDrawCustomText,
_centralWidget,&CentralWidget::slotDrawCustomText);
//SpecificHeatComparisonMethodForm
connect(_eventHandler,&EventHandler::sigSetCurve,
_specificHeatComparisonMethodForm,
&SpecificHeatComparisonMethodForm::slotSetCurve);
// Axis settings.
connect(_axisSettingForm,&AxisSettingForm::sigGetAxisInfo,
_centralWidget,&CentralWidget::slotGetAxisInfo);
connect(_centralWidget,&CentralWidget::sigGetAxisInfoWithData,
_axisSettingForm,&AxisSettingForm::slotGetAxisInfoWithData);
connect(_axisSettingForm,&AxisSettingForm::sigSetAxisSettings,
_centralWidget,&CentralWidget::slotSetAxisSettings);
}
void MainWindow::setActionEnable(const bool flag)
{
if (flag)
{
ui->actionNew->setEnabled(true);
ui->actionStart->setEnabled(true);
ui->actionStop->setEnabled(true);
ui->actionRealTimeWidget->setEnabled(true);
}
else
{
ui->actionNew->setEnabled(false);
ui->actionStart->setEnabled(false);
ui->actionStop->setEnabled(false);
ui->actionRealTimeWidget->setEnabled(false);
}
}
void MainWindow::setSubWidgetAttribute(QWidget *widget)
{
widget->setWindowModality(Qt::ApplicationModal);
widget->setWindowFlags(Qt::Dialog);
widget->setFixedSize(widget->geometry().width(),widget->geometry().height());
}
#if 0
bool MainWindow::saveExperimentFile(const QString fileName)
{
QString localFileName = fileName;
if(fileName.isEmpty()){
localFileName = "new";
}
QString xlsxfilePath = Global::SampleDataFloder + "/" + localFileName + ".xlsx";
QString filePath = QFileDialog::getSaveFileName(nullptr, "Save experiment file",
xlsxfilePath, "Excel Files (*.xlsx)");
logde<<"filePath:"<<filePath.toStdString();
if (filePath.isEmpty()) {
qDebug() << "User cancel the operation.";
return false;
}
XlsxHandler::writeFile(filePath);
return true;
}
bool MainWindow::saveAnalysisFile(const QString fileName)
{
QString localFileName = fileName;
if(fileName.isEmpty()){
localFileName = "new";
}
QString xlsxfilePath = Global::AnalysisStateFolder + "/" + localFileName + ".xlsx";
QString filePath = QFileDialog::getSaveFileName(nullptr, "Save experiment file",
xlsxfilePath, "Excel Files (*.xlsx)");
logde<<"filePath:"<<filePath.toStdString();
if (filePath.isEmpty()) {
qDebug() << "User cancel the operation.";
return false;
}
XlsxHandler::writeAnalysisOperation(filePath);
return true;
}
#endif
bool MainWindow::saveFile(const QString fileName,const Global::Mode mode)
{
QString localFileName = fileName;
if(fileName.isEmpty()){
localFileName = "new";
}
QString folder;
if(mode == Global::Mode::None){
folder = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation);
}else if(mode == Global::Mode::Analysis){
folder = Global::AnalysisStateFolder;
}else if(mode == Global::Mode::Experiment){
folder = Global::SampleDataFloder;
}
QString xlsxfilePath = folder + "/" + localFileName + ".xlsx";
QString filePath = QFileDialog::getSaveFileName(nullptr, "Save experiment file",
xlsxfilePath, "Excel Files (*.xlsx)");
logde<<"filePath:"<<filePath.toStdString();
if (filePath.isEmpty()) {
qDebug() << "User cancel the operation.";
return false;
}
// Save file.
if(mode == Global::Mode::Analysis){
if(Global::_curveFileDataVtr.empty()){
logde<<"analysis experiemt data...";
XlsxHandler::writeExperimentFile(filePath);
// XlsxHandler::writeAnalysisOperation(filePath);
}else{
logde<<"analysis xlsx data...";
if(Global::_smoothnessFlag){
}else{
XlsxHandler::appendAnalysisOperation(filePath);
}
}
}else if(mode == Global::Mode::Experiment){
logde<<"writeFile...";
XlsxHandler::writeExperimentFile(filePath);
#if 0
// Clear data.
Global::clearExperimentData();
#endif
}
return true;
}
void MainWindow::smoothness(const int level)
{
Global::_smoothnessFlag = true;
// process data.
QVector<Global::ExperimentData> targetDataVtr;
QString objectName;
QCPCurve ** curvePtrPtr;
if(!Global::_curveExperimentDataVtr.empty()){
for(auto & item:Global::_curveExperimentDataVtr){
if(_centralWidget->isCurrentCurve(item.curve)){
smoothnessDetail(level,item.dataVtr);
targetDataVtr = item.dataVtr;
objectName = Global::objectNameExperiemnt;
curvePtrPtr = &item.curve;
}
}
}else{
for(Global::CurveFileData &cfd :Global::_curveFileDataVtr){
for(Global::PhaseTotalInfo& pti:cfd.phaseTotalVtr){
if(_centralWidget->isCurrentCurve(pti.curve)){
smoothnessDetail(level,pti.dataVtr);
targetDataVtr = pti.dataVtr;
objectName = cfd.fileName;
curvePtrPtr = &pti.curve;
//
#if 0
Global::ExperimentData ed;
ed.sampleTemp = 2222;
ed.dsc = 2222;
pti.dataVtr.push_back(ed);
#endif
}
}
}
}
//
_centralWidget->deleteCurrentCurve();
//
_centralWidget->addSmoothnessCurveData(targetDataVtr,objectName);
*curvePtrPtr = _centralWidget->getCurrentCurve();
#if 0
// Get current data vtr;
QVector<Global::ExperimentData> dataVtr;
if(Global::_curveFileDataVtr.empty()){
// Load experiment data.
logde<<"experiment vtr size:"<<Global::_curveExperimentDataVtr.size();
for(Global::CurveExperimentData& ced:Global::_curveExperimentDataVtr){
if(_centralWidget->isCurrentCurve(ced.curve)){
logde<<"load experiment data.";
// PointCalculate::setAnalysisData(ced.dataVtr);
dataVtr = ced.dataVtr;
Global::_smoothnessFileName = ced.fileName;
break;
}
}
}else{
// Load xlsx file data.
for(Global::CurveFileData& cfd:Global::_curveFileDataVtr){
for(Global::PhaseTotalInfo& pti:cfd.phaseTotalVtr){
if(_centralWidget->isCurrentCurve(pti.curve)){
// PointCalculate::setAnalysisData(pti.dataVtr);
dataVtr = pti.dataVtr;
Global::_smoothnessFileName = cfd.fileName;
break;
}
}
}
}
if(dataVtr.empty()){
return;
}
// smoothness.
Lowess::Config config;
config.smoothingFactor = level * 0.1;
config.robustnessIterations = 3;
std::vector<double> x;
std::vector<double> y;
for(Global::ExperimentData& ed:dataVtr) {
if(Global::_axisMode == Global::AxisMode::SingleY){
x.push_back(ed.sampleTemp);
}else{
x.push_back(ed.runTime);
}
y.push_back(ed.dsc);
}
logde<<"smooth start...";
std::vector<double> yest = Lowess::smooth(x, y, config);
logde<<"smooth end...";
// Delete current curve;
_centralWidget->deleteCurrentCurve();
// Add new Curve.
QVector<Global::ExperimentData> newCurveDataVtr;
for(int i = 0; i < x.size();i++){
Global::ExperimentData ed;
if(Global::_axisMode == Global::AxisMode::SingleY){
ed.sampleTemp = x.at(i);
ed.runTime = dataVtr.at(i).runTime;
}else{
ed.runTime = x.at(i);
ed.sampleTemp = dataVtr.at(i).sampleTemp;
}
ed.dsc = yest.at(i);
ed.constantTempTime = dataVtr.at(i).constantTempTime;
newCurveDataVtr.push_back(ed);
}
_centralWidget->addSmoothnessCurveData(newCurveDataVtr);
#endif
}
QVector<Global::ExperimentData> MainWindow::smoothnessDetail(const int level,QVector<Global::ExperimentData>& dataVtr)
{
Lowess::Config config;
config.smoothingFactor = level * 0.1;
config.robustnessIterations = 3;
std::vector<double> x;
std::vector<double> y;
for(const Global::ExperimentData& ed:dataVtr) {
if(Global::_axisMode == Global::AxisMode::SingleY){
x.push_back(ed.sampleTemp);
}else{
x.push_back(ed.runTime);
}
y.push_back(ed.dsc);
}
logde<<"smooth start...";
std::vector<double> yest = Lowess::smooth(x, y, config);
logde<<"smooth end...";
// target data vector.
QVector<Global::ExperimentData> targetVtr;
for(int i = 0; i < x.size();i++){
Global::ExperimentData ed;
if(Global::_axisMode == Global::AxisMode::SingleY){
ed.sampleTemp = x.at(i);
ed.runTime = dataVtr.at(i).runTime;
}else{
ed.runTime = x.at(i);
ed.sampleTemp = dataVtr.at(i).sampleTemp;
}
ed.dsc = yest.at(i);
ed.constantTempTime = dataVtr.at(i).constantTempTime;
targetVtr.push_back(ed);
}
dataVtr.clear();
dataVtr = targetVtr;
return targetVtr;
}
void MainWindow::smoothnessExperimentData(const int level)
{
#if 0
for(int i = 0;i < Global::_curveExperimentDataVtr.size();i++){
Global::CurveExperimentData ced = Global::_curveExperimentDataVtr.at(i);
smoothnessDetail()
}
#endif
for(auto & item:Global::_curveExperimentDataVtr){
smoothnessDetail(level,item.dataVtr);
}
}
void MainWindow::on_actionStop_triggered()
{
logde<<" Stop experiment ...";
if(Global::_mode == Global::Mode::Experiment)
{
QByteArray ba = DataParser::setDeviceStartStop(DeviceStartMode::Stop);
SerialPort::instance()->slotSendData(ba);
#if 1
// Save data.
// if(saveExperimentFile(Global::_experimentInfo.sampleName)){
// _leftWidget->reloadFileName();
// }
if(saveFile(Global::_experimentInfo.sampleName,Global::Mode::Experiment)){
_leftWidget->reloadFileName();
}
#endif
// Set software mode to analysis.
Global::_mode = Global::Mode::Analysis;
_manuallyStopTheExperimentFlag = true;
}
}
void MainWindow::on_actionNew_triggered()
{
_expertmentSettingForm->show();
}
void MainWindow::on_actionStart_triggered()
{
logde<<"start experiment,set soft into experiment mode.";
on_actionClearAllData_triggered();
QByteArray ba = DataParser::setDeviceStartStop(DeviceStartMode::Start);
QString hexData = ba.toHex(' '); // ' ' 作为分隔符,可选参数
qDebug() << "on_actionStart_triggered info (hex):" << hexData;
SerialPort::instance()->slotSendData(ba);
Global::_mode = Global::Mode::Experiment;
_manuallyStopTheExperimentFlag = false;
}
void MainWindow::on_actionReadOnly_triggered()
{
Global::_mode = Global::Mode::Experiment;
SerialPort::instance()->openSp();
}
void MainWindow::on_actionRealTimeWidget_triggered()
{
_realTimeDataForm->show();
}
void MainWindow::slotSaveExperimentalDataMsgBox()
{
if(_manuallyStopTheExperimentFlag){
logde<<"_manuallyStopTheExperimentFlag...";
return;
}
QMessageBox::StandardButton reply;
reply = QMessageBox::question(this, "数据保存提示", "是否保存实验数据?",
QMessageBox::Yes | QMessageBox::No);
if (reply == QMessageBox::Yes) {
saveFile(Global::_experimentInfo.sampleName,Global::Mode::Experiment);
_leftWidget->reloadFileName();
} else {
on_actionClearAllData_triggered();
}
#if 0
// Clear data.
logde<<"save mesg box.clearExperimentData...";
Global::clearExperimentData();
#endif
}
void MainWindow::on_actionConnectToDev_triggered()
{
if(SerialPort::instance()->isOpen()){
SerialPort::instance()->closeSp();
ui->actionConnectToDev->setIcon(QIcon(":/images/connect.png"));
ui->actionConnectToDev->setText("连接设备");
logde<<"close serial port.";
}else{
if (SerialPort::instance()->openSp())
{
setActionEnable(true);
// Global::instance()->setMode(Global::Mode::ConnectedToDev);
Global::_mode = Global::Mode::ConnectedToDev;
QByteArray ba = DataParser::inquirePhaseInfo();
SerialPort::instance()->sendData(ba);
ui->actionConnectToDev->setIcon(QIcon(":/images/disconnect.png"));
ui->actionConnectToDev->setText("断开连接");
logde<<"open serial port.";
}
else
{
QMessageBox::warning(this, "warnning", "Serial Port open failed.");
}
}
}
void MainWindow::on_actionStartPoint_triggered()
{
_rightWidget->show();
_centralWidget->setAnalysisMode(CentralWidget::AnalysisMode::StartPoint);
}
void MainWindow::on_actionStopPoint_triggered()
{
_rightWidget->show();
_centralWidget->setAnalysisMode(CentralWidget::AnalysisMode::StopPoint);
}
void MainWindow::on_actionNumericalLabel_triggered()
{
_rightWidget->show();
_centralWidget->setAnalysisMode(CentralWidget::AnalysisMode::NumericalLabel);
}
void MainWindow::on_actionPeakSynthesisAnalysis_triggered()
{
_rightWidget->show();
_centralWidget->setAnalysisMode(CentralWidget::AnalysisMode::PeakSynthesisAnalysis);
}
void MainWindow::on_actionClearAllData_triggered()
{
_rightWidget->hide();
_centralWidget->clearAllData();
}
void MainWindow::on_actionGlassTransition_triggered()
{
_rightWidget->show();
_centralWidget->setAnalysisMode(CentralWidget::AnalysisMode::GlassTransition);
}
void MainWindow::on_actionOIT_triggered()
{
QMessageBox::warning(this, "warnning", "on_actionOIT_triggered.");
}
void MainWindow::on_actionSpecificHeatCompMethod_triggered()
{
_specificHeatComparisonMethodForm->show();
}
void MainWindow::on_actionDegreeOfCrystallinity_triggered()
{
// QMessageBox::warning(this, "warnning", "结晶度.");
_degreeOfCrystallinityForm->show();
}
void MainWindow::on_actionInstrumentParameter_triggered()
{
_instrumentCoefficientForm->show();
}
void MainWindow::on_actionOITAutoAnalysisParam_triggered()
{
_OITAutoAnalysisParamForm->show();
}
void MainWindow::on_actionOITAutoAnalysisMode_triggered()
{
//
}
void MainWindow::on_actionTimeAxisAnalysisPCTMode_triggered()
{
Global::_displayTimeValue = ui->actionTimeAxisAnalysisPCTMode->isChecked();
}
void MainWindow::on_actionDegreeOfCuring_triggered()
{
//
_degreeOfCureForm->show();
}
void MainWindow::on_actionAbout_triggered()
{
_aboutForm->show();
}
void MainWindow::on_actionEnthalpyCorrectionEdit_triggered()
{
_enthalpyDataCorrectionForm->show();
}
void MainWindow::on_actionEnthalpyCorrectionSelection_triggered()
{
_coefficientSelectionForm->show();
}
void MainWindow::on_actionPrintPreview_triggered()
{
// _printPreviewForm->show();
_printPreviewForm->setPixmap(_centralWidget->getPixMap());
_printPreviewForm->_customPrintPreviewDialog->showMaximized();
}
void MainWindow::on_actionOnsetTemperaturePoint_triggered()
{
_rightWidget->show();
_centralWidget->setAnalysisMode(CentralWidget::AnalysisMode::OnsetTemperaturePoint);
}
void MainWindow::on_actionEndsetTemperaturePoint_triggered()
{
_rightWidget->show();
_centralWidget->setAnalysisMode(CentralWidget::AnalysisMode::EndsetTemperaturePoint);
}
void MainWindow::on_actionYAxis_triggered()
{
_centralWidget->switchAxisMode();
}
void MainWindow::on_actionAxisSetting_triggered()
{
_axisSettingForm->show();
}
void MainWindow::on_actionSaveData_triggered()
{
saveFile(Global::_experimentInfo.sampleName,Global::_mode);
_leftWidget->reloadFileName();
}
void MainWindow::on_actionSaveas_triggered()
{
saveFile(Global::_experimentInfo.sampleName,Global::Mode::None);
_leftWidget->reloadFileName();
}
void MainWindow::on_actionLanguage_triggered()
{
if(Global::_languageType == Global::LanguageType::Chinese){
Global::_languageType = Global::LanguageType::English;
ui->actionLanguage->setText(Global::EnglishStr);
}else{
Global::_languageType = Global::LanguageType::Chinese;
ui->actionLanguage->setText(Global::ChineseStr);
}
}
void MainWindow::on_actionSmoothness1_triggered()
{
smoothness(1);
}
void MainWindow::on_actionSmoothness2_triggered()
{
smoothness(2);
}
void MainWindow::on_actionSmoothness3_triggered()
{
smoothness(3);
}
void MainWindow::on_actionSmoothness4_triggered()
{
smoothness(4);
}
void MainWindow::on_actionSmoothness5_triggered()
{
smoothness(5);
}
void MainWindow::on_actionSmoothness6_triggered()
{
smoothness(6);
}
void MainWindow::on_actionSmoothness7_triggered()
{
smoothness(7);
}
void MainWindow::on_actionSmoothness8_triggered()
{
smoothness(8);
}
void MainWindow::on_actionSmoothness9_triggered()
{
smoothness(9);
}
void MainWindow::on_actionSmoothness10_triggered()
{
smoothness(10);
}