2025-12-11T16:15:35

This commit is contained in:
yuntang 2025-12-11 16:15:36 +08:00
parent 8e3c534710
commit 0583d5f84f
18 changed files with 851 additions and 293 deletions

26
.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,26 @@
{
"cmake.sourceDirectory": "D:/gitfile/analysis_tool/src",
"files.associations": {
"new": "cpp",
"__locale": "cpp",
"ios": "cpp",
"queue": "cpp",
"stack": "cpp",
"__config": "cpp",
"__bit_reference": "cpp",
"__hash_table": "cpp",
"__split_buffer": "cpp",
"__tree": "cpp",
"array": "cpp",
"deque": "cpp",
"initializer_list": "cpp",
"list": "cpp",
"map": "cpp",
"set": "cpp",
"string": "cpp",
"string_view": "cpp",
"unordered_map": "cpp",
"unordered_set": "cpp",
"vector": "cpp"
}
}

View File

@ -0,0 +1,5 @@
[2025-12-01 10:46:10,897] main...
[2025-12-01 10:46:10,899] config file existed.
[2025-12-01 10:46:10,936] version:1.3.5.1
[2025-12-01 10:46:10,980] setEventHandlerEnable...0
[2025-12-01 10:46:31,805] serialport destructor.

Binary file not shown.

View File

@ -18,7 +18,7 @@
], ],
"externalConsole": false, "externalConsole": false,
"miDebuggerPath": "D:/qt/Qt5.14.2/5.14.2/mingw73_64/bin/gdb.exe", "miDebuggerPath": "D:/qt/Qt5.14.2/5.14.2/mingw73_64/bin/gdb.exe",
"visualizerFile": "c:\\Users\\sunqu\\AppData\\Roaming\\Code\\User\\workspaceStorage\\7f93734217a2e383fe34beaf49d497fe\\tonka3000.qtvsctools\\qt.natvis.xml" "visualizerFile": "c:\\Users\\sunqu\\AppData\\Roaming\\Trae CN\\User\\workspaceStorage\\7f93734217a2e383fe34beaf49d497fe\\tonka3000.qtvsctools\\qt.natvis.xml"
} }
] ]
} }

View File

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

View File

