2025-12-26T17:29:18

This commit is contained in:
yuntang 2025-12-26 17:29:18 +08:00
parent 0583d5f84f
commit 44fc93eb4e
25 changed files with 1266 additions and 683 deletions

View File

@ -5,6 +5,37 @@
"string": "cpp", "string": "cpp",
"string_view": "cpp", "string_view": "cpp",
"deque": "cpp", "deque": "cpp",
"vector": "cpp" "vector": "cpp",
"list": "cpp",
"unordered_map": "cpp",
"unordered_set": "cpp",
"initializer_list": "cpp",
"cmath": "cpp",
"complex": "cpp",
"atomic": "cpp",
"*.tcc": "cpp",
"chrono": "cpp",
"bitset": "cpp",
"exception": "cpp",
"algorithm": "cpp",
"memory": "cpp",
"optional": "cpp",
"type_traits": "cpp",
"utility": "cpp",
"functional": "cpp",
"fstream": "cpp",
"iosfwd": "cpp",
"istream": "cpp",
"limits": "cpp",
"mutex": "cpp",
"new": "cpp",
"ostream": "cpp",
"ratio": "cpp",
"sstream": "cpp",
"streambuf": "cpp",
"system_error": "cpp",
"thread": "cpp",
"tuple": "cpp",
"typeinfo": "cpp"
} }
} }

View File

@ -9,7 +9,7 @@ CONFIG+=precompile_header
PRECOMPILED_HEADER=stable.h PRECOMPILED_HEADER=stable.h
# #
VERSION = 1.4.0 VERSION = 1.3.9
# 设置目标文件名,包含版本号 # 设置目标文件名,包含版本号
TARGET = DSCAnalysisTool_$${VERSION} TARGET = DSCAnalysisTool_$${VERSION}

View File

@ -96,7 +96,10 @@ namespace Global {
QVector<Phase> phaseVtr; QVector<Phase> phaseVtr;
ExperimentInfo() ExperimentInfo()
: sampleName("new"), sampleWeight("0"), date("20250101"), experimentor("experimentor") {} : sampleName("new"),
sampleWeight("0"),
date("20250101"),
experimentor("experimentor") {}
}; };
struct PhaseTotalInfo { struct PhaseTotalInfo {
@ -179,6 +182,7 @@ extern QString _smoothnessFileName;
extern QStringList _fileList; extern QStringList _fileList;
void updateFileList(); void updateFileList();
bool isFileExist(const QString &fileName); bool isFileExist(const QString &fileName);
}; // namespace Global }; // namespace Global

View File

@ -1,7 +1,7 @@
#ifndef LOGGER_H #ifndef LOGGER_H
#define LOGGER_H #define LOGGER_H
#include "easylogging++.h" #include "../thirdparty/easylogging/easylogging++.h"
#define logde LOG(DEBUG) #define logde LOG(DEBUG)
#define loger LOG(ERROR) #define loger LOG(ERROR)
@ -17,4 +17,4 @@ public:
static Logger *instance(); static Logger *instance();
}; };
#endif // LOGGER_H #endif // LOGGER_H

View File

@ -15,7 +15,7 @@
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
// system("chcp 65001"); // system("chcp 65001");
QTextCodec *codec = QTextCodec::codecForName("UTF-8"); QTextCodec *codec = QTextCodec::codecForName("UTF-8");
QTextCodec::setCodecForLocale(codec); QTextCodec::setCodecForLocale(codec);
@ -27,6 +27,7 @@ int main(int argc, char *argv[])
// 启用高DPI支持 // 启用高DPI支持
QApplication::setAttribute(Qt::AA_UseHighDpiPixmaps); QApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
QApplication::setAttribute(Qt::AA_EnableHighDpiScaling); // 启用高DPI缩放 QApplication::setAttribute(Qt::AA_EnableHighDpiScaling); // 启用高DPI缩放
QApplication a(argc, argv); QApplication a(argc, argv);
logde<<"version:"<<a.applicationVersion().toStdString(); logde<<"version:"<<a.applicationVersion().toStdString();

View File

@ -9,107 +9,104 @@
namespace DataParser namespace DataParser
{ {
bool commonDataParser(const QByteArray &ba, CommonData &cd) bool commonDataParser(const QByteArray &ba, CommonData &cd)
{ {
const char *charArray = ba.data(); const char *charArray = ba.data();
// 判断前两个字节是否为 0xA5 和 0x5A (小端格式) // 判断前两个字节是否为 0xA5 和 0x5A (小端格式)
if (static_cast<unsigned char>(charArray[0]) == 0xA5 && if (static_cast<unsigned char>(charArray[0]) == 0xA5 &&
static_cast<unsigned char>(charArray[1]) == 0x5A) static_cast<unsigned char>(charArray[1]) == 0x5A)
{ {
// std::cout << "前两个字节是 0x5AA5 (小端)" << std::endl; // std::cout << "前两个字节是 0x5AA5 (小端)" << std::endl;
} }
else else
{ {
// std::cout << "前两个字节不是 0x5AA5 (小端)" << std::endl; // std::cout << "前两个字节不是 0x5AA5 (小端)" << std::endl;
qDebug() << "header failed."; qDebug() << "header failed.";
return false; return false;
}
if (static_cast<unsigned char>(charArray[3]) != 0x83)
{
qDebug() << "mark failed.";
return false;
}
memcpy(&cd, charArray + 6, sizeof(CommonData));
return true;
} }
if (static_cast<unsigned char>(charArray[3]) != 0x83) QByteArray setExperimentInfo(const QVector<Phase> &vtr, const QByteArray initBa)
{ {
qDebug() << "mark failed."; // const int phaseLength = sizeof(Phase);
return false; const int phaseLength = PHASE_BYTE_SIZE;
const int phaseArrayLength = vtr.size() * phaseLength;
char phaseArray[300] = {};
int offset = 0;
for (const Phase &phase : vtr)
{
memcpy(phaseArray + offset, &phase, sizeof(Phase));
offset += phaseLength;
}
// int totalDataLength = 0;
char totalData[300] = {};
u16 header = 0x5aa5;
memcpy(totalData, (char *)&header, sizeof(u16));
// command + addr + data + crc
totalData[2] = 1 + 2 + phaseArrayLength + 2 + 2;
totalData[3] = 0x82;
u16 address = 0x0050;
memcpy(totalData + 4, (char *)&address, sizeof(u16));
memcpy(totalData + 6, phaseArray, phaseArrayLength);
memcpy(totalData + 6 + phaseArrayLength, initBa.data(), 2);
//
char data[300] = {};
data[0] = 0x82;
// u16 address = 0x0050;
memcpy(data + 1, (char *)&address, sizeof(u16));
memcpy(data + 3, phaseArray, phaseArrayLength);
// initial data
memcpy(data + 3 + phaseArrayLength, initBa.data(), 2);
u16 crc = modbusCRC16((u8 *)data, 3 + phaseArrayLength + 2);
//
memcpy(totalData + 6 + phaseArrayLength + 2, (char *)&crc, sizeof(u16));
// header + phase data + initial data + crc.
return QByteArray(totalData, 6 + phaseArrayLength + 2 + 2);
} }
memcpy(&cd, charArray + 6, sizeof(CommonData)); QByteArray setDeviceStartStop(const DeviceStartMode mode)
return true;
}
QByteArray setExperimentInfo(const QVector<Phase> &vtr,const QByteArray initBa)
{
// const int phaseLength = sizeof(Phase);
const int phaseLength = PHASE_BYTE_SIZE;
const int phaseArrayLength = vtr.size() * phaseLength;
char phaseArray[300] = {};
int offset = 0;
for (const Phase &phase : vtr)
{ {
memcpy(phaseArray + offset, &phase, sizeof(Phase));
offset += phaseLength;
}
//
// int totalDataLength = 0;
char totalData[300] = {};
u16 header = 0x5aa5;
memcpy(totalData, (char *)&header, sizeof(u16));
// command + addr + data + crc
totalData[2] = 1 + 2 + phaseArrayLength + 2 + 2;
totalData[3] = 0x82;
u16 address = 0x0050;
memcpy(totalData + 4, (char *)&address, sizeof(u16));
memcpy(totalData + 6, phaseArray, phaseArrayLength);
memcpy(totalData + 6 + phaseArrayLength,initBa.data(),2);
//
char data[300] = {};
data[0] = 0x82;
// u16 address = 0x0050;
memcpy(data + 1, (char *)&address, sizeof(u16));
memcpy(data + 3, phaseArray, phaseArrayLength);
// initial data
memcpy(data + 3 + phaseArrayLength,initBa.data(),2);
u16 crc = modbusCRC16((u8 *)data, 3 + phaseArrayLength + 2);
//
memcpy(totalData + 6 + phaseArrayLength + 2, (char *)&crc, sizeof(u16));
// header + phase data + initial data + crc.
return QByteArray(totalData, 6 + phaseArrayLength + 2 + 2);
}
QByteArray setDeviceStartStop(const DeviceStartMode mode)
{
#if 1 #if 1
SerialPortProtocol spp; SerialPortProtocol spp;
spp.head = FRANE_HEAD; spp.head = FRANE_HEAD;
spp.len = 1 + 2 + 1 + 2; spp.len = 1 + 2 + 1 + 2;
spp.cmd = WRITE_CMD; spp.cmd = WRITE_CMD;
spp.addr = 0x002c; spp.addr = 0x002c;
spp.data_buf[0] = mode; spp.data_buf[0] = mode;
int sppValidLength = 6 + 1; int sppValidLength = 6 + 1;
u8 *dataPtr = (u8 *)&spp; u8 *dataPtr = (u8 *)&spp;
u16 crc = modbusCRC16((u8 *)(dataPtr + 3), 4); u16 crc = modbusCRC16((u8 *)(dataPtr + 3), 4);
return QByteArray((char *)&spp, sppValidLength) + return QByteArray((char *)&spp, sppValidLength) +
QByteArray((char *)&crc, 2); QByteArray((char *)&crc, 2);
#endif #endif
#if 0 #if 0
@ -138,73 +135,73 @@ QByteArray setDeviceStartStop(const DeviceStartMode mode)
return QByteArray(data,length); return QByteArray(data,length);
#endif #endif
}
void experimentalStateSwitching(const CommonData &cd)
{
// Switch the software mode accord to the serial port data.
switch(cd.run_type){
case DeviceRunStatus::Heat:
case DeviceRunStatus::ConstantTemp:
Global::_mode = Global::Mode::Experiment;
break;
case DeviceRunStatus::Idle:
case DeviceRunStatus::Cooling:
Global::_mode = Global::Mode::Analysis;
break;
default:break;
} }
void experimentalStateSwitching(const CommonData &cd)
{
// Switch the software mode accord to the serial port data.
switch (cd.run_type)
{
case DeviceRunStatus::Heat:
case DeviceRunStatus::ConstantTemp:
Global::_mode = Global::Mode::Experiment;
break;
case DeviceRunStatus::Idle:
case DeviceRunStatus::Cooling:
Global::_mode = Global::Mode::Analysis;
break;
default:
break;
}
#if 0 #if 0
logde<<"phase:"<<(int)cd.current_phase; logde<<"phase:"<<(int)cd.current_phase;
logde<<"run type:"<<(int)cd.run_type; logde<<"run type:"<<(int)cd.run_type;
logde<<"software mode:"<<Global::_mode; logde<<"software mode:"<<Global::_mode;
#endif #endif
} }
unsigned short modbusCRC16(unsigned char *data, unsigned short length) unsigned short modbusCRC16(unsigned char *data, unsigned short length)
{
unsigned short crc = 0xFFFF;
unsigned char i;
for (unsigned short j = 0; j < length; j++)
{ {
crc ^= (unsigned short)data[j]; unsigned short crc = 0xFFFF;
for (i = 0; i < 8; i++) unsigned char i;
for (unsigned short j = 0; j < length; j++)
{ {
if (crc & 0x0001) crc ^= (unsigned short)data[j];
for (i = 0; i < 8; i++)
{ {
crc = (crc >> 1) ^ 0xA001; if (crc & 0x0001)
} {
else crc = (crc >> 1) ^ 0xA001;
{ }
crc = crc >> 1; else
{
crc = crc >> 1;
}
} }
} }
// CRC结果低字节在前高字节在后
return crc;
}
// 请求实验参数
QByteArray inquirePhaseInfo()
{
SerialPortProtocol spp;
spp.head = FRANE_HEAD;
spp.cmd = READ_CMD;
spp.addr = 0x0050;
spp.len = 6;
//
spp.data_buf[0] = PHASE_BYTE_SIZE * 6 + 2;
//
u8 *dataPtr = (u8 *)&spp;
u16 crc = modbusCRC16((u8 *)(dataPtr + 3), 4);
//
int sppValidLength = 6 + 1;
return QByteArray((char *)&spp, sppValidLength) +
QByteArray((char *)&crc, 2);
} }
// CRC结果低字节在前高字节在后
return crc;
}
QByteArray inquirePhaseInfo()
{
SerialPortProtocol spp;
spp.head = FRANE_HEAD;
spp.cmd = READ_CMD;
spp.addr = 0x0050;
spp.len = 6;
//
spp.data_buf[0] = PHASE_BYTE_SIZE * 6 + 2;
//
u8 *dataPtr = (u8 *)&spp;
u16 crc = modbusCRC16((u8 *)(dataPtr + 3), 4);
//
int sppValidLength = 6 + 1;
return QByteArray((char *)&spp, sppValidLength) +
QByteArray((char *)&crc, 2);
}
}; };

View File

@ -21,3 +21,8 @@ unsigned short modbusCRC16(unsigned char *data,unsigned short length);
} }
#endif // DATAPARSER_H #endif // DATAPARSER_H
/**
*/

View File

@ -3,11 +3,11 @@
#include <cstdint> #include <cstdint>
#define FRANE_HEAD 0x5AA5 // #define FRANE_HEAD 0x5AA5 //
#define WRITE_CMD 0x82 //写指令 #define WRITE_CMD 0x82 //写指令
#define READ_CMD 0x83 //读指令 #define READ_CMD 0x83 //读指令
#define PHASE_START_ADDR 0X0050 #define PHASE_START_ADDR 0X0050
#define PHASE_BYTE_SIZE 12 #define PHASE_BYTE_SIZE 12
#pragma pack(push) #pragma pack(push)
@ -35,13 +35,13 @@ typedef struct com_protocol
uint8_t cmd; uint8_t cmd;
uint16_t addr; uint16_t addr;
uint8_t data_buf[256]; uint8_t data_buf[256];
}SerialPortProtocol; } SerialPortProtocol;
typedef enum gas_type { typedef enum gas_type {
NC, NC,
N2, N2,
O2 O2
}GasType; } GasType;
typedef struct control_data typedef struct control_data
{ {
@ -50,7 +50,7 @@ typedef struct control_data
float temp_flow; float temp_flow;
uint16_t constant_temp_time_min; uint16_t constant_temp_time_min;
enum gas_type gas; // uint8_t enum gas_type gas; // uint8_t
}Phase; } Phase;
struct pid_data struct pid_data
{ {
@ -59,6 +59,7 @@ struct pid_data
float kd; float kd;
}; };
#if 0
typedef struct com_data typedef struct com_data
{ {
uint8_t run_type; //0,运行状态 uint8_t run_type; //0,运行状态
@ -99,6 +100,52 @@ typedef struct com_data
float enthalpy_equation_b; //热焓方程式系数b float enthalpy_equation_b; //热焓方程式系数b
float enthalpy_equation_c; //热焓方程式系数c float enthalpy_equation_c; //热焓方程式系数c
} CommonData; } CommonData;
#endif
using rt_uint8_t = uint8_t;
typedef struct com_data
{
rt_uint8_t run_type; //0,运行状态
rt_uint8_t current_phase; //1,当前阶段
float add_run_time; //2,累计运行时间
float add_constan_temp_time; //6,当前阶段恒温时间
double sample_temp; //A,样品温度
double dsc; //12,热流
double temp_flow; //1a,升温速率
float cold_temp; //22,冷端温度
rt_uint8_t hardware_err; //26,硬件错误
rt_uint8_t current_gas; //27,当前气氛
float auto_pid_temp_flow; //28,自整定升温速率
rt_uint8_t run_mode; //2c,启动模式
rt_uint8_t reserve_buf[35]; //2d-4f,保留
struct control_data phase_data[6];//50-97,阶段控制数据
rt_uint8_t meas_type; //98测试类型
rt_uint8_t init_gas; //99, 初始气氛
struct pid_data temp_flow_pid_low;//9a-a5,升温速率 低pid
struct pid_data temp_flow_pid_high;//a6-B1,升温速率 高pid
float cold_temp_cali_standard; //B2,冷端标准温度
float cold_temp_cali_meas; //B6,冷端测量温度
rt_uint8_t cold_cali_flag; //BA,冷端温度计算
float cold_temp_slope; //BB,冷端温度倍率
float sample_temp_calilow_standard;//BF,样品标准温度低倍率
float sample_temp_calilow_meas; //C3,样品测量温度低倍率
rt_uint8_t sample_temp_cali_low_flag;//C7,样品温度计算低倍率
float sample_temp_slope_low; //C8,样品温度低倍率低倍率
float sample_temp_calimid_standard;//CC,样品标准温度中倍率
float sample_temp_calimid_meas; //D0,样品测量温度中倍率
rt_uint8_t sample_temp_cali_mid_flag;//D4,样品温度计算中倍率
float sample_temp_slope_middle; //D5,样品温度中倍率
float sample_temp_calihigh_standard;//D9,样品标准温度高倍率
float sample_temp_calihigh_meas; //DD样品测量温度高倍率
rt_uint8_t sample_temp_cali_high_flag; //E1样品温度计算高倍率
float sample_temp_slope_high; //E2样品温度高倍率
rt_uint8_t cali_data_backup; //E6标定数据备份
float enthalpy_equation_a; //热焓方程式系数a
float enthalpy_equation_b; //热焓方程式系数b
float enthalpy_equation_c; //热焓方程式系数c
}CommonData;
#pragma pack(pop) #pragma pack(pop)

View File