@ -3,23 +3,24 @@
#include "global.h" #include "global.h"
namespace Global { namespace Global
{
Mode _mode = Mode::Analysis; Mode _mode = Mode::Analysis;
AxisMode _axisMode = AxisMode::SingleY; AxisMode _axisMode = AxisMode::SingleY;
QVector<CurveFileData> _curveFileDataVtr; QVector<CurveFileData> _curveFileDataVtr;
int _currentPhase = 0; int _currentPhase = 0;
ExperimentInfo _experimentInfo; ExperimentInfo _experimentInfo;
QVector<CurveExperimentData> _curveExperimentDataVtr; QVector<CurveExperimentData> _curveExperimentDataVtr;
CurveExperimentData *_currentCurveExperimentDataPtr = nullptr; CurveExperimentData *_currentCurveExperimentDataPtr = nullptr;
bool _smoothnessFlag = false; bool _smoothnessFlag = false;
QVector<CurveExperimentData> _curveSmoothnessDataVtr; QVector<CurveExperimentData> _curveSmoothnessDataVtr;
QString _smoothnessFileName; QString _smoothnessFileName;
bool _enthalpyCoefficientEnableFlag = false; bool _enthalpyCoefficientEnableFlag = false;
QVector<double> _enthalpyCoefficientVtr; QVector<double> _enthalpyCoefficientVtr;
bool _displayTimeValue = false; bool _displayTimeValue = false;
@ -29,18 +30,21 @@ namespace Global {
bool _experimentOITFlag = false; bool _experimentOITFlag = false;
// OIT auto mode. // OIT auto mode.
bool _OITAutoAnalysisModeFlag = false; bool _OITAutoAnalysisModeFlag = false;
double _OITAutoAnalysisCoefficient = OITAutoAnalysisDefaultCoefficient; double _OITAutoAnalysisCoefficient = OITAutoAnalysisDefaultCoefficient;
double _OITAutoAnalysisThreshold = OITAutoAnalysisDefaultThreshold; double _OITAutoAnalysisThreshold = OITAutoAnalysisDefaultThreshold;
// 实验文件 // 实验文件
QStringList _fileList; QStringList _fileList;
QString converDoubleToStr(const double num) { QString converDoubleToStr(const double num)
{
return QString::number(num, 'f', 3); return QString::number(num, 'f', 3);
} }
void quadraticLeastSquaresFit(double x[], double y[], int n, double coeff[]) { void quadraticLeastSquaresFit(double x[], double y[], int n, double coeff[])
if (n < 3) { {
if (n < 3)
{
throw std::invalid_argument("At least 3 data points are required for quadratic fitting"); throw std::invalid_argument("At least 3 data points are required for quadratic fitting");
} }
@ -48,12 +52,13 @@ namespace Global {
double sum_y = 0, sum_xy = 0, sum_x2y = 0; double sum_y = 0, sum_xy = 0, sum_x2y = 0;
// 计算各项累加和 // 计算各项累加和
for (int i = 0; i < n; ++i) { for (int i = 0; i < n; ++i)
double xi = x[i]; {
double xi = x[i];
double xi2 = xi * xi; double xi2 = xi * xi;
double xi3 = xi2 * xi; double xi3 = xi2 * xi;
double xi4 = xi3 * xi; double xi4 = xi3 * xi;
double yi = y[i]; double yi = y[i];
sum_x += xi; sum_x += xi;
sum_x2 += xi2; sum_x2 += xi2;
@ -66,50 +71,61 @@ namespace Global {
// 构建正规方程组的增广矩阵 // 构建正规方程组的增广矩阵
double matrix[3][4] = { double matrix[3][4] = {
{ sum_x4, sum_x3, sum_x2, sum_x2y }, // 对应方程: a*Σx⁴ + b*Σx³ + c*Σx² = Σx²y {sum_x4, sum_x3, sum_x2, sum_x2y}, // 对应方程: a*Σx⁴ + b*Σx³ + c*Σx² = Σx²y
{ sum_x3, sum_x2, sum_x, sum_xy }, // 对应方程: a*Σx³ + b*Σx² + c*Σx = Σxy {sum_x3, sum_x2, sum_x, sum_xy}, // 对应方程: a*Σx³ + b*Σx² + c*Σx = Σxy
{ sum_x2, sum_x, static_cast<double>(n), sum_y } // 对应方程: a*Σx² + b*Σx + c*n = Σy {sum_x2, sum_x, static_cast<double>(n), sum_y} // 对应方程: a*Σx² + b*Σx + c*n = Σy
}; };
// 高斯消元法解方程组 // 高斯消元法解方程组
for (int i = 0; i < 3; ++i) { for (int i = 0; i < 3; ++i)
{
// 部分主元选择 // 部分主元选择
int maxRow = i; int maxRow = i;
for (int k = i + 1; k < 3; ++k) { for (int k = i + 1; k < 3; ++k)
if (std::abs(matrix[k][i]) > std::abs(matrix[maxRow][i])) { {
if (std::abs(matrix[k][i]) > std::abs(matrix[maxRow][i]))
{
maxRow = k; maxRow = k;
} }
} }
// 交换行 // 交换行
for (int k = i; k < 4; ++k) { for (int k = i; k < 4; ++k)
{
std::swap(matrix[i][k], matrix[maxRow][k]); std::swap(matrix[i][k], matrix[maxRow][k]);
} }
// 消元 // 消元
for (int k = i + 1; k < 3; ++k) { for (int k = i + 1; k < 3; ++k)
{
double factor = matrix[k][i] / matrix[i][i]; double factor = matrix[k][i] / matrix[i][i];
for (int j = i; j < 4; ++j) { for (int j = i; j < 4; ++j)
{
matrix[k][j] -= factor * matrix[i][j]; matrix[k][j] -= factor * matrix[i][j];
} }
} }
} }
// 回代求解 // 回代求解
coeff[2] = matrix[2][3] / matrix[2][2]; // c coeff[2] = matrix[2][3] / matrix[2][2]; // c
coeff[1] = (matrix[1][3] - matrix[1][2] * coeff[2]) / matrix[1][1]; // b coeff[1] = (matrix[1][3] - matrix[1][2] * coeff[2]) / matrix[1][1]; // b
coeff[0] = (matrix[0][3] - matrix[0][2] * coeff[2] - matrix[0][1] * coeff[1]) / matrix[0][0]; // a coeff[0] = (matrix[0][3] - matrix[0][2] * coeff[2] - matrix[0][1] * coeff[1]) / matrix[0][0]; // a
} }
// 计算一元一次函数在给定区间内开始变成负值的点 // 计算一元一次函数在给定区间内开始变成负值的点
double findNegativeStartPoint(double m, double b, double start, double end) { double findNegativeStartPoint(double m, double b, double start, double end)
{
// 处理斜率为零的情况 // 处理斜率为零的情况
if (m == 0) { if (m == 0)
{
// 当斜率为 0 时,函数值为常数 b // 当斜率为 0 时,函数值为常数 b
if (b < 0) { if (b < 0)
return start; // 若 b 为负,函数在区间起始点就为负 {
} else { return start; // 若 b 为负,函数在区间起始点就为负
return std::numeric_limits<double>::infinity(); // 若 b 非负,函数在区间内不会变负 }
else
{
return std::numeric_limits<double>::infinity(); // 若 b 非负,函数在区间内不会变负
} }
} }
@ -117,20 +133,26 @@ namespace Global {
double zeroPoint = -b / m; double zeroPoint = -b / m;
// 检查零点是否在给定区间内 // 检查零点是否在给定区间内
if (zeroPoint >= start && zeroPoint <= end) { if (zeroPoint >= start && zeroPoint <= end)
return zeroPoint; // 零点在区间内,函数在此点开始变负 {
return zeroPoint; // 零点在区间内,函数在此点开始变负
} }
// 根据斜率正负判断函数单调性,进而判断函数在区间内是否会变负 // 根据斜率正负判断函数单调性,进而判断函数在区间内是否会变负
if (m > 0) { if (m > 0)
{
// 斜率大于 0函数单调递增 // 斜率大于 0函数单调递增
if (m * start + b < 0) { if (m * start + b < 0)
return start; // 起始点函数值为负,函数在起始点就为负 {
return start; // 起始点函数值为负,函数在起始点就为负
} }
} else { }
else
{
// 斜率小于 0函数单调递减 // 斜率小于 0函数单调递减
if (m * end + b < 0) { if (m * end + b < 0)
return end; // 结束点函数值为负,函数在结束点开始为负 {
return end; // 结束点函数值为负,函数在结束点开始为负
} }
} }
@ -138,22 +160,26 @@ namespace Global {
return std::numeric_limits<double>::infinity(); return std::numeric_limits<double>::infinity();
} }
void clearExperimentData() { void clearExperimentData()
{
_curveExperimentDataVtr.clear(); _curveExperimentDataVtr.clear();
_currentCurveExperimentDataPtr = nullptr; _currentCurveExperimentDataPtr = nullptr;
_currentPhase = -1; _currentPhase = -1;
} }
bool isZero(double value, double epsilon) { bool isZero(double value, double epsilon)
{
return std::abs(value) < epsilon; return std::abs(value) < epsilon;
} }
bool isEqual(const double a, const double b) { bool isEqual(const double a, const double b)
const double tolerance = 1e-5; // 容差值,可以根据需要调整 {
const double tolerance = 1e-5; // 容差值,可以根据需要调整
return std::fabs(a - b) < tolerance; return std::fabs(a - b) < tolerance;
} }
QString getFileName(const QString filePath) { QString getFileName(const QString filePath)
{
QFileInfo fileInfo(filePath); QFileInfo fileInfo(filePath);
// 获取文件的后缀名并转换为小写,方便比较 // 获取文件的后缀名并转换为小写,方便比较
@ -162,35 +188,37 @@ namespace Global {
return fileInfo.fileName(); return fileInfo.fileName();
} }
double converStrToDouble(const QString str) { double converStrToDouble(const QString str)
bool ok; {
double value = str.toDouble(&ok); // 将字符串转换为 double并检查是否成功 bool ok;
if (!ok) { double value = str.toDouble(&ok); // 将字符串转换为 double并检查是否成功
if (!ok)
{
qDebug() << "转换失败,输入的字符串不是有效的数字"; qDebug() << "转换失败,输入的字符串不是有效的数字";
return 0.0; // 如果转换失败,返回默认值 return 0.0; // 如果转换失败,返回默认值
} }
return value; return value;
} }
bool isFileExist(const QString &fileName) { bool isFileExist(const QString &fileName)
{
return _fileList.contains(fileName); return _fileList.contains(fileName);
} }
void updateFileList()
{
_fileList.clear();
void updateFileList() QDir dir(SampleDataFloder);
{ _fileList.append(dir.entryList(QDir::Files));
_fileList.clear();
QDir dir(SampleDataFloder);
_fileList.append(dir.entryList(QDir::Files));
#if 0 #if 0
dir.setPath(BaseLineFolder); dir.setPath(BaseLineFolder);
_fileList.append(dir.entryList(QDir::Files)); _fileList.append(dir.entryList(QDir::Files));
#endif #endif
dir.setPath(AnalysisStateFolder); dir.setPath(AnalysisStateFolder);
_fileList.append(dir.entryList(QDir::Files)); _fileList.append(dir.entryList(QDir::Files));
} }
} // namespace Global } // namespace Global
#if 0 #if 0
Global::Global() Global::Global()

View File

@ -31,7 +31,8 @@ MainWindow::MainWindow(QWidget *parent)
_coefficientSelectionForm(new CoefficientSelectionForm(this)), _coefficientSelectionForm(new CoefficientSelectionForm(this)),
_printPreviewForm(new PrintPreviewForm(this)), _printPreviewForm(new PrintPreviewForm(this)),
_axisSettingForm(new AxisSettingForm(this)), _axisSettingForm(new AxisSettingForm(this)),
_manuallyStopTheExperimentFlag(false) { _manuallyStopTheExperimentFlag(false)
{
ui->setupUi(this); ui->setupUi(this);
ui->actionOITAutoAnalysisMode->setVisible(false); ui->actionOITAutoAnalysisMode->setVisible(false);
ui->toolBar->setWindowTitle("工具栏"); ui->toolBar->setWindowTitle("工具栏");
@ -84,44 +85,58 @@ MainWindow::MainWindow(QWidget *parent)
// ui->actionStop->setEnabled(false); // ui->actionStop->setEnabled(false);
} }
MainWindow::~MainWindow() { MainWindow::~MainWindow()
{
delete ui; delete ui;
} }
void MainWindow::slotContextMenuShow(const QPoint point) { void MainWindow::slotContextMenuShow(const QPoint point)
{
_contextMenu->exec(point); _contextMenu->exec(point);
} }
void MainWindow::slotUpdateStatusbarMsg(const QString msg) { void MainWindow::slotUpdateStatusbarMsg(const QString msg)
{
ui->statusbar->showMessage(msg); ui->statusbar->showMessage(msg);
} }
void MainWindow::slotOITAutoAnalysis(const double x1, const double x2) { void MainWindow::slotOITAutoAnalysis(const double x1, const double x2)
{
on_actionStop_triggered(); on_actionStop_triggered();
_centralWidget->setAnalysisMode(CentralWidget::AnalysisMode::OIT); _centralWidget->setAnalysisMode(CentralWidget::AnalysisMode::OIT);
_centralWidget->setVerticalLineRange(x1, x2); _centralWidget->setVerticalLineRange(x1, x2);
} }
void MainWindow::slotStartExperiment() { void MainWindow::slotStartExperiment()
{
startExperimentByDeviceInfo(); startExperimentByDeviceInfo();
} }
void MainWindow::closeEvent(QCloseEvent *event) { void MainWindow::closeEvent(QCloseEvent *event)
{
// 弹出确认对话框 // 弹出确认对话框
QMessageBox::StandardButton reply; QMessageBox::StandardButton reply;
reply = QMessageBox::question(this, "确认退出", "你确定要退出吗?", reply = QMessageBox::question(this, "确认退出", "你确定要退出吗?",
QMessageBox::Yes | QMessageBox::No); QMessageBox::Yes | QMessageBox::No);
if (reply == QMessageBox::Yes) { if (reply == QMessageBox::Yes)
event->accept(); // 接受关闭事件,关闭窗口 {
} else { event->accept(); // 接受关闭事件,关闭窗口
event->ignore(); // 忽略关闭事件,不关闭窗口 }
else
{
event->ignore(); // 忽略关闭事件,不关闭窗口
} }
} }
void MainWindow::connections() { void MainWindow::connections()
{
// ui // ui
connect(_expertmentSettingForm, &ExperimentSettingForm::sigDeliverData, connect(_expertmentSettingForm, &ExperimentSettingForm::sigDeliverData,
SerialPort::instance(), &SerialPort::slotDeliverData); SerialPort::instance(), &SerialPort::slotDeliverData);
// 左侧文件管理子窗口相关函数
connect(_leftWidget, &LeftWidget::sigDeleteActionTriggered,
this, &MainWindow::slotDeleteActionTriggered);
#if 1 #if 1
// SerialPort. // SerialPort.
connect(SerialPort::instance(), &SerialPort::sigSendCommonData, connect(SerialPort::instance(), &SerialPort::sigSendCommonData,
@ -172,7 +187,8 @@ void MainWindow::connections() {
_centralWidget, &CentralWidget::slotAnalysisSettingCancel); _centralWidget, &CentralWidget::slotAnalysisSettingCancel);
connect(_centralWidget, &CentralWidget::sigRightDockWidgetHide, connect(_centralWidget, &CentralWidget::sigRightDockWidgetHide,
[&]() { _rightWidget->hide(); }); [&]()
{ _rightWidget->hide(); });
connect(_degreeOfCrystallinityForm, &DegreeOfCrystallinityForm::sigDrawCustomText, connect(_degreeOfCrystallinityForm, &DegreeOfCrystallinityForm::sigDrawCustomText,
_centralWidget, &CentralWidget::slotDrawCustomText); _centralWidget, &CentralWidget::slotDrawCustomText);
@ -196,13 +212,17 @@ void MainWindow::connections() {
this, &MainWindow::slotOITAutoAnalysis); this, &MainWindow::slotOITAutoAnalysis);
} }
void MainWindow::setActionEnable(const bool flag) { void MainWindow::setActionEnable(const bool flag)
if (flag) { {
if (flag)
{
ui->actionNew->setEnabled(true); ui->actionNew->setEnabled(true);
ui->actionStart->setEnabled(true); ui->actionStart->setEnabled(true);
ui->actionStop->setEnabled(true); ui->actionStop->setEnabled(true);
ui->actionRealTimeWidget->setEnabled(true); ui->actionRealTimeWidget->setEnabled(true);
} else { }
else
{
ui->actionNew->setEnabled(false); ui->actionNew->setEnabled(false);
ui->actionStart->setEnabled(false); ui->actionStart->setEnabled(false);
ui->actionStop->setEnabled(false); ui->actionStop->setEnabled(false);
@ -210,7 +230,8 @@ void MainWindow::setActionEnable(const bool flag) {
} }
} }
void MainWindow::setSubWidgetAttribute(QWidget *widget) { void MainWindow::setSubWidgetAttribute(QWidget *widget)
{
widget->setWindowModality(Qt::ApplicationModal); widget->setWindowModality(Qt::ApplicationModal);
widget->setWindowFlags(Qt::Dialog); widget->setWindowFlags(Qt::Dialog);
@ -262,48 +283,63 @@ bool MainWindow::saveAnalysisFile(const QString fileName)
#endif #endif
bool MainWindow::saveFile(const QString fileName, const Global::Mode mode, bool MainWindow::saveFile(const QString fileName, const Global::Mode mode,
QString &finalFileName, const bool autoSaveFlag) { QString &finalFileName, const bool autoSaveFlag)
{
logde << "save file..."; logde << "save file...";
QString localFileName = fileName; QString localFileName = fileName;
if (fileName.isEmpty()) { if (fileName.isEmpty())
{
localFileName = "new"; localFileName = "new";
} }
QString folder; QString folder;
if (mode == Global::Mode::None) { if (mode == Global::Mode::None)
{
folder = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation); folder = QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation);
} else if (mode == Global::Mode::Analysis) { }
else if (mode == Global::Mode::Analysis)
{
folder = Global::AnalysisStateFolder; folder = Global::AnalysisStateFolder;
} else if (mode == Global::Mode::Experiment) { }
else if (mode == Global::Mode::Experiment)
{
folder = Global::SampleDataFloder; folder = Global::SampleDataFloder;
} }
QString filePath; QString filePath;
if (autoSaveFlag) { if (autoSaveFlag)
{
localFileName = _leftWidget->filePathCheck(fileName, folder); localFileName = _leftWidget->filePathCheck(fileName, folder);
filePath = folder + "/" + localFileName + ".xlsx"; filePath = folder + "/" + localFileName + ".xlsx";
} else { }
else
{
QString xlsxfilePath = folder + "/" + localFileName + ".xlsx"; QString xlsxfilePath = folder + "/" + localFileName + ".xlsx";
filePath = QFileDialog::getSaveFileName(nullptr, "Save experiment file", filePath = QFileDialog::getSaveFileName(nullptr, "Save experiment file",
xlsxfilePath, "Excel Files (*.xlsx)"); xlsxfilePath, "Excel Files (*.xlsx)");
} }
// //
finalFileName = localFileName + ".xlsx"; finalFileName = localFileName + ".xlsx";
logde << "filePath:" << filePath.toStdString(); logde << "filePath:" << filePath.toStdString();
if (filePath.isEmpty()) { if (filePath.isEmpty())
{
qDebug() << "User cancel the operation."; qDebug() << "User cancel the operation.";
return false; return false;
} }
// Save file. // Save file.
if (mode == Global::Mode::Analysis) { if (mode == Global::Mode::Analysis)
if (Global::_curveFileDataVtr.empty()) { {
if (Global::_curveFileDataVtr.empty())
{
// 分析模式下,但是文件数据为空,说明做完实验没有保存数据。 // 分析模式下,但是文件数据为空,说明做完实验没有保存数据。
XlsxHandler::writeExperimentFile(filePath); XlsxHandler::writeExperimentFile(filePath);
} else { }
else
{
// 分析模式下,存在文件数据,将文件数据写入文件。 // 分析模式下,存在文件数据,将文件数据写入文件。
XlsxHandler::writeXlsxFile(filePath); XlsxHandler::writeXlsxFile(filePath);
#if 0 #if 0
@ -316,57 +352,72 @@ bool MainWindow::saveFile(const QString fileName, const Global::Mode mode,
} }
#endif #endif
} }
} else if (mode == Global::Mode::Experiment) { }
else if (mode == Global::Mode::Experiment)
{
XlsxHandler::writeExperimentFile(filePath); XlsxHandler::writeExperimentFile(filePath);
} }
return true; return true;
} }
void MainWindow::smoothness(const int level) { void MainWindow::smoothness(const int level)
{
logde << "smoothness..."; logde << "smoothness...";
slotUpdateStatusbarMsg("数据平滑计算中..."); slotUpdateStatusbarMsg("数据平滑计算中...");
if (!Global::_curveExperimentDataVtr.empty()) { if (!Global::_curveExperimentDataVtr.empty())
{
// 当前数据为实验数据时,需要把所有的当前实验数据都进行平滑处理。 // 当前数据为实验数据时,需要把所有的当前实验数据都进行平滑处理。
// 删除所有objectName为experiment的curve. // 删除所有objectName为experiment的curve.
_centralWidget->deleteCurveByObjectName(Global::ObjectNameExperiemnt); _centralWidget->deleteCurveByObjectName(Global::ObjectNameExperiemnt);
// 添加所有平滑后的curve. // 添加所有平滑后的curve.
for (auto &item : Global::_curveExperimentDataVtr) { for (auto &item : Global::_curveExperimentDataVtr)
{
item.smoothDataVtr = smoothnessDetail(level, item.dataVtr); item.smoothDataVtr = smoothnessDetail(level, item.dataVtr);
item.curve = _centralWidget->addCurveData(item.smoothDataVtr, item.curve = _centralWidget->addCurveData(item.smoothDataVtr,
Global::ObjectNameExperiemnt); Global::ObjectNameExperiemnt);
} }
} else { }
else
{
// 当前数据为文件分析数据时,需要把当前文件下的所有数据都进行平滑处理。 // 当前数据为文件分析数据时,需要把当前文件下的所有数据都进行平滑处理。
QString selectedCurveObjectName = _centralWidget->getCurrentCurve()->objectName(); QString selectedCurveObjectName = _centralWidget->getCurrentCurve()->objectName();
_centralWidget->deleteCurveByObjectName(selectedCurveObjectName); _centralWidget->deleteCurveByObjectName(selectedCurveObjectName);
for (Global::CurveFileData &cfd : Global::_curveFileDataVtr) { for (Global::CurveFileData &cfd : Global::_curveFileDataVtr)
if (selectedCurveObjectName.contains(cfd.filePath)) { {
for (Global::PhaseTotalInfo &pti : cfd.phaseTotalVtr) { if (selectedCurveObjectName.contains(cfd.filePath))
{
for (Global::PhaseTotalInfo &pti : cfd.phaseTotalVtr)
{
pti.smoothDataVtr = smoothnessDetail(level, pti.dataVtr); pti.smoothDataVtr = smoothnessDetail(level, pti.dataVtr);
pti.curve = _centralWidget->addCurveData(pti.smoothDataVtr, pti.curve = _centralWidget->addCurveData(pti.smoothDataVtr,
cfd.filePath); cfd.filePath);
} }
} }
} }
} }
} }
QVector<Global::ExperimentData> MainWindow::smoothnessDetail(const int level, const QVector<Global::ExperimentData> &dataVtr) { QVector<Global::ExperimentData> MainWindow::smoothnessDetail(const int level, const QVector<Global::ExperimentData> &dataVtr)
{
Lowess::Config config; Lowess::Config config;
config.smoothingFactor = level * 0.01; config.smoothingFactor = level * 0.01;
config.robustnessIterations = 3; config.robustnessIterations = 3;
std::vector<double> x; std::vector<double> x;
std::vector<double> y; std::vector<double> y;
for (const Global::ExperimentData &ed : dataVtr) { for (const Global::ExperimentData &ed : dataVtr)
if (Global::_axisMode == Global::AxisMode::SingleY) { {
if (Global::_axisMode == Global::AxisMode::SingleY)
{
x.push_back(ed.sampleTemp); x.push_back(ed.sampleTemp);
} else { }
else
{
x.push_back(ed.runTime); x.push_back(ed.runTime);
} }
@ -385,7 +436,8 @@ QVector<Global::ExperimentData> MainWindow::smoothnessDetail(const int level, co
ui->statusbar->showMessage("数据平滑计算中..."); ui->statusbar->showMessage("数据平滑计算中...");
std::vector<double> yest = Lowess::smooth(x, y, config); std::vector<double> yest = Lowess::smooth(x, y, config);
if (yest.empty()) { if (yest.empty())
{
slotUpdateStatusbarMsg("数据平滑完成."); slotUpdateStatusbarMsg("数据平滑完成.");
return resultVtr; return resultVtr;
} }
@ -396,17 +448,21 @@ QVector<Global::ExperimentData> MainWindow::smoothnessDetail(const int level, co
// result data vector. // result data vector.
for (int i = 0; i < x.size(); i++) { for (int i = 0; i < x.size(); i++)
{
Global::ExperimentData ed; Global::ExperimentData ed;
if (Global::_axisMode == Global::AxisMode::SingleY) { if (Global::_axisMode == Global::AxisMode::SingleY)
{
ed.sampleTemp = x.at(i); ed.sampleTemp = x.at(i);
ed.runTime = dataVtr.at(i).runTime; ed.runTime = dataVtr.at(i).runTime;
} else { }
ed.runTime = x.at(i); else
{
ed.runTime = x.at(i);
ed.sampleTemp = dataVtr.at(i).sampleTemp; ed.sampleTemp = dataVtr.at(i).sampleTemp;
} }
ed.dsc = yest.at(i); ed.dsc = yest.at(i);
ed.constantTempTime = dataVtr.at(i).constantTempTime; ed.constantTempTime = dataVtr.at(i).constantTempTime;
resultVtr.push_back(ed); resultVtr.push_back(ed);
@ -415,7 +471,8 @@ QVector<Global::ExperimentData> MainWindow::smoothnessDetail(const int level, co
return resultVtr; return resultVtr;
} }
void MainWindow::smoothnessExperimentData(const int level) { void MainWindow::smoothnessExperimentData(const int level)
{
#if 0 #if 0
for(int i = 0;i < Global::_curveExperimentDataVtr.size();i++){ for(int i = 0;i < Global::_curveExperimentDataVtr.size();i++){
Global::CurveExperimentData ced = Global::_curveExperimentDataVtr.at(i); Global::CurveExperimentData ced = Global::_curveExperimentDataVtr.at(i);
@ -423,19 +480,21 @@ void MainWindow::smoothnessExperimentData(const int level) {
} }
#endif #endif
for (auto &item : Global::_curveExperimentDataVtr) { for (auto &item : Global::_curveExperimentDataVtr)
{
smoothnessDetail(level, item.dataVtr); smoothnessDetail(level, item.dataVtr);
} }
} }
void MainWindow::startExperiment() { void MainWindow::startExperiment()
{
QByteArray ba = DataParser::setDeviceStartStop(DeviceStartMode::Start); QByteArray ba = DataParser::setDeviceStartStop(DeviceStartMode::Start);
QString hexData = ba.toHex(' '); QString hexData = ba.toHex(' ');
SerialPort::instance()->slotSendData(ba); SerialPort::instance()->slotSendData(ba);
Global::_mode = Global::Mode::Experiment; Global::_mode = Global::Mode::Experiment;
_manuallyStopTheExperimentFlag = false; _manuallyStopTheExperimentFlag = false;
_centralWidget->startExperiment(); _centralWidget->startExperiment();
@ -445,8 +504,9 @@ void MainWindow::startExperiment() {
ui->menu_4->menuAction()->setEnabled(false); ui->menu_4->menuAction()->setEnabled(false);
} }
void MainWindow::startExperimentByDeviceInfo() { void MainWindow::startExperimentByDeviceInfo()
Global::_mode = Global::Mode::Experiment; {
Global::_mode = Global::Mode::Experiment;
_manuallyStopTheExperimentFlag = false; _manuallyStopTheExperimentFlag = false;
_centralWidget->startExperiment(); _centralWidget->startExperiment();
@ -454,15 +514,18 @@ void MainWindow::startExperimentByDeviceInfo() {
Global::clearExperimentData(); Global::clearExperimentData();
} }
// 停止实验 // 停止实验
void MainWindow::on_actionStop_triggered() { void MainWindow::on_actionStop_triggered()
{
logde << " Stop experiment ...++++++++++++++++++"; logde << " Stop experiment ...++++++++++++++++++";
if (!SerialPort::instance()->isOpen()) { if (!SerialPort::instance()->isOpen())
{
showMesgBox("设备未连接,请先连接设备。"); showMesgBox("设备未连接,请先连接设备。");
return; return;
} }
if (Global::_mode == Global::Mode::Experiment) { if (Global::_mode == Global::Mode::Experiment)
{
QByteArray ba = DataParser::setDeviceStartStop(DeviceStartMode::Stop); QByteArray ba = DataParser::setDeviceStartStop(DeviceStartMode::Stop);
SerialPort::instance()->slotSendData(ba); SerialPort::instance()->slotSendData(ba);
@ -477,7 +540,8 @@ void MainWindow::on_actionStop_triggered() {
logde << "on_actionStop_triggered saveFile ..."; logde << "on_actionStop_triggered saveFile ...";
QString finalFileName; QString finalFileName;
if (saveFile(Global::_experimentInfo.sampleName, Global::Mode::Experiment, finalFileName, true)) { if (saveFile(Global::_experimentInfo.sampleName, Global::Mode::Experiment, finalFileName, true))
{
_leftWidget->reloadFileName(); _leftWidget->reloadFileName();
QString str = QString("%1 文件保存成功。").arg(finalFileName); QString str = QString("%1 文件保存成功。").arg(finalFileName);
@ -492,19 +556,23 @@ void MainWindow::on_actionStop_triggered() {
ui->menu_4->menuAction()->setEnabled(true); ui->menu_4->menuAction()->setEnabled(true);
} }
void MainWindow::on_actionNew_triggered() { void MainWindow::on_actionNew_triggered()
if (!SerialPort::instance()->isOpen()) { {
if (!SerialPort::instance()->isOpen())
{
showMesgBox("设备未连接,请先连接设备。"); showMesgBox("设备未连接,请先连接设备。");
return; return;
} }
_expertmentSettingForm->show(); _expertmentSettingForm->show();
} }
void MainWindow::on_actionStart_triggered() { void MainWindow::on_actionStart_triggered()
{
logde << "start experiment,set soft into experiment mode."; logde << "start experiment,set soft into experiment mode.";
logde << "```````````````````````````````"; logde << "```````````````````````````````";
if (!SerialPort::instance()->isOpen()) { if (!SerialPort::instance()->isOpen())
{
showMesgBox("设备未连接,请先连接设备。"); showMesgBox("设备未连接,请先连接设备。");
return; return;
} }
@ -514,19 +582,23 @@ void MainWindow::on_actionStart_triggered() {
startExperiment(); startExperiment();
} }
void MainWindow::on_actionReadOnly_triggered() { void MainWindow::on_actionReadOnly_triggered()
{
Global::_mode = Global::Mode::Experiment; Global::_mode = Global::Mode::Experiment;
SerialPort::instance()->openSp(); SerialPort::instance()->openSp();
} }
void MainWindow::on_actionRealTimeWidget_triggered() { void MainWindow::on_actionRealTimeWidget_triggered()
{
_realTimeDataForm->show(); _realTimeDataForm->show();
} }
void MainWindow::slotSaveExperimentalDataMsgBox() { void MainWindow::slotSaveExperimentalDataMsgBox()
{
logde << "_manuallyStopTheExperimentFlag:" << _manuallyStopTheExperimentFlag; logde << "_manuallyStopTheExperimentFlag:" << _manuallyStopTheExperimentFlag;
if (_manuallyStopTheExperimentFlag) { if (_manuallyStopTheExperimentFlag)
{
logde << "_manuallyStopTheExperimentFlag..."; logde << "_manuallyStopTheExperimentFlag...";
return; return;
} }
@ -537,7 +609,8 @@ void MainWindow::slotSaveExperimentalDataMsgBox() {
if (saveFile(Global::_experimentInfo.sampleName, if (saveFile(Global::_experimentInfo.sampleName,
Global::Mode::Experiment, Global::Mode::Experiment,
finalFileName, finalFileName,
true)) { true))
{
_leftWidget->reloadFileName(); _leftWidget->reloadFileName();
QString str = QString("%1 文件保存成功。").arg(finalFileName); QString str = QString("%1 文件保存成功。").arg(finalFileName);
@ -564,10 +637,12 @@ void MainWindow::slotSaveExperimentalDataMsgBox() {
#endif #endif
} }
void MainWindow::on_actionConnectToDev_triggered() { void MainWindow::on_actionConnectToDev_triggered()
{
logde << "connect to device..."; logde << "connect to device...";
if (SerialPort::instance()->isOpen()) { if (SerialPort::instance()->isOpen())
{
logde << "close device."; logde << "close device.";
SerialPort::instance()->closeSp(); SerialPort::instance()->closeSp();
@ -580,10 +655,13 @@ void MainWindow::on_actionConnectToDev_triggered() {
QString str("设备已断开。"); QString str("设备已断开。");
slotUpdateStatusbarMsg(str); slotUpdateStatusbarMsg(str);
showMesgBox(str); showMesgBox(str);
} else { }
else
{
logde << "open device."; logde << "open device.";
if (SerialPort::instance()->openSp()) { if (SerialPort::instance()->openSp())
{
setActionEnable(true); setActionEnable(true);
// Global::instance()->setMode(Global::Mode::ConnectedToDev); // Global::instance()->setMode(Global::Mode::ConnectedToDev);
Global::_mode = Global::Mode::ConnectedToDev; Global::_mode = Global::Mode::ConnectedToDev;
@ -600,38 +678,46 @@ void MainWindow::on_actionConnectToDev_triggered() {
showMesgBox(str); showMesgBox(str);
logde << "open serial port success. "; logde << "open serial port success. ";
} else { }
else
{
// QMessageBox::warning(this, "warnning", "Serial Port open failed."); // QMessageBox::warning(this, "warnning", "Serial Port open failed.");
showMesgBox("设备打开失败。"); showMesgBox("设备打开失败。");
} }
} }
} }
void MainWindow::on_actionStartPoint_triggered() { void MainWindow::on_actionStartPoint_triggered()
{
logde << "start experiment..."; logde << "start experiment...";
_rightWidget->show(); _rightWidget->show();
_centralWidget->setAnalysisMode(CentralWidget::AnalysisMode::StartPoint); _centralWidget->setAnalysisMode(CentralWidget::AnalysisMode::StartPoint);
} }
void MainWindow::on_actionStopPoint_triggered() { void MainWindow::on_actionStopPoint_triggered()
{
_rightWidget->show(); _rightWidget->show();
_centralWidget->setAnalysisMode(CentralWidget::AnalysisMode::StopPoint); _centralWidget->setAnalysisMode(CentralWidget::AnalysisMode::StopPoint);
} }
void MainWindow::on_actionNumericalLabel_triggered() { void MainWindow::on_actionNumericalLabel_triggered()
{
_rightWidget->show(); _rightWidget->show();
_centralWidget->setAnalysisMode(CentralWidget::AnalysisMode::NumericalLabel); _centralWidget->setAnalysisMode(CentralWidget::AnalysisMode::NumericalLabel);
} }
void MainWindow::on_actionPeakSynthesisAnalysis_triggered() { void MainWindow::on_actionPeakSynthesisAnalysis_triggered()
{
_rightWidget->show(); _rightWidget->show();
_centralWidget->setAnalysisMode(CentralWidget::AnalysisMode::PeakSynthesisAnalysis); _centralWidget->setAnalysisMode(CentralWidget::AnalysisMode::PeakSynthesisAnalysis);
} }
void MainWindow::on_actionClearAllData_triggered() { void MainWindow::on_actionClearAllData_triggered()
{
// 实验过程中,不允许清除数据。 // 实验过程中,不允许清除数据。
if (Global::_mode == Global::Mode::Experiment) { if (Global::_mode == Global::Mode::Experiment)
{
return; return;
} }
@ -641,62 +727,75 @@ void MainWindow::on_actionClearAllData_triggered() {
_centralWidget->clearAllData(); _centralWidget->clearAllData();
} }
void MainWindow::on_actionGlassTransition_triggered() { void MainWindow::on_actionGlassTransition_triggered()
{
_rightWidget->show(); _rightWidget->show();
_centralWidget->setAnalysisMode(CentralWidget::AnalysisMode::GlassTransition); _centralWidget->setAnalysisMode(CentralWidget::AnalysisMode::GlassTransition);
} }
void MainWindow::on_actionOIT_triggered() { void MainWindow::on_actionOIT_triggered()
{
_rightWidget->show(); _rightWidget->show();
_centralWidget->setAnalysisMode(CentralWidget::AnalysisMode::OIT); _centralWidget->setAnalysisMode(CentralWidget::AnalysisMode::OIT);
} }
void MainWindow::on_actionSpecificHeatCompMethod_triggered() { void MainWindow::on_actionSpecificHeatCompMethod_triggered()
{
_specificHeatComparisonMethodForm->show(); _specificHeatComparisonMethodForm->show();
} }
void MainWindow::on_actionDegreeOfCrystallinity_triggered() { void MainWindow::on_actionDegreeOfCrystallinity_triggered()
{
// QMessageBox::warning(this, "warnning", "结晶度."); // QMessageBox::warning(this, "warnning", "结晶度.");
_degreeOfCrystallinityForm->show(); _degreeOfCrystallinityForm->show();
} }
void MainWindow::on_actionInstrumentParameter_triggered() { void MainWindow::on_actionInstrumentParameter_triggered()
{
_instrumentCoefficientForm->show(); _instrumentCoefficientForm->show();
} }
void MainWindow::on_actionOITAutoAnalysisParam_triggered()
void MainWindow::on_actionOITAutoAnalysisParam_triggered() { {
_OITAutoAnalysisParamForm->show(); _OITAutoAnalysisParamForm->show();
} }
void MainWindow::on_actionOITAutoAnalysisMode_triggered() { void MainWindow::on_actionOITAutoAnalysisMode_triggered()
{
} }
void MainWindow::on_actionTimeAxisAnalysisPCTMode_triggered() { void MainWindow::on_actionTimeAxisAnalysisPCTMode_triggered()
{
Global::_displayTimeValue = ui->actionTimeAxisAnalysisPCTMode->isChecked(); Global::_displayTimeValue = ui->actionTimeAxisAnalysisPCTMode->isChecked();
} }
void MainWindow::on_actionDegreeOfCuring_triggered() { void MainWindow::on_actionDegreeOfCuring_triggered()
{
// //
_degreeOfCureForm->show(); _degreeOfCureForm->show();
} }
void MainWindow::on_actionAbout_triggered() { void MainWindow::on_actionAbout_triggered()
{
_aboutForm->show(); _aboutForm->show();
} }
void MainWindow::on_actionEnthalpyCorrectionEdit_triggered() { void MainWindow::on_actionEnthalpyCorrectionEdit_triggered()
{
_enthalpyDataCorrectionForm->show(); _enthalpyDataCorrectionForm->show();
} }
void MainWindow::on_actionEnthalpyCorrectionSelection_triggered() { void MainWindow::on_actionEnthalpyCorrectionSelection_triggered()
{
_coefficientSelectionForm->show(); _coefficientSelectionForm->show();
} }
void MainWindow::on_actionPrintPreview_triggered() { void MainWindow::on_actionPrintPreview_triggered()
{
logde << "print preview..."; logde << "print preview...";
if (Global::_curveFileDataVtr.empty()) { if (Global::_curveFileDataVtr.empty())
{
showMesgBox("请先打开数据。"); showMesgBox("请先打开数据。");
return; return;
} }
@ -706,103 +805,132 @@ void MainWindow::on_actionPrintPreview_triggered() {
// _printPreviewForm->setOrientation(); // _printPreviewForm->setOrientation();
_printPreviewForm->_customPrintPreviewDialog->exec(); _printPreviewForm->_customPrintPreviewDialog->exec();
_printPreviewForm->_customPrintPreviewDialog->update(); // 可选,强制刷新 _printPreviewForm->_customPrintPreviewDialog->update(); // 可选,强制刷新
} }
void MainWindow::on_actionOnsetTemperaturePoint_triggered() { void MainWindow::on_actionOnsetTemperaturePoint_triggered()
{
_rightWidget->show(); _rightWidget->show();
_centralWidget->setAnalysisMode(CentralWidget::AnalysisMode::OnsetTemperaturePoint); _centralWidget->setAnalysisMode(CentralWidget::AnalysisMode::OnsetTemperaturePoint);
} }
void MainWindow::on_actionEndsetTemperaturePoint_triggered() { void MainWindow::on_actionEndsetTemperaturePoint_triggered()
{
_rightWidget->show(); _rightWidget->show();
_centralWidget->setAnalysisMode(CentralWidget::AnalysisMode::EndsetTemperaturePoint); _centralWidget->setAnalysisMode(CentralWidget::AnalysisMode::EndsetTemperaturePoint);
} }
void MainWindow::on_actionYAxis_triggered() { void MainWindow::on_actionYAxis_triggered()
{
_centralWidget->switchAxisMode(); _centralWidget->switchAxisMode();
} }
void MainWindow::on_actionAxisSetting_triggered() { void MainWindow::on_actionAxisSetting_triggered()
{
_axisSettingForm->show(); _axisSettingForm->show();
} }
void MainWindow::on_actionSaveData_triggered() { void MainWindow::on_actionSaveData_triggered()
{
QString finaleFileName; QString finaleFileName;
saveFile(Global::_experimentInfo.sampleName, Global::_mode, finaleFileName); saveFile(Global::_experimentInfo.sampleName, Global::_mode, finaleFileName);
_leftWidget->reloadFileName(); _leftWidget->reloadFileName();
} }
void MainWindow::on_actionSaveas_triggered() { void MainWindow::on_actionSaveas_triggered()
{
QString finaleFileName; QString finaleFileName;
saveFile(Global::_experimentInfo.sampleName, Global::Mode::None, finaleFileName); saveFile(Global::_experimentInfo.sampleName, Global::Mode::None, finaleFileName);
_leftWidget->reloadFileName(); _leftWidget->reloadFileName();
} }
void MainWindow::on_actionLanguage_triggered() { void MainWindow::on_actionLanguage_triggered()
if (Global::_languageType == Global::LanguageType::Chinese) { {
if (Global::_languageType == Global::LanguageType::Chinese)
{
Global::_languageType = Global::LanguageType::English; Global::_languageType = Global::LanguageType::English;
ui->actionLanguage->setText(Global::EnglishStr); ui->actionLanguage->setText(Global::EnglishStr);
} else { }
else
{
Global::_languageType = Global::LanguageType::Chinese; Global::_languageType = Global::LanguageType::Chinese;
ui->actionLanguage->setText(Global::ChineseStr); ui->actionLanguage->setText(Global::ChineseStr);
} }
} }
void MainWindow::on_actionSmoothness1_triggered() { void MainWindow::on_actionSmoothness1_triggered()
{
smoothness(1); smoothness(1);
} }
void MainWindow::on_actionSmoothness2_triggered() { void MainWindow::on_actionSmoothness2_triggered()
{
smoothness(2); smoothness(2);
} }
void MainWindow::on_actionSmoothness3_triggered() { void MainWindow::on_actionSmoothness3_triggered()
{
smoothness(3); smoothness(3);
} }
void MainWindow::on_actionSmoothness4_triggered() { void MainWindow::on_actionSmoothness4_triggered()
{
smoothness(4); smoothness(4);
} }
void MainWindow::on_actionSmoothness5_triggered() { void MainWindow::on_actionSmoothness5_triggered()
{
smoothness(5); smoothness(5);
} }
void MainWindow::on_actionSmoothness6_triggered() { void MainWindow::on_actionSmoothness6_triggered()
{
smoothness(6); smoothness(6);
} }
void MainWindow::on_actionSmoothness7_triggered() { void MainWindow::on_actionSmoothness7_triggered()
{
smoothness(7); smoothness(7);
} }
void MainWindow::on_actionSmoothness8_triggered() { void MainWindow::on_actionSmoothness8_triggered()
{
smoothness(8); smoothness(8);
} }
void MainWindow::on_actionSmoothness9_triggered() { void MainWindow::on_actionSmoothness9_triggered()
{
smoothness(9); smoothness(9);
} }
void MainWindow::on_actionSmoothness10_triggered() { void MainWindow::on_actionSmoothness10_triggered()
{
smoothness(10); smoothness(10);
} }
// 原始数据 // 原始数据
void MainWindow::on_actionOriginalData_triggered() { void MainWindow::on_actionOriginalData_triggered()
if (!Global::_curveExperimentDataVtr.empty()) { {
if (!Global::_curveExperimentDataVtr.empty())
{
// 删除所有objectName为experiment的curve. // 删除所有objectName为experiment的curve.
_centralWidget->deleteCurveByObjectName(Global::ObjectNameExperiemnt); _centralWidget->deleteCurveByObjectName(Global::ObjectNameExperiemnt);
for (auto &item : Global::_curveExperimentDataVtr) { for (auto &item : Global::_curveExperimentDataVtr)
{
item.smoothDataVtr.clear(); item.smoothDataVtr.clear();
item.curve = _centralWidget->addCurveData(item.dataVtr, Global::ObjectNameExperiemnt); item.curve = _centralWidget->addCurveData(item.dataVtr, Global::ObjectNameExperiemnt);
} }
} else { }
else
{
// 当前数据为文件分析数据时,需要把当前文件下的所有数据都进行平滑处理。 // 当前数据为文件分析数据时,需要把当前文件下的所有数据都进行平滑处理。
if(_centralWidget->getCurrentCurve() == nullptr){ if (_centralWidget->getCurrentCurve() == nullptr)
{
return; return;
} }
QString selectedCurveObjectName = _centralWidget->getCurrentCurve()->objectName(); QString selectedCurveObjectName = _centralWidget->getCurrentCurve()->objectName();
_centralWidget->deleteCurveByObjectName(selectedCurveObjectName); _centralWidget->deleteCurveByObjectName(selectedCurveObjectName);
for (Global::CurveFileData &cfd : Global::_curveFileDataVtr) { for (Global::CurveFileData &cfd : Global::_curveFileDataVtr)
if (selectedCurveObjectName.contains(cfd.filePath)) { {
for (Global::PhaseTotalInfo &pti : cfd.phaseTotalVtr) { if (selectedCurveObjectName.contains(cfd.filePath))
{
for (Global::PhaseTotalInfo &pti : cfd.phaseTotalVtr)
{
pti.smoothDataVtr.clear(); pti.smoothDataVtr.clear();
pti.curve = _centralWidget->addCurveData(pti.dataVtr, pti.curve = _centralWidget->addCurveData(pti.dataVtr,
cfd.filePath); cfd.filePath);
@ -847,19 +975,23 @@ void MainWindow::on_actionOriginalData_triggered() {
#endif #endif
} }
void MainWindow::showMesgBox(const QString str) { void MainWindow::showMesgBox(const QString str)
{
static bool isShow = false; static bool isShow = false;
if (!isShow) { if (!isShow)
{
isShow = true; isShow = true;
QMessageBox::information(this, "提示", str); QMessageBox::information(this, "提示", str);
isShow = false; isShow = false;
} }
} }
void MainWindow::slotDeviceDisconnected() { void MainWindow::slotDeviceDisconnected()
{
// logde<<"slotDeviceDisconnected...1"; // logde<<"slotDeviceDisconnected...1";
// 如果当前是实验模式时,需要先停止实验。 // 如果当前是实验模式时,需要先停止实验。
if (SerialPort::instance()->isOpen()) { if (SerialPort::instance()->isOpen())
{
// logde<<"slotDeviceDisconnected...2"; // logde<<"slotDeviceDisconnected...2";
// ui更新断开连接 // ui更新断开连接
ui->actionConnectToDev->setIcon(QIcon(":/images/connect.png")); ui->actionConnectToDev->setIcon(QIcon(":/images/connect.png"));
@ -870,3 +1002,17 @@ void MainWindow::slotDeviceDisconnected() {
SerialPort::instance()->closeSp(); SerialPort::instance()->closeSp();
} }
} }
void MainWindow::slotDeleteActionTriggered(const QString &filePath)
{
logde<<"slotDeleteActionTriggered...1:"<<filePath.toStdString();
int ret = QMessageBox::question(this,
tr("请确认"),
tr("确定要删除文件“%1”吗").arg(filePath),
QMessageBox::Ok | QMessageBox::Cancel,
QMessageBox::Ok);
_leftWidget->confirmDelete(ret == QMessageBox::Ok ? true : false);
}

View File

@ -45,6 +45,9 @@ public slots:
void slotStartExperiment(); void slotStartExperiment();
void slotDeviceDisconnected(); void slotDeviceDisconnected();
// 左侧文件管理子窗口操作函数
void slotDeleteActionTriggered(const QString&);
protected: protected:
void closeEvent(QCloseEvent *event) override; void closeEvent(QCloseEvent *event) override;
private slots: private slots:
@ -52,6 +55,7 @@ private slots:
void on_actionConnectToDev_triggered(); void on_actionConnectToDev_triggered();
void on_actionNew_triggered(); void on_actionNew_triggered();
void on_actionStart_triggered(); void on_actionStart_triggered();
// 停止实验 // 停止实验
void on_actionStop_triggered(); void on_actionStop_triggered();
void on_actionReadOnly_triggered(); void on_actionReadOnly_triggered();

View File

@ -1,63 +1,59 @@
#include <qdir.h> #include <QDir>
#include <qdebug.h> #include <QDebug>
#include <QHBoxLayout> #include <QHBoxLayout>
#include <QStyle>
#include <QFileInfo>
#include <QTreeWidgetItemIterator>
#include <QTreeWidget>
#include <QTreeWidgetItem>
#include <QDirIterator>
#include <QMenu>
#include <QAction>
#include <QMessageBox>
#include <QInputDialog>
#include "leftwidget.h" #include "leftwidget.h"
#include "filemanager.h" #include "filemanager.h"
#include "global.h" #include "global.h"
#include "logger.h"
LeftWidget::LeftWidget(QWidget *parent) : QDockWidget(parent) { LeftWidget::LeftWidget(QWidget *parent) : QDockWidget(parent)
{
setWindowTitle("文件浏览"); setWindowTitle("文件浏览");
_treeWidget = new QTreeWidget(); _treeWidget = new QTreeWidget();
_treeWidget->setHeaderHidden(true); _treeWidget->setHeaderHidden(true);
_sampleDataItem = new QTreeWidgetItem(_treeWidget);
_sampleDataItem->setText(0, "样品数据");
#if 0
_baseLineItem = new QTreeWidgetItem(_treeWidget);
_baseLineItem->setText(0,"基线");
#endif
_analysisStateItem = new QTreeWidgetItem(_treeWidget);
_analysisStateItem->setText(0, "分析状态");
_treeWidget->setSortingEnabled(false); _treeWidget->setSortingEnabled(false);
_treeWidget->insertTopLevelItem(0, _sampleDataItem);
// _treeWidget->insertTopLevelItem(1, _baseLineItem);
_treeWidget->insertTopLevelItem(2, _analysisStateItem);
setWidget(_treeWidget); setWidget(_treeWidget);
// init file name. // 初始化文件树
initFileName(_sampleDataItem, Global::SampleDataFloder); reloadFileTree();
#if 0
initFileName(_baseLineItem,Global::BaseLineFolder);
#endif
initFileName(_analysisStateItem, Global::AnalysisStateFolder);
expandAll(_sampleDataItem);
// expandAll(_baseLineItem);
expandAll(_analysisStateItem);
Global::updateFileList();
// connections // connections
connect(_treeWidget, &QTreeWidget::itemDoubleClicked, connect(_treeWidget, &QTreeWidget::itemDoubleClicked,
this, &LeftWidget::slotTreeWidgetItemClicked); this, &LeftWidget::slotTreeWidgetItemClicked);
// 右键菜单 // 右键菜单
_contextMenu = new QMenu(_treeWidget); _contextMenu = new QMenu(_treeWidget);
_deleteAction = new QAction("删除", this); _deleteFileAction = new QAction("删除文件", this);
_contextMenu->addAction(_deleteAction); _createFolderAction = new QAction("新建文件夹", this);
_contextMenu->addAction(_deleteFileAction);
_contextMenu->addAction(_createFolderAction);
_treeWidget->setContextMenuPolicy(Qt::CustomContextMenu); _treeWidget->setContextMenuPolicy(Qt::CustomContextMenu);
connect(_treeWidget, &QTreeWidget::customContextMenuRequested, connect(_treeWidget, &QTreeWidget::customContextMenuRequested,
this, &LeftWidget::slotShowContextMenu); this, &LeftWidget::slotShowContextMenu);
connect(_deleteFileAction, &QAction::triggered,
this, &LeftWidget::slotDeleteActionTriggered);
connect(_createFolderAction, &QAction::triggered,
this, &LeftWidget::slotCreateFolderActionTriggered);
} }
void LeftWidget::reloadFileName() { void LeftWidget::reloadFileName()
{
clearAllChildItems(_sampleDataItem); clearAllChildItems(_sampleDataItem);
// clearAllChildItems(_baseLineItem); // clearAllChildItems(_baseLineItem);
clearAllChildItems(_analysisStateItem); clearAllChildItems(_analysisStateItem);
@ -66,21 +62,25 @@ void LeftWidget::reloadFileName() {
#if 0 #if 0
initFileName(_baseLineItem,Global::BaseLineFolder); initFileName(_baseLineItem,Global::BaseLineFolder);
#endif #endif
initFileName(_analysisStateItem, Global::AnalysisStateFolder); initFileName(_analysisStateItem, Global::AnalysisStateFolder);
// 更新文件列表 // 更新文件列表
Global::updateFileList(); Global::updateFileList();
} }
QString LeftWidget::filePathCheck(const QString fileName, const QString folderPath) { QString LeftWidget::filePathCheck(const QString fileName, const QString folderPath)
{
QString resultFileName = fileName; QString resultFileName = fileName;
QDir dir(folderPath); QDir dir(folderPath);
QStringList files = dir.entryList(QDir::Files); QStringList files = dir.entryList(QDir::Files);
for (const QString &existedFileName : files) { for (const QString &existedFileName : files)
{
QFileInfo fileInfo(existedFileName); QFileInfo fileInfo(existedFileName);
if (fileName == fileInfo.baseName()) { if (fileName == fileInfo.baseName())
{
QDateTime currentDateTime = QDateTime::currentDateTime(); QDateTime currentDateTime = QDateTime::currentDateTime();
QString formattedTime = currentDateTime.toString("yyyy_MM_dd_HH_mm_ss"); QString formattedTime = currentDateTime.toString("yyyy_MM_dd_HH_mm_ss");
resultFileName = fileName + QString("_") + formattedTime; resultFileName = fileName + QString("_") + formattedTime;
break; break;
@ -90,70 +90,89 @@ QString LeftWidget::filePathCheck(const QString fileName, const QString folderPa
return resultFileName; return resultFileName;
} }
void LeftWidget::initData() { void LeftWidget::initData()
{
// const QString folderPath = QDir::currentPath()+"/../experiment_data"; // const QString folderPath = QDir::currentPath()+"/../experiment_data";
const QString folderPath = Global::SampleDataFloder; const QString folderPath = Global::SampleDataFloder;
#if 1 #if 1
QDir dir(folderPath); QDir dir(folderPath);
if (!dir.exists()) { if (!dir.exists())
{
qWarning() << "文件夹不存在: " << folderPath; qWarning() << "文件夹不存在: " << folderPath;
return; return;
} }
// 遍历文件 // 遍历文件
QFileInfoList fileList = dir.entryInfoList(QDir::Files | QDir::NoDotAndDotDot); QFileInfoList fileList = dir.entryInfoList(QDir::Files | QDir::NoDotAndDotDot);
for (const QFileInfo &fileInfo : fileList) { for (const QFileInfo &fileInfo : fileList)
{
QFile file(fileInfo.absoluteFilePath()); QFile file(fileInfo.absoluteFilePath());
if (file.open(QIODevice::ReadOnly | QIODevice::Text)) { if (file.open(QIODevice::ReadOnly | QIODevice::Text))
{
QString content = file.readAll(); QString content = file.readAll();
qDebug() << "读取文件 " << fileInfo.absoluteFilePath() << " 内容: " << content; qDebug() << "读取文件 " << fileInfo.absoluteFilePath() << " 内容: " << content;
file.close(); file.close();
// 写入文件操作示例:这里简单在文件末尾追加一行内容 // 写入文件操作示例:这里简单在文件末尾追加一行内容
if (file.open(QIODevice::Append | QIODevice::Text)) { if (file.open(QIODevice::Append | QIODevice::Text))
{
file.write("\n这是通过递归写入添加的内容"); file.write("\n这是通过递归写入添加的内容");
qDebug() << "已向文件 " << fileInfo.absoluteFilePath() << " 写入内容"; qDebug() << "已向文件 " << fileInfo.absoluteFilePath() << " 写入内容";
file.close(); file.close();
} else { }
else
{
qWarning() << "无法打开文件进行写入: " << fileInfo.absoluteFilePath(); qWarning() << "无法打开文件进行写入: " << fileInfo.absoluteFilePath();
} }
} else { }
else
{
qWarning() << "无法打开文件进行读取: " << fileInfo.absoluteFilePath(); qWarning() << "无法打开文件进行读取: " << fileInfo.absoluteFilePath();
} }
} }
#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;
if (Global::Mode::Analysis != Global::_mode) { if (Global::Mode::Analysis != Global::_mode)
{
return; return;
} }
QString fileName; // 检查是否是文件项(有用户数据)
// 获取父节点 QVariant userData = item->data(0, Qt::UserRole);
QTreeWidgetItem *parentItem = item->parent(); if (userData.isNull() || !userData.isValid())
if (parentItem) { {
qDebug() << "parent item text:" << parentItem->text(0); qDebug() << "点击的是目录项或无效项";
if (parentItem == _sampleDataItem) {
fileName = Global::SampleDataFloder + "/" + item->text(0);
#if 0
}else if(parentItem == _baseLineItem){
fileName =Global::BaseLineFolder + "/" +item->text(0);
#endif
} else if (parentItem == _analysisStateItem) {
fileName = Global::AnalysisStateFolder + "/" + item->text(0);
}
} else {
qDebug() << "item has no parent (it is a top-level item)";
return; return;
} }
emit sigSendAnalysisFileName(fileName); QString filePath = userData.toString();
if (filePath.isEmpty())
{
qDebug() << "文件路径为空";
return;
}
// 检查文件是否存在
QFileInfo fileInfo(filePath);
if (!fileInfo.exists())
{
qWarning() << "文件不存在: " << filePath;
return;
}
// 发送文件路径信号
emit sigSendAnalysisFileName(filePath);
} }
void LeftWidget::initFileName(QTreeWidgetItem *parentItem, const QString &folderPath) {
QDir dir(folderPath); void LeftWidget::initFileName(QTreeWidgetItem *parentItem, const QString &folderPath)
{
QDir dir(folderPath);
QStringList files = dir.entryList(QDir::Files); QStringList files = dir.entryList(QDir::Files);
for (const QString &fileName : files) { for (const QString &fileName : files)
{
QTreeWidgetItem *subItem = new QTreeWidgetItem(); QTreeWidgetItem *subItem = new QTreeWidgetItem();
subItem->setText(0, fileName); subItem->setText(0, fileName);
subItem->setData(0, Qt::UserRole, QVariant::fromValue(folderPath + "/" + fileName)); subItem->setData(0, Qt::UserRole, QVariant::fromValue(folderPath + "/" + fileName));
@ -161,22 +180,25 @@ void LeftWidget::initFileName(QTreeWidgetItem *parentItem, const QString &folder
} }
} }
void LeftWidget::expandAll(QTreeWidgetItem *item) { void LeftWidget::expandAll(QTreeWidgetItem *item)
{
item->setExpanded(true); item->setExpanded(true);
for (int i = 0; i < item->childCount(); ++i) { for (int i = 0; i < item->childCount(); ++i)
{
expandAll(item->child(i)); expandAll(item->child(i));
} }
} }
void LeftWidget::clearAllChildItems(QTreeWidgetItem *parentItem) { void LeftWidget::clearAllChildItems(QTreeWidgetItem *parentItem)
{
int childCount = parentItem->childCount(); int childCount = parentItem->childCount();
for (int i = 0; i < childCount; ++i) { for (int i = 0; i < childCount; ++i)
{
QTreeWidgetItem *childItem = parentItem->takeChild(0); QTreeWidgetItem *childItem = parentItem->takeChild(0);
delete childItem; delete childItem;
} }
} }
#if 0 #if 0
void LeftWidget::recursiveFolderOperation(const QString& folderPath) { void LeftWidget::recursiveFolderOperation(const QString& folderPath) {
QDir dir(folderPath); QDir dir(folderPath);
@ -215,26 +237,334 @@ void LeftWidget::recursiveFolderOperation(const QString& folderPath) {
} }
#endif #endif
void LeftWidget::slotShowContextMenu(const QPoint &pos) { void LeftWidget::slotShowContextMenu(const QPoint &pos)
QPoint globalPos = _treeWidget->mapToGlobal(pos); {
_contextMenu->exec(globalPos); QTreeWidgetItem *item = _treeWidget->itemAt(pos);
if (item) {
// 获取文件路径
QString filePath = item->data(0, Qt::UserRole).toString();
QString dirPath = item->data(0, Qt::UserRole + 1).toString();
// 获取当前选中的项 // 如果是文件
QTreeWidgetItem *currentItem = _treeWidget->itemAt(pos); if (!filePath.isEmpty()) {
if (currentItem == nullptr) { _deleteFileActionFilePath = filePath;
return; _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);
}
QString filePath = currentItem->data(0, Qt::UserRole).toString(); // 只有当点击的是目录时才显示"新建文件夹"选项
if (filePath.isEmpty()) { bool isDir = !dirPath.isEmpty();
return; _createFolderAction->setVisible(isDir);
}
// qDebug() << "file:" << filePath;
if (QFile::remove(filePath)) {
qDebug() << "文件删除成功:" << filePath;
} else {
qWarning() << "文件删除失败:" << filePath;
}
reloadFileName(); _contextMenu->exec(_treeWidget->mapToGlobal(pos));
}
}
void LeftWidget::slotDeleteActionTriggered()
{
if (_deleteFileActionFilePath.isEmpty()) {
return;
}
QFileInfo fileInfo(_deleteFileActionFilePath);
bool isDir = fileInfo.isDir();
// 检查文件/目录是否存在
if (!fileInfo.exists()) {
QMessageBox::warning(this, tr("警告"), tr("文件/目录不存在!"));
return;
}
// 确认删除对话框
int ret = QMessageBox::question(this, tr("确认删除"),
tr("确定要删除%1\n%2?").arg(isDir ? tr("文件夹及其所有内容") : tr("文件")).arg(_deleteFileActionFilePath),
QMessageBox::Yes | QMessageBox::No,
QMessageBox::No);
if (ret == QMessageBox::Yes) {
bool success;
if (isDir) {
// 删除目录及其内容
success = removeDir(_deleteFileActionFilePath);
} else {
// 删除文件
success = QFile::remove(_deleteFileActionFilePath);
}
if (success) {
// 重新加载文件树
reloadFileTree();
} else {
QMessageBox::critical(this, tr("错误"), tr("删除失败!"));
}
}
_deleteFileActionFilePath.clear();
}
bool LeftWidget::removeDir(const QString &dirPath)
{
bool result = true;
QDir dir(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()) {
result = removeDir(info.absoluteFilePath());
} else {
result = QFile::remove(info.absoluteFilePath());
}
if (!result) {
return result;
}
}
result = dir.rmdir(dirPath);
}
return result;
}
void LeftWidget::slotCreateFolderActionTriggered()
{
// 获取当前选中的项目
QTreeWidgetItem *currentItem = _treeWidget->currentItem();
if (!currentItem) {
return;
}
// 获取当前目录路径
QString dirPath;
if (currentItem->data(0, Qt::UserRole + 1).toString().isEmpty()) {
// 如果是文件,获取其父目录
dirPath = QFileInfo(currentItem->data(0, Qt::UserRole).toString()).absolutePath();
} else {
// 如果是目录,直接使用其路径
dirPath = currentItem->data(0, Qt::UserRole + 1).toString();
}
// 弹出对话框,输入新文件夹名称
bool ok;
QString folderName = QInputDialog::getText(this, tr("新建文件夹"),
tr("请输入文件夹名称:"),
QLineEdit::Normal,
tr("新建文件夹"), &ok);
if (!ok || folderName.isEmpty()) {
return;
}
// 检查文件夹名称是否有效
if (folderName.contains(QRegExp("[\\/:*?\"<>|]"))) {
QMessageBox::warning(this, tr("错误"), tr("文件夹名称包含非法字符!"));
return;
}
// 创建新文件夹路径
QString newFolderPath = dirPath + "/" + folderName;
// 检查文件夹是否已存在
if (QDir(newFolderPath).exists()) {
QMessageBox::warning(this, tr("错误"), tr("文件夹已存在!"));
return;
}
// 创建文件夹
if (QDir().mkdir(newFolderPath)) {
// 保存当前展开状态
saveExpandedState();
// 重新加载文件树
reloadFileTree();
// 恢复展开状态
restoreExpandedState();
// 展开当前目录并选中新创建的文件夹
expandAndSelectItem(newFolderPath);
} else {
QMessageBox::critical(this, tr("错误"), tr("创建文件夹失败!"));
}
}
void LeftWidget::expandAndSelectItem(const QString &path)
{
// 递归展开到指定路径并选中该项
QTreeWidgetItemIterator it(_treeWidget);
while (*it) {
QTreeWidgetItem *item = *it;
QString itemPath = item->data(0, Qt::UserRole + 1).toString();
if (itemPath == path) {
// 展开所有父节点
QTreeWidgetItem *parent = item->parent();
while (parent) {
parent->setExpanded(true);
parent = parent->parent();
}
// 选中新创建的文件夹
_treeWidget->setCurrentItem(item);
break;
}
++it;
}
}
void LeftWidget::confirmDelete(bool enabled)
{
if (enabled)
{
if (QFile::remove(_deleteFileActionFilePath))
{
// qDebug() << "文件删除成功:" << filePath;
logde << "delete succ:" << _deleteFileActionFilePath.toStdString();
}
else
{
// qWarning() << "文件删除失败:" << filePath;
logde << "delete fail:" << _deleteFileActionFilePath.toStdString();
}
// 重新加载文件树
reloadFileTree();
}
}
void LeftWidget::reloadFileTree()
{
// 保存当前展开状态
saveExpandedState();
// 清空现有的树形结构
_treeWidget->clear();
// 创建根节点
QTreeWidgetItem *rootItem = new QTreeWidgetItem(_treeWidget);
rootItem->setText(0, "实验数据");
rootItem->setData(0, Qt::UserRole, Global::ExperimentDirPath);
// 保存根目录路径,用于恢复展开状态
rootItem->setData(0, Qt::UserRole + 1, Global::ExperimentDirPath);
// 递归扫描目录并构建树形结构
buildFileTree(rootItem, Global::ExperimentDirPath);
// 展开根节点
rootItem->setExpanded(true);
// 恢复展开状态
restoreExpandedState();
// 更新全局文件列表
Global::updateFileList();
}
QFileInfoList LeftWidget::scanDirRecursively(const QString &rootPath)
{
QFileInfoList result; // 1. 结果容器
QDirIterator it(rootPath, // 2. 迭代器:从 rootPath 开始
QDir::Dirs | QDir::Files | QDir::NoDotAndDotDot, // 3. 要哪些条目
QDirIterator::Subdirectories); // 4. 递归标志
while (it.hasNext())
{ // 5. 还有下一条吗?
it.next(); // 6. 推进到下一个条目
result.append(it.fileInfo()); // 7. 把当前条目塞进列表
}
return result; // 8. 返回
}
void LeftWidget::buildFileTree(QTreeWidgetItem *parentItem, const QString &dirPath)
{
QDir dir(dirPath);
if (!dir.exists()) {
qWarning() << "目录不存在: " << dirPath;
return;
}
// 获取所有子目录和文件,按名称排序
dir.setSorting(QDir::Name | QDir::DirsFirst);
QFileInfoList list = dir.entryInfoList(QDir::Dirs | QDir::Files | QDir::NoDotAndDotDot);
for (const QFileInfo &fileInfo : list) {
QTreeWidgetItem *item = new QTreeWidgetItem(parentItem);
if (fileInfo.isDir()) {
// 设置目录项
item->setText(0, fileInfo.fileName());
// 使用系统默认的目录图标
item->setIcon(0, _treeWidget->style()->standardIcon(QStyle::SP_DirIcon));
// 保存目录路径,用于恢复展开状态
item->setData(0, Qt::UserRole + 1, fileInfo.absoluteFilePath());
// 递归处理子目录
buildFileTree(item, fileInfo.absoluteFilePath());
} else {
// 设置文件项
item->setText(0, fileInfo.fileName());
item->setData(0, Qt::UserRole, fileInfo.absoluteFilePath());
// 根据文件类型设置不同的图标
QString suffix = fileInfo.suffix().toLower();
if (suffix == "xlsx" || suffix == "xls") {
// 使用系统默认的文档图标
item->setIcon(0, _treeWidget->style()->standardIcon(QStyle::SP_FileIcon));
} else {
// 使用默认文件图标
item->setIcon(0, _treeWidget->style()->standardIcon(QStyle::SP_FileIcon));
}
}
}
}
void LeftWidget::saveExpandedState()
{
_expandedPaths.clear();
// 递归遍历所有项,保存展开的目录路径
QTreeWidgetItemIterator it(_treeWidget);
while (*it) {
QTreeWidgetItem *item = *it;
if (item->isExpanded()) {
QVariant pathData = item->data(0, Qt::UserRole + 1);
if (!pathData.isNull()) {
_expandedPaths.append(pathData.toString());
}
}
++it;
}
qDebug() << "保存了" << _expandedPaths.size() << "个展开状态:" << _expandedPaths;
}
void LeftWidget::restoreExpandedState()
{
int restoredCount = 0;
// 递归遍历所有项,恢复展开状态
QTreeWidgetItemIterator it(_treeWidget);
while (*it) {
QTreeWidgetItem *item = *it;
QVariant pathData = item->data(0, Qt::UserRole + 1);
if (!pathData.isNull()) {
QString path = pathData.toString();
if (_expandedPaths.contains(path)) {
item->setExpanded(true);
restoredCount++;
}
}
++it;
}
qDebug() << "恢复了" << restoredCount << "个展开状态";
} }

View File

@ -19,18 +19,30 @@ public:
void reloadFileName(); void reloadFileName();
void reloadFileTree();
QString filePathCheck(const QString fileName,const QString folderPath); QString filePathCheck(const QString fileName,const QString folderPath);
// 确认删除文件
void confirmDelete(bool enabled);
signals: signals:
void sigSendAnalysisFileName(const QString&); void sigSendAnalysisFileName(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);
void removeFile(const QString& filePath); QFileInfoList scanDirRecursively(const QString &rootPath);
void buildFileTree(QTreeWidgetItem *parentItem, const QString &dirPath);
void saveExpandedState();
void restoreExpandedState();
void expandAndSelectItem(const QString &path);
bool removeDir(const QString &dirPath);
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 slotCreateFolderActionTriggered();
private: private:
QTreeWidget *_treeWidget; QTreeWidget *_treeWidget;
@ -39,7 +51,14 @@ private:
*_sampleDataItem; *_sampleDataItem;
QMenu *_contextMenu; QMenu *_contextMenu;
QAction *_deleteAction;
QAction *_deleteFileAction;
QAction *_createFolderAction;
QString _deleteFileActionFilePath;
// 保存展开状态的列表
QStringList _expandedPaths;
}; };
#endif // LEFTWIDGET_H #endif // LEFTWIDGET_H