@ -15,16 +15,17 @@
using namespace std; using namespace std;
const u16 conVid = 1155; // 0x0483 const u16 conVid = 1155; // 0x0483
const u16 conPid = 22336; // 0x5740 const u16 conPid = 22336; // 0x5740
SerialPort::SerialPort(QObject *parent) SerialPort::SerialPort(QObject *parent)
: QObject(parent), _sp(new QSerialPort(this)), : QObject(parent), _sp(new QSerialPort(this)),
_portCheckTimer(new QTimer(this)) { _portCheckTimer(new QTimer(this))
{
// //
connect(_portCheckTimer, &QTimer::timeout, connect(_portCheckTimer, &QTimer::timeout,
this, &SerialPort::slotPortCheck); this, &SerialPort::slotPortCheck);
_portCheckTimer->start(1000); // 每秒检测一次 _portCheckTimer->start(1000); // 每秒检测一次
// displayPortInfo(); // displayPortInfo();
@ -77,12 +78,14 @@ SerialPort::SerialPort(QObject *parent)
#endif #endif
} }
SerialPort *SerialPort::instance() { SerialPort *SerialPort::instance()
{
static SerialPort ins; static SerialPort ins;
return &ins; return &ins;
} }
SerialPort::~SerialPort() { SerialPort::~SerialPort()
{
logde << "serialport destructor."; logde << "serialport destructor.";
closeSp(); closeSp();
@ -95,9 +98,11 @@ SerialPort::~SerialPort() {
_portCheckTimer = nullptr; _portCheckTimer = nullptr;
} }
void SerialPort::slotReadData() { void SerialPort::slotReadData()
{
QByteArray ba = _sp->readAll(); QByteArray ba = _sp->readAll();
if (ba.size() == 0) { if (ba.size() == 0)
{
return; return;
} }
@ -107,42 +112,74 @@ void SerialPort::slotReadData() {
#endif #endif
SerialPortProtocol *spp = (SerialPortProtocol *)ba.data(); SerialPortProtocol *spp = (SerialPortProtocol *)ba.data();
if (FRANE_HEAD != spp->head) { if (FRANE_HEAD != spp->head)
{
logde << "Data header error."; logde << "Data header error.";
return; return;
} }
// phase setting data // 实验阶段数据设置
if (spp->addr == PHASE_START_ADDR) { if (spp->addr == PHASE_START_ADDR)
{
emit sigSendPhaseInfo(ba); emit sigSendPhaseInfo(ba);
return; return;
} }
int dataLength = spp->len - 5; int dataLength = spp->len - 5;
// 非实验阶段数据解析
CommonData cd; CommonData cd;
u8 *cdPtr = (u8 *)&cd; u8 *cdPtr = (u8 *)&cd;
memcpy(cdPtr + spp->addr, spp->data_buf, dataLength); memcpy(cdPtr + spp->addr, spp->data_buf, dataLength);
if (WRITE_CMD == spp->cmd) { // 写指令
if (WRITE_CMD == spp->cmd)
{
logde << "write cmd...";
QString hexData = ba.toHex(' '); // ' ' 作为分隔符,可选参数
logde << "receive info (hex):" << hexData.toStdString();
logde << "addr:" << spp->addr;
logde << "init gas type:" << (int)cd.init_gas;
commonDataParser(dataLength, spp->addr, cd); commonDataParser(dataLength, spp->addr, cd);
} else if (READ_CMD == spp->cmd) {
logde << "meas type:" << (int)cd.meas_type;
logde << "init gas:" << (int)cd.init_gas;
if(spp->addr == 0x99){
logde<<"init gas type:"<<(int)spp->data_buf[0];
Global::_experimentInfo.initialAtmosPhere = (GasType)spp->data_buf[0];
}
}
else if (READ_CMD == spp->cmd)
{
// 读指令
// logde<<"read cmd...";
// DataParser::experimentalStateSwitching(cd); // DataParser::experimentalStateSwitching(cd);
updateStatus(cd); updateStatus(cd);
if (spp->addr == 0) { if (spp->addr == 0)
if (Global::Mode::Experiment == Global::_mode) { {
if (Global::Mode::Experiment == Global::_mode)
{
emit sigSendCommonData(cd); emit sigSendCommonData(cd);
} }
// emit sigSendCommonDataToRealDataForm(cd); // emit sigSendCommonDataToRealDataForm(cd);
} else { }
QString hexData = ba.toHex(' '); // ' ' 作为分隔符,可选参数 else
{
QString hexData = ba.toHex(' '); // ' ' 作为分隔符,可选参数
logde << "receive info (hex):" << hexData.toStdString(); logde << "receive info (hex):" << hexData.toStdString();
} }
} }
} }
void SerialPort::updateStatus(const CommonData &cd) { void SerialPort::updateStatus(const CommonData &cd)
{
#if 0 #if 0
// logde<<"phase:"<<(int)cd.current_phase; // logde<<"phase:"<<(int)cd.current_phase;
// logde<<"run type:"<<(int)cd.run_type; // logde<<"run type:"<<(int)cd.run_type;
@ -150,32 +187,37 @@ void SerialPort::updateStatus(const CommonData &cd) {
#endif #endif
// Switch the software mode accord to the serial port data. // Switch the software mode accord to the serial port data.
switch (cd.run_type) { switch (cd.run_type)
case DeviceRunStatus::Heat: {
case DeviceRunStatus::ConstantTemp: case DeviceRunStatus::Heat:
if (Global::_mode != Global::Mode::Experiment) { case DeviceRunStatus::ConstantTemp:
Global::_mode = Global::Mode::Experiment; if (Global::_mode != Global::Mode::Experiment)
} {
break; Global::_mode = Global::Mode::Experiment;
case DeviceRunStatus::Idle: }
case DeviceRunStatus::Cooling: break;
if (Global::_mode != Global::Mode::Analysis) { case DeviceRunStatus::Idle:
Global::_mode = Global::Mode::Analysis; case DeviceRunStatus::Cooling:
} if (Global::_mode != Global::Mode::Analysis)
break; {
default: Global::_mode = Global::Mode::Analysis;
break; }
break;
default:
break;
} }
// 判断是否根据下位机数据,切换软件实验模式。 // 判断是否根据下位机数据,切换软件实验模式。
static Global::Mode preMode = Global::Mode::Analysis; static Global::Mode preMode = Global::Mode::Analysis;
bool sendSaveSignalFlag = false; bool sendSaveSignalFlag = false;
if (Global::_mode != preMode) { if (Global::_mode != preMode)
if (preMode == Global::Mode::Experiment {
&& Global::_mode == Global::Mode::Analysis) { if (preMode == Global::Mode::Experiment && Global::_mode == Global::Mode::Analysis)
{
sendSaveSignalFlag = true; sendSaveSignalFlag = true;
} else if (preMode == Global::Mode::Analysis }
&& Global::_mode == Global::Mode::Experiment) { else if (preMode == Global::Mode::Analysis && Global::_mode == Global::Mode::Experiment)
{
// 根据下位机数据,软件进入实验模式,开始实验。 // 根据下位机数据,软件进入实验模式,开始实验。
logde << "start experiment, accord to device data..."; logde << "start experiment, accord to device data...";
@ -188,8 +230,10 @@ void SerialPort::updateStatus(const CommonData &cd) {
} }
// If phase update, add new phase data to the global param. // If phase update, add new phase data to the global param.
if (Global::_mode == Global::Mode::Experiment) { if (Global::_mode == Global::Mode::Experiment)
if (Global::_currentPhase != (int)cd.current_phase) { {
if (Global::_currentPhase != (int)cd.current_phase)
{
logde << "mode experiment,phase not equeal."; logde << "mode experiment,phase not equeal.";
@ -215,31 +259,35 @@ void SerialPort::updateStatus(const CommonData &cd) {
updateAxis(); updateAxis();
// Update axis. // Update axis.
bool experimentEnded = false; bool experimentEnded = false;
QString devRunModeStr; QString devRunModeStr;
switch (cd.run_type) { switch (cd.run_type)
case DeviceRunStatus::Heat: {
devRunModeStr = "升温"; case DeviceRunStatus::Heat:
experimentEnded = true; devRunModeStr = "升温";
break; experimentEnded = true;
case DeviceRunStatus::ConstantTemp: break;
devRunModeStr = "实验"; case DeviceRunStatus::ConstantTemp:
experimentEnded = true; devRunModeStr = "实验";
break; experimentEnded = true;
case DeviceRunStatus::Idle: break;
case DeviceRunStatus::Cooling: case DeviceRunStatus::Idle:
devRunModeStr = "冷却"; case DeviceRunStatus::Cooling:
experimentEnded = false; devRunModeStr = "冷却";
break; experimentEnded = false;
break; break;
default: break;
break; default:
break;
} }
QString msg; QString msg;
if (experimentEnded) { if (experimentEnded)
{
msg = QString("设备运行状态:%2 实验阶段:%3 实验进行中").arg(devRunModeStr).arg(cd.current_phase); msg = QString("设备运行状态:%2 实验阶段:%3 实验进行中").arg(devRunModeStr).arg(cd.current_phase);
} else { }
else
{
// msg = QString("设备运行状态:%2 实验阶段:%3 实验结束").arg(devRunModeStr).arg(cd.current_phase); // msg = QString("设备运行状态:%2 实验阶段:%3 实验结束").arg(devRunModeStr).arg(cd.current_phase);
msg = QString("设备运行状态:%2 实验结束").arg(devRunModeStr); msg = QString("设备运行状态:%2 实验结束").arg(devRunModeStr);
} }
@ -269,22 +317,30 @@ void SerialPort::updateStatus(const CommonData &cd) {
#endif #endif
// 弹出保存数据对话框。 // 弹出保存数据对话框。
if (sendSaveSignalFlag && !Global::_OITAutoAnalysisModeFlag) { if (sendSaveSignalFlag && !Global::_OITAutoAnalysisModeFlag)
{
emit sigSaveExperimentalDataMsgBox(); emit sigSaveExperimentalDataMsgBox();
} }
} }
// 解析下位机数据,更新全局参数。
void SerialPort::commonDataParser(const int dataLength, const u16 addr, void SerialPort::commonDataParser(const int dataLength, const u16 addr,
const CommonData &cd) { const CommonData &cd)
int localLength = dataLength; {
int localAddr = addr;
int phaseByteSize = sizeof(Phase); int localLength = dataLength;
auto phaseParserFunc = [&](const int index) { int localAddr = addr;
logde << "localLength total:" << localLength;
logde << "localAddr total:" << localAddr;
int phaseByteSize = sizeof(Phase);
auto phaseParserFunc = [&](const int index)
{
Phase phase; Phase phase;
phase.onoff = 1; phase.onoff = 1;
phase.gas = cd.phase_data[index].gas; phase.gas = cd.phase_data[index].gas;
phase.temp_flow = cd.phase_data[index].temp_flow; phase.temp_flow = cd.phase_data[index].temp_flow;
phase.cutoff_temp = cd.phase_data[index].cutoff_temp; phase.cutoff_temp = cd.phase_data[index].cutoff_temp;
phase.constant_temp_time_min = phase.constant_temp_time_min =
cd.phase_data[index].constant_temp_time_min; cd.phase_data[index].constant_temp_time_min;
@ -293,81 +349,103 @@ void SerialPort::commonDataParser(const int dataLength, const u16 addr,
localAddr += phaseByteSize; localAddr += phaseByteSize;
}; };
while (localLength) { logde << "init_gas offset:" << offsetof(CommonData, init_gas);
while (localLength)
{
logde << "localLength:" << localLength; logde << "localLength:" << localLength;
switch (localAddr) { switch (localAddr)
case offsetof(CommonData, run_type): // 运行状态 {
case offsetof(CommonData, run_type): // 运行状态
{
switch (cd.run_type)
{ {
switch (cd.run_type) { case DeviceRunStatus::Cooling:
case DeviceRunStatus::Cooling: // Global::instance()->setMode(Global::Mode::Analysis);
// Global::instance()->setMode(Global::Mode::Analysis); Global::_mode = Global::Mode::Analysis;
Global::_mode = Global::Mode::Analysis; logde << "set global mode analysis.common data parser.";
logde << "set global mode analysis.common data parser.";
break;
default:
break;
}
localAddr += 1;
localLength -= 1;
break;
}
case offsetof(CommonData, current_gas): // 当前气氛
// gas_type_set(dev->temp, msg_data.current_gas);
localAddr += 1;
localLength -= 1;
break;
case offsetof(CommonData, auto_pid_temp_flow): // 自整定升温速率
localAddr += 4;
localLength -= 4;
break;
case offsetof(CommonData, run_mode): {
DeviceStartMode mode = (DeviceStartMode)cd.run_mode;
switch (mode) {
case DeviceStartMode::Stop:
Global::_mode = Global::Mode::Analysis;
logde << "set global mode analysis.";
break;
case DeviceStartMode::Start:
Global::_mode = Global::Mode::Experiment;
break;
default:
break;
}
//
localLength--;
localAddr++;
break;
}
case offsetof(CommonData, phase_data[0].onoff):
phaseParserFunc(0);
break;
case offsetof(CommonData, phase_data[1].onoff):
phaseParserFunc(1);
break;
case offsetof(CommonData, phase_data[2].onoff):
phaseParserFunc(2);
break;
case offsetof(CommonData, phase_data[3].onoff):
phaseParserFunc(3);
break;
case offsetof(CommonData, phase_data[4].onoff):
phaseParserFunc(4);
break;
case offsetof(CommonData, phase_data[5].onoff):
phaseParserFunc(5);
break; break;
default: default:
localLength--;
break; break;
}
localAddr += 1;
localLength -= 1;
break;
}
case offsetof(CommonData, current_gas): // 当前气氛
// gas_type_set(dev->temp, msg_data.current_gas);
localAddr += 1;
localLength -= 1;
break;
case offsetof(CommonData, auto_pid_temp_flow): // 自整定升温速率
localAddr += 4;
localLength -= 4;
break;
case offsetof(CommonData, run_mode):
{
DeviceStartMode mode = (DeviceStartMode)cd.run_mode;
switch (mode)
{
case DeviceStartMode::Stop:
Global::_mode = Global::Mode::Analysis;
logde << "set global mode analysis.";
break;
case DeviceStartMode::Start:
Global::_mode = Global::Mode::Experiment;
break;
default:
break;
}
//
localLength--;
localAddr++;
break;
}
case offsetof(CommonData, phase_data[0].onoff):
phaseParserFunc(0);
break;
case offsetof(CommonData, phase_data[1].onoff):
phaseParserFunc(1);
break;
case offsetof(CommonData, phase_data[2].onoff):
phaseParserFunc(2);
break;
case offsetof(CommonData, phase_data[3].onoff):
phaseParserFunc(3);
break;
case offsetof(CommonData, phase_data[4].onoff):
phaseParserFunc(4);
break;
case offsetof(CommonData, phase_data[5].onoff):
phaseParserFunc(5);
break;
// 测试类型
case offsetof(CommonData, meas_type):
logde << "meas_type:" << cd.meas_type;
localLength--;
localAddr++;
break;
// 初始气氛
case offsetof(CommonData, init_gas):
logde << "init_gas:" << cd.init_gas;
localLength--;
localAddr++;
break;
default:
localLength--;
break;
}; };
} }
} }
bool SerialPort::openSp() { bool SerialPort::openSp()
{
logde << "openSp 1"; logde << "openSp 1";
closeSp(); closeSp();
QThread::msleep(100); QThread::msleep(100);
@ -379,17 +457,20 @@ bool SerialPort::openSp() {
#endif #endif
logde << "openSp 2"; logde << "openSp 2";
foreach (const QSerialPortInfo &info, QSerialPortInfo::availablePorts()) { foreach (const QSerialPortInfo &info, QSerialPortInfo::availablePorts())
{
u16 pid = info.productIdentifier(); u16 pid = info.productIdentifier();
u16 vid = info.vendorIdentifier(); u16 vid = info.vendorIdentifier();
if ((pid == conPid) && (vid == conVid)) { if ((pid == conPid) && (vid == conVid))
{
_sp->setPort(info); _sp->setPort(info);
break; break;
} }
} }
logde << "openSp 3"; logde << "openSp 3";
if (_sp == nullptr) { if (_sp == nullptr)
{
qDebug() << "Device not found."; qDebug() << "Device not found.";
return false; return false;
} }
@ -397,10 +478,10 @@ bool SerialPort::openSp() {
// 设置波特率和读写方向 // 设置波特率和读写方向
_sp->setBaudRate(QSerialPort::Baud115200, _sp->setBaudRate(QSerialPort::Baud115200,
QSerialPort::AllDirections); QSerialPort::AllDirections);
_sp->setDataBits(QSerialPort::Data8); // 数据位为8位 _sp->setDataBits(QSerialPort::Data8); // 数据位为8位
_sp->setFlowControl(QSerialPort::NoFlowControl); // 无流控制 _sp->setFlowControl(QSerialPort::NoFlowControl); // 无流控制
_sp->setParity(QSerialPort::NoParity); // 无校验位 _sp->setParity(QSerialPort::NoParity); // 无校验位
_sp->setStopBits(QSerialPort::OneStop); // 一位停止位 _sp->setStopBits(QSerialPort::OneStop); // 一位停止位
// 4.连接信号槽 // 4.连接信号槽
connect(_sp, &QSerialPort::readyRead, connect(_sp, &QSerialPort::readyRead,
@ -408,10 +489,13 @@ bool SerialPort::openSp() {
logde << "openSp 4"; logde << "openSp 4";
// 2.打开串口 // 2.打开串口
if (!_sp->open(QIODevice::ReadWrite)) { if (!_sp->open(QIODevice::ReadWrite))
{
qDebug() << "open failed." << _sp->error(); qDebug() << "open failed." << _sp->error();
return false; return false;
} else { }
else
{
// qDebug() << "open succ."; // qDebug() << "open succ.";
logde << "openSp 5."; logde << "openSp 5.";
// 设置 DTR 信号为就绪状态true 表示低电平) // 设置 DTR 信号为就绪状态true 表示低电平)
@ -422,29 +506,37 @@ bool SerialPort::openSp() {
return true; return true;
} }
bool SerialPort::closeSp() { bool SerialPort::closeSp()
if (_sp && _sp->isOpen()) { {
if (_sp && _sp->isOpen())
{
_sp->clear(); _sp->clear();
_sp->close(); _sp->close();
} }
} }
void SerialPort::sendCmd(const SerialPort::E_CMD_TYPE e) { void SerialPort::sendCmd(const SerialPort::E_CMD_TYPE e)
{
#if 1 #if 1
int length = 20; int length = 20;
char in_char[21] = { '\0' }; char in_char[21] = {'\0'};
if (e == e_zero) { if (e == e_zero)
{
// char data[10] = {'55','aa','0b','0a','20', // char data[10] = {'55','aa','0b','0a','20',
// '4e','00','00','00','c3'}; // '4e','00','00','00','c3'};
const char *data = "55aa0b0a204e000000c3"; const char *data = "55aa0b0a204e000000c3";
memcpy(in_char, data, length); memcpy(in_char, data, length);
} else if (e == e_back) { }
else if (e == e_back)
{
// char data[10] = {'55','aa','08','10','27', // char data[10] = {'55','aa','08','10','27',
// 'f0','d8','ff','ff','c3'}; // 'f0','d8','ff','ff','c3'};
const char *data = "55aa081027f0d8ffffc3"; const char *data = "55aa081027f0d8ffffc3";
memcpy(in_char, data, length); memcpy(in_char, data, length);
} else if (e == e_forward) { }
else if (e == e_forward)
{
// char data[10] = {'55','aa','08','10','27', // char data[10] = {'55','aa','08','10','27',
// '10','27','00','00','c3'}; // '10','27','00','00','c3'};
const char *data = "55aa08102710270000c3"; const char *data = "55aa08102710270000c3";
@ -454,21 +546,26 @@ void SerialPort::sendCmd(const SerialPort::E_CMD_TYPE e) {
#endif #endif
// char in_char[] = "55aa0b0a204e000000c3"; // char in_char[] = "55aa0b0a204e000000c3";
char out_char[21] = { '\0' }; char out_char[21] = {'\0'};
int hex_length = 10; int hex_length = 10;
toHex(in_char, hex_length, out_char); toHex(in_char, hex_length, out_char);
int num = _sp->write(out_char, int num = _sp->write(out_char,
hex_length); hex_length);
if (num == -1) { if (num == -1)
{
qDebug() << "write failed."; qDebug() << "write failed.";
} else { }
else
{
qDebug() << "write ok|num:" << num; qDebug() << "write ok|num:" << num;
} }
} }
void SerialPort::toHex(char *in_char, int char_length, char *out_char) { void SerialPort::toHex(char *in_char, int char_length, char *out_char)
while (char_length--) { {
while (char_length--)
{
*out_char = (*in_char & 0x40 ? *in_char + 9 : *in_char) << 4; *out_char = (*in_char & 0x40 ? *in_char + 9 : *in_char) << 4;
++in_char; ++in_char;
*out_char |= (*in_char & 0x40 ? *in_char + 9 : *in_char) & 0xF; *out_char |= (*in_char & 0x40 ? *in_char + 9 : *in_char) & 0xF;
@ -477,12 +574,14 @@ void SerialPort::toHex(char *in_char, int char_length, char *out_char) {
} }
} }
void SerialPort::displayPortInfo() { void SerialPort::displayPortInfo()
{
// 获取系统中所有可用的串口信息 // 获取系统中所有可用的串口信息
QList<QSerialPortInfo> serialPorts = QSerialPortInfo::availablePorts(); QList<QSerialPortInfo> serialPorts = QSerialPortInfo::availablePorts();
// 遍历每个串口信息 // 遍历每个串口信息
for (const QSerialPortInfo &portInfo : serialPorts) { for (const QSerialPortInfo &portInfo : serialPorts)
{
qDebug() << "================================================"; qDebug() << "================================================";
// 打印串口的名称 // 打印串口的名称
qDebug() << "串口名称: " << portInfo.portName(); qDebug() << "串口名称: " << portInfo.portName();
@ -499,14 +598,16 @@ void SerialPort::displayPortInfo() {
// 打印是否有产品标识符 // 打印是否有产品标识符
qDebug() << "是否有产品标识符: " << (portInfo.hasProductIdentifier() ? "" : ""); qDebug() << "是否有产品标识符: " << (portInfo.hasProductIdentifier() ? "" : "");
// 如果有虚拟调制解调器,打印其标识符 // 如果有虚拟调制解调器,打印其标识符
if (portInfo.hasVendorIdentifier()) { if (portInfo.hasVendorIdentifier())
{
qint16 vid = portInfo.vendorIdentifier(); qint16 vid = portInfo.vendorIdentifier();
qDebug() << "虚拟调制解调器标识符: " << vid; qDebug() << "虚拟调制解调器标识符: " << vid;
QString hexStr = QString("0x%1").arg(vid, 4, 16, QChar('0')).toUpper(); QString hexStr = QString("0x%1").arg(vid, 4, 16, QChar('0')).toUpper();
qDebug() << "vid 0x" << hexStr; qDebug() << "vid 0x" << hexStr;
} }
// 如果有产品标识符,打印其标识符 // 如果有产品标识符,打印其标识符
if (portInfo.hasProductIdentifier()) { if (portInfo.hasProductIdentifier())
{
qint16 pid = portInfo.productIdentifier(); qint16 pid = portInfo.productIdentifier();
qDebug() << "产品标识符: " << pid; qDebug() << "产品标识符: " << pid;
QString hexStr = QString("0x%1").arg(pid, 4, 16, QChar('0')).toUpper(); QString hexStr = QString("0x%1").arg(pid, 4, 16, QChar('0')).toUpper();
@ -515,29 +616,34 @@ void SerialPort::displayPortInfo() {
} }
} }
void SerialPort::updateAxis() { void SerialPort::updateAxis()
static Global::Mode previousMode = Global::Analysis; // 记录上一次的模式 {
static Global::Mode previousMode = Global::Analysis; // 记录上一次的模式
if (previousMode == Global::Analysis && Global::_mode == Global::Experiment) { if (previousMode == Global::Analysis && Global::_mode == Global::Experiment)
{
// std::cout << "Mode has changed from Analysis to Experiment!" << std::endl; // std::cout << "Mode has changed from Analysis to Experiment!" << std::endl;
Global::ExperimentInfo &eti = Global::_experimentInfo; Global::ExperimentInfo &eti = Global::_experimentInfo;
if (eti.phaseVtr.size() > 0) { if (eti.phaseVtr.size() > 0)
{
logde << "serialport set axis."; logde << "serialport set axis.";
float temp = eti.phaseVtr.at(0).cutoff_temp; float temp = eti.phaseVtr.at(0).cutoff_temp;
emit sigAxisModify(temp); emit sigAxisModify(temp);
} }
} }
if (previousMode != Global::_mode) { if (previousMode != Global::_mode)
{
previousMode = Global::_mode; previousMode = Global::_mode;
} }
} }
void SerialPort::parserTest() { void SerialPort::parserTest()
const uchar data[] = { 0xa5, 0x5a, 0x2d, 0x83, {
0x00, 0x00, const uchar data[] = {0xa5, 0x5a, 0x2d, 0x83,
0x00, 0x01, 0x23, 0x23, 0x00, 0x00,
0x23, 0x23, 0x23, 0x23, 0x23, 0x00, 0x01, 0x23, 0x23,
0x23, 0x07, 0xbc, 0xb5, 0xf2, 0xc8, 0x57, 0x38, 0x40, 0x1b, 0x63, 0x27, 0xbc, 0x04, 0xa7, 0xf2, 0x3f, 0x55, 0x55, 0x55, 0xd5, 0x04, 0xf3, 0xab, 0xbf, 0xfa, 0x2b, 0xcd, 0x41, 0x00, 0x00, 0x93, 0xba }; 0x23, 0x23, 0x23, 0x23, 0x23,
0x23, 0x07, 0xbc, 0xb5, 0xf2, 0xc8, 0x57, 0x38, 0x40, 0x1b, 0x63, 0x27, 0xbc, 0x04, 0xa7, 0xf2, 0x3f, 0x55, 0x55, 0x55, 0xd5, 0x04, 0xf3, 0xab, 0xbf, 0xfa, 0x2b, 0xcd, 0x41, 0x00, 0x00, 0x93, 0xba};
CommonData *serialPortData = nullptr; CommonData *serialPortData = nullptr;
qDebug() << "data length:" << sizeof(data) / sizeof(uchar); qDebug() << "data length:" << sizeof(data) / sizeof(uchar);
@ -572,49 +678,64 @@ void SerialPort::parserTest() {
#endif #endif
} }
void SerialPort::slotDeliverData(const QByteArray &ba) { void SerialPort::slotDeliverData(const QByteArray &ba)
{
openSp(); openSp();
slotSendData(ba); slotSendData(ba);
} }
void SerialPort::slotSendData(const QByteArray &ba) { void SerialPort::slotSendData(const QByteArray &ba)
{
#if 1 #if 1
logde << "slotSendData =========================="; logde << "slotSendData ==========================";
logde << "slotSendData:" << ba.size(); logde << "slotSendData:" << ba.size();
QString hexData = ba.toHex(' '); // ' ' 作为分隔符,可选参数 QString hexData = ba.toHex(' '); // ' ' 作为分隔符,可选参数
logde << "slotSendData:" << hexData.toStdString(); logde << "slotSendData:" << hexData.toStdString();
#endif #endif
if (_sp != nullptr && _sp->isOpen()) { if (_sp != nullptr && _sp->isOpen())
{
int bytesWritten = _sp->write(ba); int bytesWritten = _sp->write(ba);
if (bytesWritten == -1) { if (bytesWritten == -1)
{
logde << "Write failed." << _sp->errorString().toStdString(); logde << "Write failed." << _sp->errorString().toStdString();
} else if (bytesWritten != ba.size()) { }
else if (bytesWritten != ba.size())
{
logde << "Not all data was writen."; logde << "Not all data was writen.";
} else { }
else
{
logde << "All data writen."; logde << "All data writen.";
} }
} else { }
else
{
logde << "sp not open."; logde << "sp not open.";
return; return;
} }
} }
void SerialPort::slotCloseSp() { void SerialPort::slotCloseSp()
if (_sp != nullptr && _sp->isOpen()) { {
if (_sp != nullptr && _sp->isOpen())
{
_sp->close(); _sp->close();
} }
} }
void SerialPort::slotPortCheck() { void SerialPort::slotPortCheck()
// logde<<"slotPortCheck..."; {
// logde<<"slotPortCheck...";
foreach (const QSerialPortInfo &info, QSerialPortInfo::availablePorts()) { foreach (const QSerialPortInfo &info, QSerialPortInfo::availablePorts())
{
u16 pid = info.productIdentifier(); u16 pid = info.productIdentifier();
u16 vid = info.vendorIdentifier(); u16 vid = info.vendorIdentifier();
if ((pid == conPid) && (vid == conVid)) { if ((pid == conPid) && (vid == conVid))
// logde<<"slotPortCheck... device connected."; {
// logde<<"slotPortCheck... device connected.";
return; return;
} }
} }
@ -622,5 +743,5 @@ void SerialPort::slotPortCheck() {
// logde<<"device disconnected."; // logde<<"device disconnected.";
emit sigDeviceDisconnected(); emit sigDeviceDisconnected();
// logde<<"slotPortCheck... device disconnected."; // logde<<"slotPortCheck... device disconnected.";
} }

View File

@ -10,15 +10,17 @@
#include "filemanager.h" #include "filemanager.h"
#include "logger.h" #include "logger.h"
QString extractObjectName(const QString &fullObjectName) { QString extractObjectName(const QString &fullObjectName)
return fullObjectName.mid(4); // 去掉前 4 个字符("ui->" {
return fullObjectName.mid(4); // 去掉前 4 个字符("ui->"
} }
#define SET_OBJECT_NAME(WIDGET) \ #define SET_OBJECT_NAME(WIDGET) \
WIDGET->setObjectName(extractObjectName(#WIDGET)) WIDGET->setObjectName(extractObjectName(#WIDGET))
ExperimentSettingForm::ExperimentSettingForm(QWidget *parent) : QWidget(parent), ExperimentSettingForm::ExperimentSettingForm(QWidget *parent) : QWidget(parent),
ui(new Ui::ExperimentSettingForm) { ui(new Ui::ExperimentSettingForm)
{
ui->setupUi(this); ui->setupUi(this);
ui->sampleNameLineEdit->setText("new"); ui->sampleNameLineEdit->setText("new");
@ -52,11 +54,13 @@ ExperimentSettingForm::ExperimentSettingForm(QWidget *parent) : QWidget(parent),
this, &ExperimentSettingForm::slotCancel); this, &ExperimentSettingForm::slotCancel);
} }
ExperimentSettingForm::~ExperimentSettingForm() { ExperimentSettingForm::~ExperimentSettingForm()
{
delete ui; delete ui;
} }
void ExperimentSettingForm::uiReset() { void ExperimentSettingForm::uiReset()
{
// init data and status. // init data and status.
// default value // default value
@ -164,84 +168,90 @@ void ExperimentSettingForm::uiReset() {
SET_OBJECT_NAME(ui->comboBox_initial_atmosphere); SET_OBJECT_NAME(ui->comboBox_initial_atmosphere);
} }
void ExperimentSettingForm::uiSetPhaseEnable(const int index) { void ExperimentSettingForm::uiSetPhaseEnable(const int index)
switch (index) { {
case 1: switch (index)
ui->checkBox_phase_1->setTristate(true); {
ui->phase_1_cutoff_temp->setEnabled(true); case 1:
ui->phase_1_scan_rate->setEnabled(true); ui->checkBox_phase_1->setTristate(true);
ui->phase_1_constant_temp->setEnabled(true); ui->phase_1_cutoff_temp->setEnabled(true);
ui->comboBox_phase_1_atmosphere->setEnabled(true); ui->phase_1_scan_rate->setEnabled(true);
break; ui->phase_1_constant_temp->setEnabled(true);
case 2: ui->comboBox_phase_1_atmosphere->setEnabled(true);
ui->checkBox_phase_2->setTristate(true); break;
ui->phase_2_cutoff_temp->setEnabled(true); case 2:
ui->phase_2_scan_rate->setEnabled(true); ui->checkBox_phase_2->setTristate(true);
ui->phase_3_constant_temp->setEnabled(true); ui->phase_2_cutoff_temp->setEnabled(true);
ui->comboBox_phase_1_atmosphere->setEnabled(true); ui->phase_2_scan_rate->setEnabled(true);
break; ui->phase_3_constant_temp->setEnabled(true);
case 3: ui->comboBox_phase_1_atmosphere->setEnabled(true);
ui->checkBox_phase_1->setTristate(true); break;
ui->phase_1_cutoff_temp->setEnabled(true); case 3:
ui->phase_1_scan_rate->setEnabled(true); ui->checkBox_phase_1->setTristate(true);
ui->phase_1_constant_temp->setEnabled(true); ui->phase_1_cutoff_temp->setEnabled(true);
ui->comboBox_phase_1_atmosphere->setEnabled(true); ui->phase_1_scan_rate->setEnabled(true);
break; ui->phase_1_constant_temp->setEnabled(true);
case 4: ui->comboBox_phase_1_atmosphere->setEnabled(true);
ui->checkBox_phase_1->setTristate(true); break;
ui->phase_1_cutoff_temp->setEnabled(true); case 4:
ui->phase_1_scan_rate->setEnabled(true); ui->checkBox_phase_1->setTristate(true);
ui->phase_1_constant_temp->setEnabled(true); ui->phase_1_cutoff_temp->setEnabled(true);
ui->comboBox_phase_1_atmosphere->setEnabled(true); ui->phase_1_scan_rate->setEnabled(true);
break; ui->phase_1_constant_temp->setEnabled(true);
case 5: ui->comboBox_phase_1_atmosphere->setEnabled(true);
ui->checkBox_phase_1->setTristate(true); break;
ui->phase_1_cutoff_temp->setEnabled(true); case 5:
ui->phase_1_scan_rate->setEnabled(true); ui->checkBox_phase_1->setTristate(true);
ui->phase_1_constant_temp->setEnabled(true); ui->phase_1_cutoff_temp->setEnabled(true);
ui->comboBox_phase_1_atmosphere->setEnabled(true); ui->phase_1_scan_rate->setEnabled(true);
break; ui->phase_1_constant_temp->setEnabled(true);
case 6: ui->comboBox_phase_1_atmosphere->setEnabled(true);
ui->checkBox_phase_1->setTristate(true); break;
ui->phase_1_cutoff_temp->setEnabled(true); case 6:
ui->phase_1_scan_rate->setEnabled(true); ui->checkBox_phase_1->setTristate(true);
ui->phase_1_constant_temp->setEnabled(true); ui->phase_1_cutoff_temp->setEnabled(true);
ui->comboBox_phase_1_atmosphere->setEnabled(true); ui->phase_1_scan_rate->setEnabled(true);
break; ui->phase_1_constant_temp->setEnabled(true);
default: ui->comboBox_phase_1_atmosphere->setEnabled(true);
break; break;
default:
break;
} }
} }
GasType ExperimentSettingForm::conver2GasType(const int index) { GasType ExperimentSettingForm::conver2GasType(const int index)
switch (index) { {
case 0: switch (index)
return GasType::NC; {
break; // 假设 GAS_AIR 是 gas_type 的枚举值 case 0:
case 1: return GasType::NC;
return GasType::N2; break; // 假设 GAS_AIR 是 gas_type 的枚举值
break; case 1:
case 2: return GasType::N2;
return GasType::O2; break;
break; case 2:
default: return GasType::O2;
return GasType::NC; break;
break; // 处理未知情况 default:
return GasType::NC;
break; // 处理未知情况
} }
return GasType::NC; return GasType::NC;
} }
bool ExperimentSettingForm::phaseCufoffTempAndTempFlowCheck(const int phaseIndex, bool ExperimentSettingForm::phaseCufoffTempAndTempFlowCheck(const int phaseIndex,
const float prePhaseCufoffTemp, const float prePhaseCufoffTemp,
const float currentPhaseCufoffTemp, const float currentPhaseCufoffTemp,
const float tempFlow) { const float tempFlow)
if (tempFlow < 0) { {
if (tempFlow < 0)
{
phaseScanRateErrorMesgBox(phaseIndex); phaseScanRateErrorMesgBox(phaseIndex);
return false; return false;
} }
if (prePhaseCufoffTemp != currentPhaseCufoffTemp if (prePhaseCufoffTemp != currentPhaseCufoffTemp && tempFlow == 0)
&& tempFlow == 0) { {
phaseScanRateErrorMesgBox(phaseIndex); phaseScanRateErrorMesgBox(phaseIndex);
return false; return false;
} }
@ -249,19 +259,26 @@ bool ExperimentSettingForm::phaseCufoffTempAndTempFlowCheck(const int phaseInd
return true; return true;
} }
void ExperimentSettingForm::slotPhase2StateChanged(int state) { void ExperimentSettingForm::slotPhase2StateChanged(int state)
{
qDebug() << "slotPhase2StateChanged:" << state; qDebug() << "slotPhase2StateChanged:" << state;
if (state == Qt::PartiallyChecked) { if (state == Qt::PartiallyChecked)
{
ui->phase_2_cutoff_temp->setEnabled(true); ui->phase_2_cutoff_temp->setEnabled(true);
ui->phase_2_scan_rate->setEnabled(true); ui->phase_2_scan_rate->setEnabled(true);
ui->phase_2_constant_temp->setEnabled(true); ui->phase_2_constant_temp->setEnabled(true);
ui->comboBox_phase_2_atmosphere->setEnabled(true); ui->comboBox_phase_2_atmosphere->setEnabled(true);
} else { }
else
{
// unchecked // unchecked
if (ui->checkBox_phase_3->isChecked()) { if (ui->checkBox_phase_3->isChecked())
{
ui->checkBox_phase_2->setChecked(true); ui->checkBox_phase_2->setChecked(true);
} else { }
else
{
ui->phase_2_cutoff_temp->setEnabled(false); ui->phase_2_cutoff_temp->setEnabled(false);
ui->phase_2_scan_rate->setEnabled(false); ui->phase_2_scan_rate->setEnabled(false);
ui->phase_2_constant_temp->setEnabled(false); ui->phase_2_constant_temp->setEnabled(false);
@ -270,20 +287,30 @@ void ExperimentSettingForm::slotPhase2StateChanged(int state) {
} }
} }
void ExperimentSettingForm::slotPhase3StateChanged(int state) { void ExperimentSettingForm::slotPhase3StateChanged(int state)
if (state == Qt::PartiallyChecked) { {
if (ui->checkBox_phase_2->isChecked()) { if (state == Qt::PartiallyChecked)
{
if (ui->checkBox_phase_2->isChecked())
{
ui->phase_3_cutoff_temp->setEnabled(true); ui->phase_3_cutoff_temp->setEnabled(true);
ui->phase_3_scan_rate->setEnabled(true); ui->phase_3_scan_rate->setEnabled(true);
ui->phase_3_constant_temp->setEnabled(true); ui->phase_3_constant_temp->setEnabled(true);
ui->comboBox_phase_3_atmosphere->setEnabled(true); ui->comboBox_phase_3_atmosphere->setEnabled(true);
} else { }
else
{
ui->checkBox_phase_3->setChecked(false); ui->checkBox_phase_3->setChecked(false);
} }
} else { }
if (ui->checkBox_phase_4->isChecked()) { else
{
if (ui->checkBox_phase_4->isChecked())
{
ui->checkBox_phase_3->setChecked(true); ui->checkBox_phase_3->setChecked(true);
} else { }
else
{
ui->phase_3_cutoff_temp->setEnabled(false); ui->phase_3_cutoff_temp->setEnabled(false);
ui->phase_3_scan_rate->setEnabled(false); ui->phase_3_scan_rate->setEnabled(false);
ui->phase_3_constant_temp->setEnabled(false); ui->phase_3_constant_temp->setEnabled(false);
@ -292,20 +319,30 @@ void ExperimentSettingForm::slotPhase3StateChanged(int state) {
} }
} }
void ExperimentSettingForm::slotPhase4StateChanged(int state) { void ExperimentSettingForm::slotPhase4StateChanged(int state)
if (state == Qt::PartiallyChecked) { {
if (ui->checkBox_phase_3->isChecked()) { if (state == Qt::PartiallyChecked)
{
if (ui->checkBox_phase_3->isChecked())
{
ui->phase_4_cutoff_temp->setEnabled(true); ui->phase_4_cutoff_temp->setEnabled(true);
ui->phase_4_scan_rate->setEnabled(true); ui->phase_4_scan_rate->setEnabled(true);
ui->phase_4_constant_temp->setEnabled(true); ui->phase_4_constant_temp->setEnabled(true);
ui->comboBox_phase_4_atmosphere->setEnabled(true); ui->comboBox_phase_4_atmosphere->setEnabled(true);
} else { }
else
{
ui->checkBox_phase_4->setChecked(false); ui->checkBox_phase_4->setChecked(false);
} }
} else { }
if (ui->checkBox_phase_5->isChecked()) { else
{
if (ui->checkBox_phase_5->isChecked())
{
ui->checkBox_phase_4->setChecked(true); ui->checkBox_phase_4->setChecked(true);
} else { }
else
{
ui->phase_4_cutoff_temp->setEnabled(false); ui->phase_4_cutoff_temp->setEnabled(false);
ui->phase_4_scan_rate->setEnabled(false); ui->phase_4_scan_rate->setEnabled(false);
ui->phase_4_constant_temp->setEnabled(false); ui->phase_4_constant_temp->setEnabled(false);
@ -314,20 +351,30 @@ void ExperimentSettingForm::slotPhase4StateChanged(int state) {
} }
} }
void ExperimentSettingForm::slotPhase5StateChanged(int state) { void ExperimentSettingForm::slotPhase5StateChanged(int state)
if (state == Qt::PartiallyChecked) { {
if (ui->checkBox_phase_4->isChecked()) { if (state == Qt::PartiallyChecked)
{
if (ui->checkBox_phase_4->isChecked())
{
ui->phase_5_cutoff_temp->setEnabled(true); ui->phase_5_cutoff_temp->setEnabled(true);
ui->phase_5_scan_rate->setEnabled(true); ui->phase_5_scan_rate->setEnabled(true);
ui->phase_5_constant_temp->setEnabled(true); ui->phase_5_constant_temp->setEnabled(true);
ui->comboBox_phase_5_atmosphere->setEnabled(true); ui->comboBox_phase_5_atmosphere->setEnabled(true);
} else { }
else
{
ui->checkBox_phase_5->setChecked(false); ui->checkBox_phase_5->setChecked(false);
} }
} else { }
if (ui->checkBox_phase_6->isChecked()) { else
{
if (ui->checkBox_phase_6->isChecked())
{
ui->checkBox_phase_5->setChecked(true); ui->checkBox_phase_5->setChecked(true);
} else { }
else
{
ui->phase_5_cutoff_temp->setEnabled(false); ui->phase_5_cutoff_temp->setEnabled(false);
ui->phase_5_scan_rate->setEnabled(false); ui->phase_5_scan_rate->setEnabled(false);
ui->phase_5_constant_temp->setEnabled(false); ui->phase_5_constant_temp->setEnabled(false);
@ -336,27 +383,35 @@ void ExperimentSettingForm::slotPhase5StateChanged(int state) {
} }
} }
void ExperimentSettingForm::slotPhase6StateChanged(int state) { void ExperimentSettingForm::slotPhase6StateChanged(int state)
{
qDebug() << "slotPhase2StateChanged:" << state; qDebug() << "slotPhase2StateChanged:" << state;
if (state == Qt::PartiallyChecked) { if (state == Qt::PartiallyChecked)
if (ui->checkBox_phase_5->isChecked()) { {
if (ui->checkBox_phase_5->isChecked())
{
ui->phase_6_cutoff_temp->setEnabled(true); ui->phase_6_cutoff_temp->setEnabled(true);
ui->phase_6_scan_rate->setEnabled(true); ui->phase_6_scan_rate->setEnabled(true);
ui->phase_6_constant_temp->setEnabled(true); ui->phase_6_constant_temp->setEnabled(true);
ui->comboBox_phase_6_atmosphere->setEnabled(true); ui->comboBox_phase_6_atmosphere->setEnabled(true);
} else { }
else
{
ui->checkBox_phase_6->setChecked(false); ui->checkBox_phase_6->setChecked(false);
} }
} else { }
else
{
ui->phase_6_cutoff_temp->setEnabled(false); ui->phase_6_cutoff_temp->setEnabled(false);
ui->phase_6_scan_rate->setEnabled(false); ui->phase_6_scan_rate->setEnabled(false);
ui->phase_6_constant_temp->setEnabled(false); ui->phase_6_constant_temp->setEnabled(false);
ui->comboBox_phase_6_atmosphere->setEnabled(false); ui->comboBox_phase_6_atmosphere->setEnabled(false);
} }
} }
// 发布数据
void ExperimentSettingForm::on_pushButton_deliverData_clicked() { void ExperimentSettingForm::on_pushButton_deliverData_clicked()
{
float phase1CutoffTemp = 0.0; float phase1CutoffTemp = 0.0;
float phase2CutoffTemp = 0.0; float phase2CutoffTemp = 0.0;
float phase3CutoffTemp = 0.0; float phase3CutoffTemp = 0.0;
@ -367,9 +422,9 @@ void ExperimentSettingForm::on_pushButton_deliverData_clicked() {
QVector<Phase> phaseVtr; QVector<Phase> phaseVtr;
{ {
Phase phase; Phase phase;
phase.onoff = ui->checkBox_phase_1->checkState() ? 1 : 0; phase.onoff = ui->checkBox_phase_1->checkState() ? 1 : 0;
phase.cutoff_temp = ui->phase_1_cutoff_temp->text().toFloat(); phase.cutoff_temp = ui->phase_1_cutoff_temp->text().toFloat();
phase.temp_flow = ui->phase_1_scan_rate->text().toFloat(); phase.temp_flow = ui->phase_1_scan_rate->text().toFloat();
phase.constant_temp_time_min = (uint16_t)ui->phase_1_constant_temp->text().toInt(); phase.constant_temp_time_min = (uint16_t)ui->phase_1_constant_temp->text().toInt();
phase.gas = conver2GasType(ui->comboBox_phase_1_atmosphere->currentIndex()); phase.gas = conver2GasType(ui->comboBox_phase_1_atmosphere->currentIndex());
@ -378,7 +433,8 @@ void ExperimentSettingForm::on_pushButton_deliverData_clicked() {
// //
phase1CutoffTemp = phase.cutoff_temp; phase1CutoffTemp = phase.cutoff_temp;
// //
if (phase.temp_flow <= 0) { if (phase.temp_flow <= 0)
{
phaseScanRateErrorMesgBox(1); phaseScanRateErrorMesgBox(1);
return; return;
} }
@ -386,18 +442,20 @@ void ExperimentSettingForm::on_pushButton_deliverData_clicked() {
{ {
Phase phase; Phase phase;
phase.onoff = ui->checkBox_phase_2->checkState() ? 1 : 0; phase.onoff = ui->checkBox_phase_2->checkState() ? 1 : 0;
phase.cutoff_temp = ui->phase_2_cutoff_temp->text().toFloat(); phase.cutoff_temp = ui->phase_2_cutoff_temp->text().toFloat();
phase.temp_flow = ui->phase_2_scan_rate->text().toFloat(); phase.temp_flow = ui->phase_2_scan_rate->text().toFloat();
phase.constant_temp_time_min = (uint16_t)ui->phase_2_constant_temp->text().toInt(); phase.constant_temp_time_min = (uint16_t)ui->phase_2_constant_temp->text().toInt();
phase.gas = conver2GasType(ui->comboBox_phase_2_atmosphere->currentIndex()); phase.gas = conver2GasType(ui->comboBox_phase_2_atmosphere->currentIndex());
phaseVtr.push_back(phase); phaseVtr.push_back(phase);
// //
if (phase.onoff) { if (phase.onoff)
{
logde << "phase 2 enable."; logde << "phase 2 enable.";
phase2CutoffTemp = phase.cutoff_temp; phase2CutoffTemp = phase.cutoff_temp;
if (phase2CutoffTemp < phase1CutoffTemp) { if (phase2CutoffTemp < phase1CutoffTemp)
{
phaseCufoffTempErrorMesgBox(2); phaseCufoffTempErrorMesgBox(2);
return; return;
} }
@ -418,7 +476,8 @@ void ExperimentSettingForm::on_pushButton_deliverData_clicked() {
if (!phaseCufoffTempAndTempFlowCheck(2, if (!phaseCufoffTempAndTempFlowCheck(2,
phase1CutoffTemp, phase1CutoffTemp,
phase2CutoffTemp, phase2CutoffTemp,
phase.temp_flow)) { phase.temp_flow))
{
return; return;
} }
} }
@ -426,18 +485,20 @@ void ExperimentSettingForm::on_pushButton_deliverData_clicked() {
{ {
Phase phase; Phase phase;
phase.onoff = ui->checkBox_phase_3->checkState() ? 1 : 0; phase.onoff = ui->checkBox_phase_3->checkState() ? 1 : 0;
phase.cutoff_temp = ui->phase_3_cutoff_temp->text().toFloat(); phase.cutoff_temp = ui->phase_3_cutoff_temp->text().toFloat();
phase.temp_flow = ui->phase_3_scan_rate->text().toFloat(); phase.temp_flow = ui->phase_3_scan_rate->text().toFloat();
phase.constant_temp_time_min = (uint16_t)ui->phase_3_constant_temp->text().toInt(); phase.constant_temp_time_min = (uint16_t)ui->phase_3_constant_temp->text().toInt();
phase.gas = conver2GasType(ui->comboBox_phase_3_atmosphere->currentIndex()); phase.gas = conver2GasType(ui->comboBox_phase_3_atmosphere->currentIndex());
phaseVtr.push_back(phase); phaseVtr.push_back(phase);
// //
if (phase.onoff) { if (phase.onoff)
{
logde << "phase 3 enable."; logde << "phase 3 enable.";
phase3CutoffTemp = phase.cutoff_temp; phase3CutoffTemp = phase.cutoff_temp;
if (phase3CutoffTemp < phase2CutoffTemp) { if (phase3CutoffTemp < phase2CutoffTemp)
{
phaseCufoffTempErrorMesgBox(3); phaseCufoffTempErrorMesgBox(3);
return; return;
} }
@ -450,7 +511,8 @@ void ExperimentSettingForm::on_pushButton_deliverData_clicked() {
if (!phaseCufoffTempAndTempFlowCheck(3, if (!phaseCufoffTempAndTempFlowCheck(3,
phase2CutoffTemp, phase2CutoffTemp,
phase3CutoffTemp, phase3CutoffTemp,
phase.temp_flow)) { phase.temp_flow))
{
return; return;
} }
} }
@ -458,18 +520,20 @@ void ExperimentSettingForm::on_pushButton_deliverData_clicked() {
{ {
Phase phase; Phase phase;
phase.onoff = ui->checkBox_phase_4->checkState() ? 1 : 0; phase.onoff = ui->checkBox_phase_4->checkState() ? 1 : 0;
phase.cutoff_temp = ui->phase_4_cutoff_temp->text().toFloat(); phase.cutoff_temp = ui->phase_4_cutoff_temp->text().toFloat();
phase.temp_flow = ui->phase_4_scan_rate->text().toFloat(); phase.temp_flow = ui->phase_4_scan_rate->text().toFloat();
phase.constant_temp_time_min = (uint16_t)ui->phase_4_constant_temp->text().toInt(); phase.constant_temp_time_min = (uint16_t)ui->phase_4_constant_temp->text().toInt();
phase.gas = conver2GasType(ui->comboBox_phase_4_atmosphere->currentIndex()); phase.gas = conver2GasType(ui->comboBox_phase_4_atmosphere->currentIndex());
phaseVtr.push_back(phase); phaseVtr.push_back(phase);
// //
if (phase.onoff) { if (phase.onoff)
{
logde << "phase 4 enable."; logde << "phase 4 enable.";
phase4CutoffTemp = phase.cutoff_temp; phase4CutoffTemp = phase.cutoff_temp;
if (phase4CutoffTemp < phase3CutoffTemp) { if (phase4CutoffTemp < phase3CutoffTemp)
{
phaseCufoffTempErrorMesgBox(4); phaseCufoffTempErrorMesgBox(4);
return; return;
} }
@ -482,7 +546,8 @@ void ExperimentSettingForm::on_pushButton_deliverData_clicked() {
if (!phaseCufoffTempAndTempFlowCheck(4, if (!phaseCufoffTempAndTempFlowCheck(4,
phase3CutoffTemp, phase3CutoffTemp,
phase4CutoffTemp, phase4CutoffTemp,
phase.temp_flow)) { phase.temp_flow))
{
return; return;
} }
} }
@ -490,18 +555,20 @@ void ExperimentSettingForm::on_pushButton_deliverData_clicked() {
{ {
Phase phase; Phase phase;
phase.onoff = ui->checkBox_phase_5->checkState() ? 1 : 0; phase.onoff = ui->checkBox_phase_5->checkState() ? 1 : 0;
phase.cutoff_temp = ui->phase_5_cutoff_temp->text().toFloat(); phase.cutoff_temp = ui->phase_5_cutoff_temp->text().toFloat();
phase.temp_flow = ui->phase_5_scan_rate->text().toFloat(); phase.temp_flow = ui->phase_5_scan_rate->text().toFloat();
phase.constant_temp_time_min = (uint16_t)ui->phase_5_constant_temp->text().toInt(); phase.constant_temp_time_min = (uint16_t)ui->phase_5_constant_temp->text().toInt();
phase.gas = conver2GasType(ui->comboBox_phase_5_atmosphere->currentIndex()); phase.gas = conver2GasType(ui->comboBox_phase_5_atmosphere->currentIndex());
phaseVtr.push_back(phase); phaseVtr.push_back(phase);
// //
if (phase.onoff) { if (phase.onoff)
{
logde << "phase 5 enable."; logde << "phase 5 enable.";
phase5CutoffTemp = phase.cutoff_temp; phase5CutoffTemp = phase.cutoff_temp;
if (phase5CutoffTemp < phase4CutoffTemp) { if (phase5CutoffTemp < phase4CutoffTemp)
{
phaseCufoffTempErrorMesgBox(5); phaseCufoffTempErrorMesgBox(5);
return; return;
} }
@ -514,7 +581,8 @@ void ExperimentSettingForm::on_pushButton_deliverData_clicked() {
if (!phaseCufoffTempAndTempFlowCheck(5, if (!phaseCufoffTempAndTempFlowCheck(5,
phase4CutoffTemp, phase4CutoffTemp,
phase5CutoffTemp, phase5CutoffTemp,
phase.temp_flow)) { phase.temp_flow))
{
return; return;
} }
} }
@ -522,18 +590,20 @@ void ExperimentSettingForm::on_pushButton_deliverData_clicked() {
{ {
Phase phase; Phase phase;
phase.onoff = ui->checkBox_phase_6->checkState() ? 1 : 0; phase.onoff = ui->checkBox_phase_6->checkState() ? 1 : 0;
phase.cutoff_temp = ui->phase_6_cutoff_temp->text().toFloat(); phase.cutoff_temp = ui->phase_6_cutoff_temp->text().toFloat();
phase.temp_flow = ui->phase_6_scan_rate->text().toFloat(); phase.temp_flow = ui->phase_6_scan_rate->text().toFloat();
phase.constant_temp_time_min = (uint16_t)ui->phase_6_constant_temp->text().toInt(); phase.constant_temp_time_min = (uint16_t)ui->phase_6_constant_temp->text().toInt();
phase.gas = conver2GasType(ui->comboBox_phase_6_atmosphere->currentIndex()); phase.gas = conver2GasType(ui->comboBox_phase_6_atmosphere->currentIndex());
phaseVtr.push_back(phase); phaseVtr.push_back(phase);
// //
if (phase.onoff) { if (phase.onoff)
{
logde << "phase 6 enable."; logde << "phase 6 enable.";
phase6CutoffTemp = phase.cutoff_temp; phase6CutoffTemp = phase.cutoff_temp;
if (phase6CutoffTemp < phase5CutoffTemp) { if (phase6CutoffTemp < phase5CutoffTemp)
{
phaseCufoffTempErrorMesgBox(6); phaseCufoffTempErrorMesgBox(6);
return; return;
} }
@ -546,17 +616,18 @@ void ExperimentSettingForm::on_pushButton_deliverData_clicked() {
if (!phaseCufoffTempAndTempFlowCheck(6, if (!phaseCufoffTempAndTempFlowCheck(6,
phase5CutoffTemp, phase5CutoffTemp,
phase6CutoffTemp, phase6CutoffTemp,
phase.temp_flow)) { phase.temp_flow))
{
return; return;
} }
} }
} }
// //
Global::ExperimentInfo &ei = Global::_experimentInfo; Global::ExperimentInfo &ei = Global::_experimentInfo;
ei.sampleName = ui->sampleNameLineEdit->text(); ei.sampleName = ui->sampleNameLineEdit->text();
ei.sampleWeight = ui->sampleWeightLineEdit->text(); ei.sampleWeight = ui->sampleWeightLineEdit->text();
ei.date = ui->dateTimeLineEdit->text(); ei.date = ui->dateTimeLineEdit->text();
ei.experimentor = ui->userLineEdit->text(); ei.experimentor = ui->userLineEdit->text();
#if 0 #if 0
ei.phaseVtr = phaseVtr; ei.phaseVtr = phaseVtr;
@ -571,13 +642,16 @@ void ExperimentSettingForm::on_pushButton_deliverData_clicked() {
// initial data. // initial data.
QByteArray initialBa; QByteArray initialBa;
if (ui->radioButton_OIT->isChecked()) { if (ui->radioButton_OIT->isChecked())
{
initialBa.append((char)0); initialBa.append((char)0);
Global::_experimentOITFlag = true; Global::_experimentOITFlag = true;
logde << "Global::_experimentOITFlag = true;"; logde << "Global::_experimentOITFlag = true;";
} else { }
else
{
initialBa.append((char)1); initialBa.append((char)1);
Global::_experimentOITFlag = false; Global::_experimentOITFlag = false;
@ -589,7 +663,8 @@ void ExperimentSettingForm::on_pushButton_deliverData_clicked() {
initialBa.append(index); initialBa.append(index);
// 实验名称检查 // 实验名称检查
if (Global::isFileExist(ei.sampleName)) { if (Global::isFileExist(ei.sampleName))
{
QMessageBox::question(this, "实验名称重复", "实验名称已存在,请重新输入!", QMessageBox::question(this, "实验名称重复", "实验名称已存在,请重新输入!",
QMessageBox::Yes); QMessageBox::Yes);
return; return;
@ -603,55 +678,73 @@ void ExperimentSettingForm::on_pushButton_deliverData_clicked() {
hide(); hide();
} }
void ExperimentSettingForm::slotCancel() { void ExperimentSettingForm::slotCancel()
{
hide(); hide();
} }
void ExperimentSettingForm::phaseCufoffTempErrorMesgBox(const int phaseNum) { void ExperimentSettingForm::phaseCufoffTempErrorMesgBox(const int phaseNum)
{
QString title = QString("阶段%1截止温度错误").arg(QString::number(phaseNum)); QString title = QString("阶段%1截止温度错误").arg(QString::number(phaseNum));
QString text = QString("阶段%1截止温度不能小于上一阶段截止温度! ").arg(QString::number(phaseNum)); QString text = QString("阶段%1截止温度不能小于上一阶段截止温度! ").arg(QString::number(phaseNum));
QMessageBox::question(this, title, text, QMessageBox::question(this, title, text,
QMessageBox::Yes); QMessageBox::Yes);
} }
void ExperimentSettingForm::phaseScanRateErrorMesgBox(const int phaseNum) { void ExperimentSettingForm::phaseScanRateErrorMesgBox(const int phaseNum)
{
QString title = QString("阶段%1扫描速率错误").arg(QString::number(phaseNum)); QString title = QString("阶段%1扫描速率错误").arg(QString::number(phaseNum));
QString text = QString("阶段%1扫描速率必须大于0! ").arg(QString::number(phaseNum)); QString text = QString("阶段%1扫描速率必须大于0! ").arg(QString::number(phaseNum));
QMessageBox::question(this, title, text, QMessageBox::question(this, title, text,
QMessageBox::Yes); QMessageBox::Yes);
} }
void ExperimentSettingForm::slotPhaseCheck() { void ExperimentSettingForm::slotPhaseCheck()
if (sender() == ui->checkBox_phase_2) { {
if (ui->checkBox_phase_2->isChecked()) { if (sender() == ui->checkBox_phase_2)
{
if (ui->checkBox_phase_2->isChecked())
{
ui->phase_2_cutoff_temp->setEnabled(true); ui->phase_2_cutoff_temp->setEnabled(true);
ui->phase_2_scan_rate->setEnabled(true); ui->phase_2_scan_rate->setEnabled(true);
ui->phase_2_constant_temp->setEnabled(true); ui->phase_2_constant_temp->setEnabled(true);
ui->comboBox_phase_2_atmosphere->setEnabled(true); ui->comboBox_phase_2_atmosphere->setEnabled(true);
} else { }
else
{
ui->phase_2_cutoff_temp->setEnabled(false); ui->phase_2_cutoff_temp->setEnabled(false);
ui->phase_2_scan_rate->setEnabled(false); ui->phase_2_scan_rate->setEnabled(false);
ui->phase_2_constant_temp->setEnabled(false); ui->phase_2_constant_temp->setEnabled(false);
ui->comboBox_phase_2_atmosphere->setEnabled(false); ui->comboBox_phase_2_atmosphere->setEnabled(false);
} }
} else if (sender() == ui->checkBox_phase_3) { }
if (ui->checkBox_phase_3->isChecked()) { else if (sender() == ui->checkBox_phase_3)
{
if (ui->checkBox_phase_3->isChecked())
{
ui->phase_3_cutoff_temp->setEnabled(true); ui->phase_3_cutoff_temp->setEnabled(true);
ui->phase_3_scan_rate->setEnabled(true); ui->phase_3_scan_rate->setEnabled(true);
ui->phase_3_constant_temp->setEnabled(true); ui->phase_3_constant_temp->setEnabled(true);
ui->comboBox_phase_3_atmosphere->setEnabled(true); ui->comboBox_phase_3_atmosphere->setEnabled(true);
} else { }
else
{
ui->phase_3_cutoff_temp->setEnabled(false); ui->phase_3_cutoff_temp->setEnabled(false);
ui->phase_3_scan_rate->setEnabled(false); ui->phase_3_scan_rate->setEnabled(false);
ui->phase_3_constant_temp->setEnabled(false); ui->phase_3_constant_temp->setEnabled(false);
ui->comboBox_phase_3_atmosphere->setEnabled(false); ui->comboBox_phase_3_atmosphere->setEnabled(false);
} }
} else if (sender() == ui->checkBox_phase_4) { }
if (ui->checkBox_phase_4->isChecked()) { else if (sender() == ui->checkBox_phase_4)
{
if (ui->checkBox_phase_4->isChecked())
{
ui->phase_4_cutoff_temp->setEnabled(true); ui->phase_4_cutoff_temp->setEnabled(true);
ui->phase_4_scan_rate->setEnabled(true); ui->phase_4_scan_rate->setEnabled(true);
ui->phase_4_constant_temp->setEnabled(true); ui->phase_4_constant_temp->setEnabled(true);
ui->comboBox_phase_4_atmosphere->setEnabled(true); ui->comboBox_phase_4_atmosphere->setEnabled(true);
} else { }
else
{
ui->phase_4_cutoff_temp->setEnabled(false); ui->phase_4_cutoff_temp->setEnabled(false);
ui->phase_4_scan_rate->setEnabled(false); ui->phase_4_scan_rate->setEnabled(false);
ui->phase_4_constant_temp->setEnabled(false); ui->phase_4_constant_temp->setEnabled(false);
@ -660,23 +753,25 @@ void ExperimentSettingForm::slotPhaseCheck() {
} }
} }
void ExperimentSettingForm::slotRecvPhaseInfo(const QByteArray &ba) { void ExperimentSettingForm::slotRecvPhaseInfo(const QByteArray &ba)
{
logde << "recv phase info ----------------------- "; logde << "recv phase info ----------------------- ";
#if 1 #if 1
QString hexData = ba.toHex(' '); // ' ' 作为分隔符,可选参数 QString hexData = ba.toHex(' '); // ' ' 作为分隔符,可选参数
qDebug() << "slotRecvPhaseInfo hex:" << hexData; qDebug() << "slotRecvPhaseInfo hex:" << hexData;
#endif #endif
QByteArray localba = ba; QByteArray localba = ba;
SerialPortProtocol *spp = (SerialPortProtocol *)localba.data(); SerialPortProtocol *spp = (SerialPortProtocol *)localba.data();
u8 *data = spp->data_buf; u8 *data = spp->data_buf;
int phaseSize = spp->len / PHASE_BYTE_SIZE; int phaseSize = spp->len / PHASE_BYTE_SIZE;
QVector<Phase> phaseVtr; QVector<Phase> phaseVtr;
for (int i = 0; i < phaseSize; i++) { for (int i = 0; i < phaseSize; i++)
{
#if 0 #if 0
Phase *phase = (Phase *)(data + i * PHASE_BYTE_SIZE); Phase *phase = (Phase *)(data + i * PHASE_BYTE_SIZE);
phaseVtr.push_back(*phase); phaseVtr.push_back(*phase);
@ -719,7 +814,7 @@ void ExperimentSettingForm::slotRecvPhaseInfo(const QByteArray &ba) {
phaseVtr.push_back(phase); phaseVtr.push_back(phase);
#endif #endif
uint8_t *localData = data + i * PHASE_BYTE_SIZE; uint8_t *localData = data + i * PHASE_BYTE_SIZE;
int index = 0; int index = 0;
Phase phase; Phase phase;
// 解析 onoff // 解析 onoff
@ -741,19 +836,20 @@ void ExperimentSettingForm::slotRecvPhaseInfo(const QByteArray &ba) {
// 解析 gas // 解析 gas
uint8_t gasType = *(localData + index); uint8_t gasType = *(localData + index);
switch (gasType) { switch (gasType)
case NC: {
phase.gas = NC; case NC:
break; phase.gas = NC;
case N2: break;
phase.gas = N2; case N2:
break; phase.gas = N2;
case O2: break;
phase.gas = O2; case O2:
break; phase.gas = O2;
default: break;
phase.gas = NC; // 默认值,表示未知类型 default:
break; phase.gas = NC; // 默认值,表示未知类型
break;
} }
phaseVtr.push_back(phase); phaseVtr.push_back(phase);
} }
@ -763,51 +859,62 @@ void ExperimentSettingForm::slotRecvPhaseInfo(const QByteArray &ba) {
// ui update // ui update
// logde<<"phaseVtr size:"<<phaseVtr.size(); // logde<<"phaseVtr size:"<<phaseVtr.size();
// ui重置成默认状态
uiReset(); uiReset();
for (int i = 0; i < phaseVtr.size();) { // ui设置实验阶段参数
for (int i = 0; i < phaseVtr.size();)
{
const Phase &phase = phaseVtr[i]; const Phase &phase = phaseVtr[i];
if (phase.onoff == 0) { if (phase.onoff == 0)
{
break; break;
} }
i++; i++;
// qDebug()<<"index :"<<i; // qDebug()<<"index :"<<i;
QString checkBoxName = QString("checkBox_phase_%1").arg(i); QString checkBoxName = QString("checkBox_phase_%1").arg(i);
QCheckBox *checkBox_phase = qobject_cast<QCheckBox *>(this->findChild<QObject *>(checkBoxName)); QCheckBox *checkBox_phase = qobject_cast<QCheckBox *>(this->findChild<QObject *>(checkBoxName));
if (checkBox_phase) { if (checkBox_phase)
{
checkBox_phase->setChecked(true); checkBox_phase->setChecked(true);
// qDebug()<<"found..."; // qDebug()<<"found...";
} else { }
else
{
// qDebug()<<"not found..."; // qDebug()<<"not found...";
} }
QString cutOffTempLineEditName = QString("phase_%1_cutoff_temp").arg(i); QString cutOffTempLineEditName = QString("phase_%1_cutoff_temp").arg(i);
QLineEdit *cutOffTempLineEdit = qobject_cast<QLineEdit *>(this->findChild<QObject *>(cutOffTempLineEditName)); QLineEdit *cutOffTempLineEdit = qobject_cast<QLineEdit *>(this->findChild<QObject *>(cutOffTempLineEditName));
if (cutOffTempLineEdit) { if (cutOffTempLineEdit)
{
cutOffTempLineEdit->setText(QString::number(phase.cutoff_temp, 'f', 3)); cutOffTempLineEdit->setText(QString::number(phase.cutoff_temp, 'f', 3));
cutOffTempLineEdit->setEnabled(true); cutOffTempLineEdit->setEnabled(true);
} }
QString scanRateLineEditName = QString("phase_%1_scan_rate").arg(i); QString scanRateLineEditName = QString("phase_%1_scan_rate").arg(i);
QLineEdit *scanRateLineEdit = QLineEdit *scanRateLineEdit =
qobject_cast<QLineEdit *>(this->findChild<QObject *>(scanRateLineEditName)); qobject_cast<QLineEdit *>(this->findChild<QObject *>(scanRateLineEditName));
if (scanRateLineEdit) { if (scanRateLineEdit)
{
scanRateLineEdit->setText(QString::number(phase.temp_flow, 'f', 3)); scanRateLineEdit->setText(QString::number(phase.temp_flow, 'f', 3));
scanRateLineEdit->setEnabled(true); scanRateLineEdit->setEnabled(true);
} }
QString constantTempLineEditName = QString("phase_%1_constant_temp").arg(i); QString constantTempLineEditName = QString("phase_%1_constant_temp").arg(i);
QLineEdit *constantTempLineEdit = QLineEdit *constantTempLineEdit =
qobject_cast<QLineEdit *>(this->findChild<QObject *>(constantTempLineEditName)); qobject_cast<QLineEdit *>(this->findChild<QObject *>(constantTempLineEditName));
if (constantTempLineEdit) { if (constantTempLineEdit)
{
constantTempLineEdit->setText(QString::number(phase.constant_temp_time_min)); constantTempLineEdit->setText(QString::number(phase.constant_temp_time_min));
constantTempLineEdit->setEnabled(true); constantTempLineEdit->setEnabled(true);
} }
QString atmoshpereComboBoxName = QString("comboBox_phase_%1_atmosphere").arg(i); QString atmoshpereComboBoxName = QString("comboBox_phase_%1_atmosphere").arg(i);
QComboBox *atmoshpereComboBox = QComboBox *atmoshpereComboBox =
qobject_cast<QComboBox *>(this->findChild<QObject *>(atmoshpereComboBoxName)); qobject_cast<QComboBox *>(this->findChild<QObject *>(atmoshpereComboBoxName));
if (atmoshpereComboBox) { if (atmoshpereComboBox)
{
atmoshpereComboBox->setCurrentIndex(phase.gas % 256); atmoshpereComboBox->setCurrentIndex(phase.gas % 256);
atmoshpereComboBox->setEnabled(true); atmoshpereComboBox->setEnabled(true);
} }
@ -817,10 +924,13 @@ void ExperimentSettingForm::slotRecvPhaseInfo(const QByteArray &ba) {
// radioButton_OIT // radioButton_OIT
// comboBox_initial_atmosphere // comboBox_initial_atmosphere
// 设置OIT类型
u8 *oitValue = (data + 72); u8 *oitValue = (data + 72);
logde << "oit value:" << (int)*oitValue; logde << "oit value:" << (int)*oitValue;
if (*oitValue) { if (*oitValue)
{
ui->radioButton_OIT->setChecked(false); ui->radioButton_OIT->setChecked(false);
ui->radioButton_OIT_not->setChecked(true); ui->radioButton_OIT_not->setChecked(true);
#if 0 #if 0
@ -831,7 +941,9 @@ void ExperimentSettingForm::slotRecvPhaseInfo(const QByteArray &ba) {
oitRadioButton->setChecked(true); oitRadioButton->setChecked(true);
} }
#endif #endif
} else { }
else
{
ui->radioButton_OIT->setChecked(true); ui->radioButton_OIT->setChecked(true);
ui->radioButton_OIT_not->setChecked(false); ui->radioButton_OIT_not->setChecked(false);
Global::_experimentOITFlag = true; Global::_experimentOITFlag = true;
@ -847,6 +959,7 @@ void ExperimentSettingForm::slotRecvPhaseInfo(const QByteArray &ba) {
#endif #endif
} }
// 设置默认其他类型。
u8 *initAtmosphereValue = (data + 73); u8 *initAtmosphereValue = (data + 73);
logde << "initAtmosphereValue:" << (int)(*initAtmosphereValue); logde << "initAtmosphereValue:" << (int)(*initAtmosphereValue);
ui->comboBox_initial_atmosphere->setCurrentIndex((int)*initAtmosphereValue); ui->comboBox_initial_atmosphere->setCurrentIndex((int)*initAtmosphereValue);
@ -861,9 +974,28 @@ void ExperimentSettingForm::slotRecvPhaseInfo(const QByteArray &ba) {
#endif #endif
} }
void ExperimentSettingForm::showEvent(QShowEvent *event) { void ExperimentSettingForm::showEvent(QShowEvent *event)
QDateTime currentDateTime = QDateTime::currentDateTime(); {
QString internationalFormat = currentDateTime.toString("yyyy/MM/dd hh:mm:ss"); QDateTime currentDateTime = QDateTime::currentDateTime();
QString internationalFormat = currentDateTime.toString("yyyy/MM/dd hh:mm:ss");
ui->dateTimeLineEdit->setText(internationalFormat); ui->dateTimeLineEdit->setText(internationalFormat);
// 测试类型OIT设置
if (Global::_experimentInfo.testType == Global::TestType::OIT)
{
Global::_experimentOITFlag = true;
ui->radioButton_OIT->setChecked(true);
ui->radioButton_OIT_not->setChecked(false);
}
else
{
Global::_experimentOITFlag = false;
ui->radioButton_OIT->setChecked(false);
ui->radioButton_OIT_not->setChecked(true);
}
// 初始气氛
ui->comboBox_initial_atmosphere->setCurrentIndex((int)Global::_experimentInfo.initialAtmosPhere);
} }

View File

@ -15,7 +15,7 @@
#include "leftwidget.h" #include "leftwidget.h"
#include "filemanager.h" #include "filemanager.h"
#include "global.h" #include "global.h"
#include "logger.h" #include "../logger/logger.h"
LeftWidget::LeftWidget(QWidget *parent) : QDockWidget(parent) LeftWidget::LeftWidget(QWidget *parent) : QDockWidget(parent)
{ {
@ -38,8 +38,13 @@ LeftWidget::LeftWidget(QWidget *parent) : QDockWidget(parent)
_contextMenu = new QMenu(_treeWidget); _contextMenu = new QMenu(_treeWidget);
_deleteFileAction = new QAction("删除文件", this); _deleteFileAction = new QAction("删除文件", this);
_createFolderAction = new QAction("新建文件夹", this); _createFolderAction = new QAction("新建文件夹", this);
_moveToFolderAction = new QAction("移动到文件夹", this);
_moveToFolderSubMenu = new QMenu("移动到文件夹", this); // Initialize submenu
_moveToFolderAction->setMenu(_moveToFolderSubMenu); // Set submenu for move to folder action
_contextMenu->addAction(_deleteFileAction); _contextMenu->addAction(_deleteFileAction);
_contextMenu->addAction(_createFolderAction); _contextMenu->addAction(_createFolderAction);
_contextMenu->addMenu(_moveToFolderSubMenu); // Add submenu instead of action
_treeWidget->setContextMenuPolicy(Qt::CustomContextMenu); _treeWidget->setContextMenuPolicy(Qt::CustomContextMenu);
@ -50,20 +55,112 @@ LeftWidget::LeftWidget(QWidget *parent) : QDockWidget(parent)
this, &LeftWidget::slotDeleteActionTriggered); this, &LeftWidget::slotDeleteActionTriggered);
connect(_createFolderAction, &QAction::triggered, connect(_createFolderAction, &QAction::triggered,
this, &LeftWidget::slotCreateFolderActionTriggered); this, &LeftWidget::slotCreateFolderActionTriggered);
connect(_moveToFolderAction, &QAction::triggered,
this, &LeftWidget::slotMoveToFolderActionTriggered); // Connect the move to folder action
}
void LeftWidget::slotShowContextMenu(const QPoint &pos)
{
QTreeWidgetItem *item = _treeWidget->itemAt(pos);
if (item)
{
// 获取文件路径
QString filePath = item->data(0, Qt::UserRole).toString();
QString dirPath = item->data(0, Qt::UserRole + 1).toString();
logde << "filePath:" << filePath.toStdString();
logde << "dirPath:" << dirPath.toStdString();
// 如果是文件
if (!filePath.isEmpty())
{
_deleteFileActionFilePath = filePath;
_deleteFileAction->setVisible(true);
_deleteFileAction->setText(tr("删除文件"));
// 显示移动到文件夹选项
_moveToFolderAction->setVisible(true);
// 清除之前的子菜单项
_moveToFolderSubMenu->clear();
// 获取根目录下的文件夹路径并创建子菜单项(只显示第一层文件夹)
QStringList folderPaths = getRootFolderPaths();
for (const QString &folderPath : folderPaths)
{
// 获取文件夹名称
QString folderName = QFileInfo(folderPath).fileName();
// 创建子菜单项
QAction *folderAction = new QAction(folderName, this);
folderAction->setData(folderPath); // 将完整路径存储在action中
// 连接信号到槽
connect(folderAction, &QAction::triggered, this, [this, folderAction]()
{ slotMoveToSpecificFolder(folderAction->data().toString()); });
// 添加到子菜单
_moveToFolderSubMenu->addAction(folderAction);
}
// 如果没有可用文件夹,禁用移动功能
if (folderPaths.isEmpty())
{
_moveToFolderAction->setEnabled(false);
}
else
{
_moveToFolderAction->setEnabled(true);
}
}
// 如果是目录
else if (!dirPath.isEmpty())
{
// 不显示删除文件功能
_deleteFileAction->setVisible(false);
// 不显示移动到文件夹功能(目录不能移动)
_moveToFolderAction->setVisible(false);
_moveToFolderAction->setEnabled(false);
#if 0
_deleteFileAction->setVisible(true);
_deleteFileActionFilePath = dirPath;
_deleteFileAction->setText(tr("删除文件夹"));
#endif
}
else
{
// 对于根节点或其他项目,不显示移动功能
_moveToFolderAction->setVisible(false);
_moveToFolderAction->setEnabled(false);
}
// 只有当点击的是目录时才显示"新建文件夹"选项
bool isDir = !dirPath.isEmpty();
_createFolderAction->setVisible(isDir);
_contextMenu->exec(_treeWidget->mapToGlobal(pos));
}
} }
void LeftWidget::reloadFileName() void LeftWidget::reloadFileName()
{ {
#if 0
clearAllChildItems(_sampleDataItem); clearAllChildItems(_sampleDataItem);
// clearAllChildItems(_baseLineItem); // clearAllChildItems(_baseLineItem);
clearAllChildItems(_analysisStateItem); clearAllChildItems(_analysisStateItem);
initFileName(_sampleDataItem, Global::SampleDataFloder); initFileName(_sampleDataItem, Global::SampleDataFloder);
#if 0 #if 0
initFileName(_baseLineItem,Global::BaseLineFolder); initFileName(_baseLineItem,Global::BaseLineFolder);
#endif #endif
initFileName(_analysisStateItem, Global::AnalysisStateFolder); initFileName(_analysisStateItem, Global::AnalysisStateFolder);
#endif
reloadFileTree();
// 更新文件列表 // 更新文件列表
Global::updateFileList(); Global::updateFileList();
} }
@ -131,6 +228,7 @@ void LeftWidget::initData()
} }
#endif #endif
} }
void LeftWidget::slotTreeWidgetItemClicked(QTreeWidgetItem *item, int column) void LeftWidget::slotTreeWidgetItemClicked(QTreeWidgetItem *item, int column)
{ {
qDebug() << "item clicked:" << item->text(0) << column; qDebug() << "item clicked:" << item->text(0) << column;
@ -237,80 +335,54 @@ void LeftWidget::recursiveFolderOperation(const QString& folderPath) {
} }
#endif #endif
void LeftWidget::slotShowContextMenu(const QPoint &pos)
{
QTreeWidgetItem *item = _treeWidget->itemAt(pos);
if (item) {
// 获取文件路径
QString filePath = item->data(0, Qt::UserRole).toString();
QString dirPath = item->data(0, Qt::UserRole + 1).toString();
// 如果是文件
if (!filePath.isEmpty()) {
_deleteFileActionFilePath = filePath;
_deleteFileAction->setVisible(true);
_deleteFileAction->setText(tr("删除文件"));
}
// 如果是目录
else if (!dirPath.isEmpty()) {
// 暂时不要删除文件件功能
_deleteFileAction->setVisible(false);
#if 0
_deleteFileAction->setVisible(true);
_deleteFileActionFilePath = dirPath;
_deleteFileAction->setText(tr("删除文件夹"));
#endif
} else {
_deleteFileAction->setVisible(false);
}
// 只有当点击的是目录时才显示"新建文件夹"选项
bool isDir = !dirPath.isEmpty();
_createFolderAction->setVisible(isDir);
_contextMenu->exec(_treeWidget->mapToGlobal(pos));
}
}
void LeftWidget::slotDeleteActionTriggered() void LeftWidget::slotDeleteActionTriggered()
{ {
if (_deleteFileActionFilePath.isEmpty()) { if (_deleteFileActionFilePath.isEmpty())
{
return; return;
} }
QFileInfo fileInfo(_deleteFileActionFilePath); QFileInfo fileInfo(_deleteFileActionFilePath);
bool isDir = fileInfo.isDir(); bool isDir = fileInfo.isDir();
// 检查文件/目录是否存在 // 检查文件/目录是否存在
if (!fileInfo.exists()) { if (!fileInfo.exists())
{
QMessageBox::warning(this, tr("警告"), tr("文件/目录不存在!")); QMessageBox::warning(this, tr("警告"), tr("文件/目录不存在!"));
return; return;
} }
// 确认删除对话框 // 确认删除对话框
int ret = QMessageBox::question(this, tr("确认删除"), int ret = QMessageBox::question(this, tr("确认删除"),
tr("确定要删除%1\n%2?").arg(isDir ? tr("文件夹及其所有内容") : tr("文件")).arg(_deleteFileActionFilePath), tr("确定要删除%1\n%2?").arg(isDir ? tr("文件夹及其所有内容") : tr("文件")).arg(_deleteFileActionFilePath),
QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes | QMessageBox::No,
QMessageBox::No); QMessageBox::No);
if (ret == QMessageBox::Yes) { if (ret == QMessageBox::Yes)
{
bool success; bool success;
if (isDir) { if (isDir)
{
// 删除目录及其内容 // 删除目录及其内容
success = removeDir(_deleteFileActionFilePath); success = removeDir(_deleteFileActionFilePath);
} else { }
else
{
// 删除文件 // 删除文件
success = QFile::remove(_deleteFileActionFilePath); success = QFile::remove(_deleteFileActionFilePath);
} }
if (success) { if (success)
{
// 重新加载文件树 // 重新加载文件树
reloadFileTree(); reloadFileTree();
} else { }
else
{
QMessageBox::critical(this, tr("错误"), tr("删除失败!")); QMessageBox::critical(this, tr("错误"), tr("删除失败!"));
} }
} }
_deleteFileActionFilePath.clear(); _deleteFileActionFilePath.clear();
} }
@ -318,83 +390,96 @@ bool LeftWidget::removeDir(const QString &dirPath)
{ {
bool result = true; bool result = true;
QDir dir(dirPath); QDir dir(dirPath);
if (dir.exists(dirPath)) { if (dir.exists(dirPath))
Q_FOREACH(QFileInfo info, dir.entryInfoList(QDir::NoDotAndDotDot | QDir::System | QDir::Hidden | QDir::AllDirs | QDir::Files, QDir::DirsFirst)) { {
if (info.isDir()) { Q_FOREACH (QFileInfo info, dir.entryInfoList(QDir::NoDotAndDotDot | QDir::System | QDir::Hidden | QDir::AllDirs | QDir::Files, QDir::DirsFirst))
{
if (info.isDir())
{
result = removeDir(info.absoluteFilePath()); result = removeDir(info.absoluteFilePath());
} else { }
else
{
result = QFile::remove(info.absoluteFilePath()); result = QFile::remove(info.absoluteFilePath());
} }
if (!result) { if (!result)
{
return result; return result;
} }
} }
result = dir.rmdir(dirPath); result = dir.rmdir(dirPath);
} }
return result; return result;
} }
void LeftWidget::slotCreateFolderActionTriggered() void LeftWidget::slotCreateFolderActionTriggered()
{ {
// 获取当前选中的项目 // 创建主分支下的文件夹
QTreeWidgetItem *currentItem = _treeWidget->currentItem(); QTreeWidgetItem *currentItem = _treeWidget->topLevelItem(0);
if (!currentItem) { logde << "currentItem : " << currentItem->text(0).toStdString();
return;
}
// 获取当前目录路径 // 获取当前目录路径
QString dirPath; QString dirPath;
if (currentItem->data(0, Qt::UserRole + 1).toString().isEmpty()) { if (currentItem->data(0, Qt::UserRole + 1).toString().isEmpty())
{
// 如果是文件,获取其父目录 // 如果是文件,获取其父目录
dirPath = QFileInfo(currentItem->data(0, Qt::UserRole).toString()).absolutePath(); dirPath = QFileInfo(currentItem->data(0, Qt::UserRole).toString()).absolutePath();
} else { }
else
{
// 如果是目录,直接使用其路径 // 如果是目录,直接使用其路径
dirPath = currentItem->data(0, Qt::UserRole + 1).toString(); dirPath = currentItem->data(0, Qt::UserRole + 1).toString();
} }
// 弹出对话框,输入新文件夹名称 // 弹出对话框,输入新文件夹名称
bool ok; bool ok;
QString folderName = QInputDialog::getText(this, tr("新建文件夹"), QString folderName = QInputDialog::getText(this, tr("新建文件夹"),
tr("请输入文件夹名称:"), tr("请输入文件夹名称:"),
QLineEdit::Normal, QLineEdit::Normal,
tr("新建文件夹"), &ok); tr("新建文件夹"), &ok);
if (!ok || folderName.isEmpty()) { if (!ok || folderName.isEmpty())
{
return; return;
} }
// 检查文件夹名称是否有效 // 检查文件夹名称是否有效
if (folderName.contains(QRegExp("[\\/:*?\"<>|]"))) { if (folderName.contains(QRegExp("[\\/:*?\"<>|]")))
{
QMessageBox::warning(this, tr("错误"), tr("文件夹名称包含非法字符!")); QMessageBox::warning(this, tr("错误"), tr("文件夹名称包含非法字符!"));
return; return;
} }
// 创建新文件夹路径 // 创建新文件夹路径
QString newFolderPath = dirPath + "/" + folderName; QString newFolderPath = dirPath + "/" + folderName;
// 检查文件夹是否已存在 // 检查文件夹是否已存在
if (QDir(newFolderPath).exists()) { if (QDir(newFolderPath).exists())
{
QMessageBox::warning(this, tr("错误"), tr("文件夹已存在!")); QMessageBox::warning(this, tr("错误"), tr("文件夹已存在!"));
return; return;
} }
// 创建文件夹 // 创建文件夹
if (QDir().mkdir(newFolderPath)) { if (QDir().mkdir(newFolderPath))
{
// 保存当前展开状态 // 保存当前展开状态
saveExpandedState(); saveExpandedState();
// 重新加载文件树 // 重新加载文件树
reloadFileTree(); reloadFileTree();
// 恢复展开状态 // 恢复展开状态
restoreExpandedState(); restoreExpandedState();
// 展开当前目录并选中新创建的文件夹 // 展开当前目录并选中新创建的文件夹
expandAndSelectItem(newFolderPath); expandAndSelectItem(newFolderPath);
} else { }
else
{
QMessageBox::critical(this, tr("错误"), tr("创建文件夹失败!")); QMessageBox::critical(this, tr("错误"), tr("创建文件夹失败!"));
} }
} }
@ -403,18 +488,21 @@ void LeftWidget::expandAndSelectItem(const QString &path)
{ {
// 递归展开到指定路径并选中该项 // 递归展开到指定路径并选中该项
QTreeWidgetItemIterator it(_treeWidget); QTreeWidgetItemIterator it(_treeWidget);
while (*it) { while (*it)
{
QTreeWidgetItem *item = *it; QTreeWidgetItem *item = *it;
QString itemPath = item->data(0, Qt::UserRole + 1).toString(); QString itemPath = item->data(0, Qt::UserRole + 1).toString();
if (itemPath == path) { if (itemPath == path)
{
// 展开所有父节点 // 展开所有父节点
QTreeWidgetItem *parent = item->parent(); QTreeWidgetItem *parent = item->parent();
while (parent) { while (parent)
{
parent->setExpanded(true); parent->setExpanded(true);
parent = parent->parent(); parent = parent->parent();
} }
// 选中新创建的文件夹 // 选中新创建的文件夹
_treeWidget->setCurrentItem(item); _treeWidget->setCurrentItem(item);
break; break;
@ -446,26 +534,26 @@ void LeftWidget::reloadFileTree()
{ {
// 保存当前展开状态 // 保存当前展开状态
saveExpandedState(); saveExpandedState();
// 清空现有的树形结构 // 清空现有的树形结构
_treeWidget->clear(); _treeWidget->clear();
// 创建根节点 // 创建根节点
QTreeWidgetItem *rootItem = new QTreeWidgetItem(_treeWidget); QTreeWidgetItem *rootItem = new QTreeWidgetItem(_treeWidget);
rootItem->setText(0, "实验数据"); rootItem->setText(0, "实验数据");
rootItem->setData(0, Qt::UserRole, Global::ExperimentDirPath); // rootItem->setData(0, Qt::UserRole, Global::ExperimentDirPath);
// 保存根目录路径,用于恢复展开状态 // 保存根目录路径,用于恢复展开状态
rootItem->setData(0, Qt::UserRole + 1, Global::ExperimentDirPath); rootItem->setData(0, Qt::UserRole + 1, Global::ExperimentDirPath);
// 递归扫描目录并构建树形结构 // 递归扫描目录并构建树形结构
buildFileTree(rootItem, Global::ExperimentDirPath); buildFileTree(rootItem, Global::ExperimentDirPath);
// 展开根节点 // 展开根节点
rootItem->setExpanded(true); rootItem->setExpanded(true);
// 恢复展开状态 // 恢复展开状态
restoreExpandedState(); restoreExpandedState();
// 更新全局文件列表 // 更新全局文件列表
Global::updateFileList(); Global::updateFileList();
} }
@ -487,39 +575,47 @@ QFileInfoList LeftWidget::scanDirRecursively(const QString &rootPath)
void LeftWidget::buildFileTree(QTreeWidgetItem *parentItem, const QString &dirPath) void LeftWidget::buildFileTree(QTreeWidgetItem *parentItem, const QString &dirPath)
{ {
QDir dir(dirPath); QDir dir(dirPath);
if (!dir.exists()) { if (!dir.exists())
{
qWarning() << "目录不存在: " << dirPath; qWarning() << "目录不存在: " << dirPath;
return; return;
} }
// 获取所有子目录和文件,按名称排序 // 获取所有子目录和文件,按名称排序
dir.setSorting(QDir::Name | QDir::DirsFirst); dir.setSorting(QDir::Name | QDir::DirsFirst);
QFileInfoList list = dir.entryInfoList(QDir::Dirs | QDir::Files | QDir::NoDotAndDotDot); QFileInfoList list = dir.entryInfoList(QDir::Dirs | QDir::Files | QDir::NoDotAndDotDot);
for (const QFileInfo &fileInfo : list) { for (const QFileInfo &fileInfo : list)
{
QTreeWidgetItem *item = new QTreeWidgetItem(parentItem); QTreeWidgetItem *item = new QTreeWidgetItem(parentItem);
if (fileInfo.isDir()) { if (fileInfo.isDir())
{
// 设置目录项 // 设置目录项
item->setText(0, fileInfo.fileName()); item->setText(0, fileInfo.fileName());
// 使用系统默认的目录图标 // 使用系统默认的目录图标
item->setIcon(0, _treeWidget->style()->standardIcon(QStyle::SP_DirIcon)); item->setIcon(0, _treeWidget->style()->standardIcon(QStyle::SP_DirIcon));
// 保存目录路径,用于恢复展开状态 // 保存目录路径,用于恢复展开状态
item->setData(0, Qt::UserRole + 1, fileInfo.absoluteFilePath()); item->setData(0, Qt::UserRole + 1, fileInfo.absoluteFilePath());
// 递归处理子目录 // 递归处理子目录
buildFileTree(item, fileInfo.absoluteFilePath()); buildFileTree(item, fileInfo.absoluteFilePath());
} else { }
else
{
// 设置文件项 // 设置文件项
item->setText(0, fileInfo.fileName()); item->setText(0, fileInfo.fileName());
item->setData(0, Qt::UserRole, fileInfo.absoluteFilePath()); item->setData(0, Qt::UserRole, fileInfo.absoluteFilePath());
// 根据文件类型设置不同的图标 // 根据文件类型设置不同的图标
QString suffix = fileInfo.suffix().toLower(); QString suffix = fileInfo.suffix().toLower();
if (suffix == "xlsx" || suffix == "xls") { if (suffix == "xlsx" || suffix == "xls")
{
// 使用系统默认的文档图标 // 使用系统默认的文档图标
item->setIcon(0, _treeWidget->style()->standardIcon(QStyle::SP_FileIcon)); item->setIcon(0, _treeWidget->style()->standardIcon(QStyle::SP_FileIcon));
} else { }
else
{
// 使用默认文件图标 // 使用默认文件图标
item->setIcon(0, _treeWidget->style()->standardIcon(QStyle::SP_FileIcon)); item->setIcon(0, _treeWidget->style()->standardIcon(QStyle::SP_FileIcon));
} }
@ -530,41 +626,179 @@ void LeftWidget::buildFileTree(QTreeWidgetItem *parentItem, const QString &dirPa
void LeftWidget::saveExpandedState() void LeftWidget::saveExpandedState()
{ {
_expandedPaths.clear(); _expandedPaths.clear();
// 递归遍历所有项,保存展开的目录路径 // 递归遍历所有项,保存展开的目录路径
QTreeWidgetItemIterator it(_treeWidget); QTreeWidgetItemIterator it(_treeWidget);
while (*it) { while (*it)
{
QTreeWidgetItem *item = *it; QTreeWidgetItem *item = *it;
if (item->isExpanded()) { if (item->isExpanded())
{
QVariant pathData = item->data(0, Qt::UserRole + 1); QVariant pathData = item->data(0, Qt::UserRole + 1);
if (!pathData.isNull()) { if (!pathData.isNull())
{
_expandedPaths.append(pathData.toString()); _expandedPaths.append(pathData.toString());
} }
} }
++it; ++it;
} }
qDebug() << "保存了" << _expandedPaths.size() << "个展开状态:" << _expandedPaths; qDebug() << "保存了" << _expandedPaths.size() << "个展开状态:" << _expandedPaths;
} }
void LeftWidget::restoreExpandedState() void LeftWidget::restoreExpandedState()
{ {
int restoredCount = 0; int restoredCount = 0;
// 递归遍历所有项,恢复展开状态 // 递归遍历所有项,恢复展开状态
QTreeWidgetItemIterator it(_treeWidget); QTreeWidgetItemIterator it(_treeWidget);
while (*it) { while (*it)
{
QTreeWidgetItem *item = *it; QTreeWidgetItem *item = *it;
QVariant pathData = item->data(0, Qt::UserRole + 1); QVariant pathData = item->data(0, Qt::UserRole + 1);
if (!pathData.isNull()) { if (!pathData.isNull())
{
QString path = pathData.toString(); QString path = pathData.toString();
if (_expandedPaths.contains(path)) { if (_expandedPaths.contains(path))
{
item->setExpanded(true); item->setExpanded(true);
restoredCount++; restoredCount++;
} }
} }
++it; ++it;
} }
qDebug() << "恢复了" << restoredCount << "个展开状态"; qDebug() << "恢复了" << restoredCount << "个展开状态";
} }
void LeftWidget::slotMoveToFolderActionTriggered()
{
// 获取当前选中的项目
QTreeWidgetItem *currentItem = _treeWidget->currentItem();
if (!currentItem)
{
return;
}
// 检查是否是文件(不能移动文件夹)
QString filePath = currentItem->data(0, Qt::UserRole).toString();
if (filePath.isEmpty())
{
QMessageBox::information(this, tr("提示"), tr("请选择一个文件进行移动!"));
return;
}
// 弹出对话框让用户选择目标文件夹
QStringList folderPaths = getAllFolderPaths();
bool ok;
QString selectedPath = QInputDialog::getItem(this,
tr("选择目标文件夹"),
tr("请选择要移动到的目标文件夹:"),
folderPaths,
0,
false,
&ok);
if (!ok || selectedPath.isEmpty())
{
return;
}
slotMoveToSpecificFolder(selectedPath);
}
void LeftWidget::slotMoveToSpecificFolder(const QString &targetFolderPath)
{
// 获取当前选中的项目
QTreeWidgetItem *currentItem = _treeWidget->currentItem();
if (!currentItem)
{
return;
}
// 检查是否是文件(不能移动文件夹)
QString filePath = currentItem->data(0, Qt::UserRole).toString();
if (filePath.isEmpty())
{
QMessageBox::information(this, tr("提示"), tr("请选择一个文件进行移动!"));
return;
}
// 保存要移动的文件路径
QString fileToMove = filePath;
// 执行移动操作
QString targetPath = targetFolderPath + "/" + QFileInfo(fileToMove).fileName();
// 检查目标文件是否已存在
if (QFile::exists(targetPath))
{
int ret = QMessageBox::question(this, tr("确认覆盖"),
tr("目标文件已存在,是否覆盖?\n%1").arg(targetPath),
QMessageBox::Yes | QMessageBox::No,
QMessageBox::No);
if (ret == QMessageBox::No)
{
return;
}
}
// 移动文件
if (QFile::rename(fileToMove, targetPath))
{
logde << "文件移动成功: " << fileToMove.toStdString() << " -> " << targetPath.toStdString();
// 保存当前展开状态
saveExpandedState();
// 重新加载文件树
reloadFileTree();
// 恢复展开状态
restoreExpandedState();
// 展开并选中目标文件夹
expandAndSelectItem(targetFolderPath);
}
else
{
QMessageBox::critical(this, tr("错误"), tr("文件移动失败!"));
}
}
QStringList LeftWidget::getRootFolderPaths()
{
QStringList folderPaths;
QDir rootDir(Global::ExperimentDirPath);
if (rootDir.exists())
{
// Get only directories in the root path (no recursion)
QFileInfoList entries = rootDir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot);
for (const QFileInfo &entry : entries)
{
folderPaths << entry.absoluteFilePath();
}
}
return folderPaths;
}
QStringList LeftWidget::getAllFolderPaths()
{
QStringList folderPaths;
// 递归遍历所有项目以获取所有文件夹路径
QTreeWidgetItemIterator it(_treeWidget);
while (*it)
{
QTreeWidgetItem *item = *it;
QString dirPath = item->data(0, Qt::UserRole + 1).toString();
if (!dirPath.isEmpty())
{
folderPaths << dirPath;
}
++it;
}
return folderPaths;
}

View File

@ -11,7 +11,7 @@
#include "global.h" #include "global.h"
class LeftWidget:public QDockWidget class LeftWidget : public QDockWidget
{ {
Q_OBJECT Q_OBJECT
public: public:
@ -21,44 +21,56 @@ public:
void reloadFileTree(); void reloadFileTree();
QString filePathCheck(const QString fileName,const QString folderPath); QString filePathCheck(const QString fileName, const QString folderPath);
// 确认删除文件 // 确认删除文件
void confirmDelete(bool enabled); void confirmDelete(bool enabled);
signals: signals:
void sigSendAnalysisFileName(const QString&); void sigSendAnalysisFileName(const QString &);
void sigDeleteActionTriggered(const QString&); void sigDeleteActionTriggered(const QString &);
private: private:
void initData(); void initData();
void initFileName(QTreeWidgetItem*,const QString &folderPath); void initFileName(QTreeWidgetItem *, const QString &folderPath);
void expandAll(QTreeWidgetItem* item); void expandAll(QTreeWidgetItem *item);
void clearAllChildItems(QTreeWidgetItem* parentItem); void clearAllChildItems(QTreeWidgetItem *parentItem);
QFileInfoList scanDirRecursively(const QString &rootPath); QFileInfoList scanDirRecursively(const QString &rootPath);
void buildFileTree(QTreeWidgetItem *parentItem, const QString &dirPath); void buildFileTree(QTreeWidgetItem *parentItem, const QString &dirPath);
void saveExpandedState(); void saveExpandedState();
void restoreExpandedState(); void restoreExpandedState();
void expandAndSelectItem(const QString &path); void expandAndSelectItem(const QString &path);
bool removeDir(const QString &dirPath); bool removeDir(const QString &dirPath);
QStringList getAllFolderPaths(); // Add function to get all folder paths for move operation
QStringList getRootFolderPaths(); // Add function to get only root level folder paths
private slots: private slots:
void slotTreeWidgetItemClicked(QTreeWidgetItem *item, int column); void slotTreeWidgetItemClicked(QTreeWidgetItem *item, int column);
// 右键菜单
void slotShowContextMenu(const QPoint &pos); void slotShowContextMenu(const QPoint &pos);
void slotDeleteActionTriggered(); void slotDeleteActionTriggered();
void slotCreateFolderActionTriggered(); void slotCreateFolderActionTriggered();
void slotMoveToFolderActionTriggered(); // Add slot for move to folder action
void slotMoveToSpecificFolder(const QString &targetFolderPath); // 新增:移动到指定文件夹的槽函数
private: private:
QTreeWidget *_treeWidget; QTreeWidget *_treeWidget;
#if 0
QTreeWidgetItem *_analysisStateItem, QTreeWidgetItem *_analysisStateItem,
*_baseLineItem, *_baseLineItem,
*_sampleDataItem; *_sampleDataItem;
#endif
QMenu *_contextMenu; QMenu *_contextMenu;
QAction *_deleteFileAction; QAction *_deleteFileAction;
QAction *_createFolderAction; QAction *_createFolderAction;
QAction *_moveToFolderAction;
QMenu *_moveToFolderSubMenu; // Add submenu for move to folder
QString _deleteFileActionFilePath; QString _deleteFileActionFilePath;
// 保存展开状态的列表 // 保存展开状态的列表
QStringList _expandedPaths; QStringList _expandedPaths;
}; };
#endif // LEFTWIDGET_H #endif // LEFTWIDGET_H

View File

@ -84,7 +84,6 @@ void PrintPreviewForm::slotPaintRequested(QPrinter *printer) {
painter.setOpacity(1.0); painter.setOpacity(1.0);
#endif #endif
// 获取页面矩形区域 // 获取页面矩形区域
QRect pageRect = printer->pageRect(); QRect pageRect = printer->pageRect();