1、完善框架;2、添加qcustomplot;3、处理csv中文路径问题

This commit is contained in:
徐海 2026-03-03 18:15:34 +08:00
parent ceb16887f2
commit 259c798b5d
25 changed files with 43662 additions and 294 deletions

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,3 @@
INCLUDEPATH += $${PWD}
HEADERS += $${PWD}/qcustomplot.h
SOURCES += $${PWD}/qcustomplot.cpp

View File

@ -1,16 +1,16 @@
#include "DataProcessWorkPool.h"
#include <QThreadPool>
#include <QDir>
#include "MeasureAnalysisProjectModel.h"
#include "OutputInfoDefine.h"
#include "GlobalDefine.h"
#include "csv.h"
#include <fstream>
#include <vector>
#include <QDir>
#include <QThreadPool>
#include <algorithm>
#include <queue>
#include <fstream>
#include <memory>
#include <string>
#include <queue>
#include <sstream>
#include <string>
#include <vector>
using namespace DataProcessWorkPool;
using namespace io;
@ -26,13 +26,11 @@ void ParticleDataTask::SetFinishedNotifier(QObject* finished_notifier, const cha
this->_project_name = project_name;
}
const QString& ParticleDataTask::GetAllChannelParticleDataFilename() const
{
return this->_all_channel_particle_data_filename;
}
const QString& ParticleDataTask::GetProjectName() const
{
return this->_project_name;
@ -50,10 +48,7 @@ QObject* ParticleDataTask::GetFinishedNotifier() const
bool ParticleDataTask::IsValidSetWorkParameters() const
{
return (!GetAllChannelParticleDataFilename().isEmpty()) &&
(GetFinishedNotifier() != nullptr) &&
(!GetProjectName().isEmpty()) &&
(GetFinishedNotifierProcess() != nullptr);
return (!GetAllChannelParticleDataFilename().isEmpty()) && (!GetProjectName().isEmpty());
}
void ParticleDataTask::StartTask()
@ -67,11 +62,13 @@ void ParticleDataTask::run()
return;
}
if (!processEveryChannelParticleData()) {
if (!processEveryChannelParticleData()) {
return;
}
QMetaObject::invokeMethod(_finished_notifier, _finished_notifier_process, Qt::QueuedConnection, Q_ARG(QString, _project_name));
if ((GetFinishedNotifier() != nullptr) && (GetFinishedNotifierProcess() != nullptr)) {
QMetaObject::invokeMethod(_finished_notifier, _finished_notifier_process, Qt::QueuedConnection, Q_ARG(QString, _project_name));
}
}
void EveryChannelParticleDataSeparateTask::SetResultDataDir(const QString& result_data_dir)
@ -113,8 +110,8 @@ bool EveryChannelParticleDataSeparateTask::processEveryChannelParticleData()
io::trim_chars<' ', '\t'>,
io::double_quote_escape<',', '"'>,
io::throw_on_overflow,
io::empty_line_comment
> reader(all_channel_particle_data_filename.toStdString());
io::empty_line_comment>
reader(QStrToSysPath(all_channel_particle_data_filename));
reader.read_header(io::ignore_extra_column, board_id_str, channel_id_str, address_str, time_str);
uint board_id;
uint channel_id;
@ -128,14 +125,13 @@ bool EveryChannelParticleDataSeparateTask::processEveryChannelParticleData()
if (!particle_data_filename_list.contains(channel_num)) {
particle_data_filename_list.insert(channel_num, particle_data_filename);
}
if ( !ch_particle_data_of_list.contains(channel_num) ) {
if (!ch_particle_data_of_list.contains(channel_num)) {
std::shared_ptr<std::ofstream> out(
new std::ofstream(particle_data_filename.toStdString(), std::ios::out | std::ios::app),
[](std::ofstream* p){p->close();}
);
new std::ofstream(QStrToSysPath(particle_data_filename), std::ios::out | std::ios::app),
[](std::ofstream* p) { p->close(); });
*out << QString(QStringLiteral(u"板卡号,通道号,道址,时间计数")).toStdString() << std::endl;
ch_particle_data_of_list.insert(channel_num, out);
ch_particle_data_of_list.insert(channel_num, out);
}
auto ch_particle_data_of = ch_particle_data_of_list.value(channel_num);
*ch_particle_data_of << board_id << "," << channel_id << "," << address << "," << time << std::endl;
@ -162,35 +158,33 @@ bool EveryChannelParticleDataSeparateTask::processEveryChannelParticleData()
for (auto it = particle_data_filename_list.begin(); it != particle_data_filename_list.end(); ++it) {
project_model->SetChannelParticleDataFilename(it.key(), it.value());
}
return ret_ok;
}
void EveryChannelParticleCountDataTask::SetAllChannelCountResultDir(const QString &dir_path)
void EveryChannelParticleCountDataTask::SetAllChannelCountResultDir(const QString& dir_path)
{
this->_all_ch_count_dir = dir_path;
}
const QString &EveryChannelParticleCountDataTask::GetAllChannelCountResultDir() const
const QString& EveryChannelParticleCountDataTask::GetAllChannelCountResultDir() const
{
return this->_all_ch_count_dir;
}
void EveryChannelParticleCountDataTask::SetEveryChannelCountResultDir(const QString &dir_path)
void EveryChannelParticleCountDataTask::SetEveryChannelCountResultDir(const QString& dir_path)
{
this->_every_ch_count_dir = dir_path;
}
const QString &EveryChannelParticleCountDataTask::GetEveryChannelCountResultDir() const
const QString& EveryChannelParticleCountDataTask::GetEveryChannelCountResultDir() const
{
return this->_every_ch_count_dir;
}
bool EveryChannelParticleCountDataTask::IsValidSetWorkParameters() const
{
return (!GetAllChannelCountResultDir().isEmpty()) &&
(!GetEveryChannelCountResultDir().isEmpty()) &&
ParticleDataTask::IsValidSetWorkParameters();
return (!GetAllChannelCountResultDir().isEmpty()) && (!GetEveryChannelCountResultDir().isEmpty()) && ParticleDataTask::IsValidSetWorkParameters();
}
bool EveryChannelParticleCountDataTask::processEveryChannelParticleData()
@ -198,10 +192,10 @@ bool EveryChannelParticleCountDataTask::processEveryChannelParticleData()
bool ret_ok = true;
const QString& all_ch_count_dir = GetAllChannelCountResultDir();
const QString& every_ch_count_dir = GetEveryChannelCountResultDir();
QDir all_ch_count_output_dir(all_ch_count_dir);
all_ch_count_output_dir.mkpath(all_ch_count_dir);
QDir every_ch_count_output_dir(every_ch_count_dir);
every_ch_count_output_dir.mkpath(every_ch_count_dir);
@ -212,23 +206,23 @@ bool EveryChannelParticleCountDataTask::processEveryChannelParticleData()
try {
// 统计每个通道的粒子计数(相同板卡号通道号相同道址)
QMap<uint, QMap<uint, uint>> channel_address_counts; // 通道号 -> 地址 -> 计数
// 统计所有通道的粒子计数(不同板卡号通道号相同道址)
QMap<uint, uint> all_channel_address_counts; // 地址 -> 计数
std::string board_id_str = QString(QStringLiteral(u"板卡号")).toStdString();
std::string channel_id_str = QString(QStringLiteral(u"通道号")).toStdString();
std::string address_str = QString(QStringLiteral(u"道址")).toStdString();
std::string time_str = QString(QStringLiteral(u"时间计数")).toStdString();
// 使用更灵活的方式处理CSV文件忽略额外列
io::CSVReader<
4,
io::trim_chars<' ', '\t'>,
io::double_quote_escape<',', '"'>,
io::throw_on_overflow,
io::empty_line_comment
> reader(all_channel_particle_data_filename.toStdString());
io::empty_line_comment>
reader(QStrToSysPath(all_channel_particle_data_filename));
reader.read_header(io::ignore_extra_column, board_id_str, channel_id_str, address_str, time_str);
uint board_id;
uint channel_id;
@ -237,60 +231,60 @@ bool EveryChannelParticleCountDataTask::processEveryChannelParticleData()
while (reader.read_row(board_id, channel_id, address, time)) {
// 板卡和通道号计算,通道号 = 板卡号 * 4 + 通道号
int channel_num = (board_id) * 4 + (channel_id + 1);
// 统计每个通道的粒子计数
if (!channel_address_counts.contains(channel_num)) {
channel_address_counts[channel_num] = QMap<uint, uint>();
}
channel_address_counts[channel_num][address]++;
// 统计所有通道的粒子计数
all_channel_address_counts[address]++;
}
// 写入每个通道的粒子计数数据(优化:使用一次打开文件,批量写入)
QMap<uint, std::shared_ptr<std::ofstream>> channel_file_streams;
// 预创建所有通道的文件流
for (auto channel_it = channel_address_counts.begin(); channel_it != channel_address_counts.end(); ++channel_it) {
uint channel_num = channel_it.key();
QString count_data_filename = every_ch_count_output_dir.filePath(QString("ParticleCountData_ch_%1.csv").arg(channel_num));
particle_count_filename_list.insert(channel_num, count_data_filename);
// 创建文件流
std::shared_ptr<std::ofstream> out(new std::ofstream(count_data_filename.toStdString()));
std::shared_ptr<std::ofstream> out(new std::ofstream( QStrToSysPath(count_data_filename)));
channel_file_streams[channel_num] = out;
*out << QString(QStringLiteral(u"道址")).toStdString() << "," << QString(QStringLiteral(u"计数")).toStdString() << std::endl;
}
// 批量写入数据
for (auto channel_it = channel_address_counts.begin(); channel_it != channel_address_counts.end(); ++channel_it) {
uint channel_num = channel_it.key();
const QMap<uint, uint>& address_counts = channel_it.value();
auto out_stream = channel_file_streams[channel_num];
for (auto address_it = address_counts.begin(); address_it != address_counts.end(); ++address_it) {
uint address = address_it.key();
uint count = address_it.value();
*out_stream << address << "," << count << std::endl;
}
}
// 文件流会在shared_ptr析构时自动关闭
channel_file_streams.clear();
// 写入所有通道的粒子计数数据
all_channel_total_count_filename = all_ch_count_output_dir.filePath("AllChannelParticleTotalCountData.csv");
std::ofstream all_channel_out(all_channel_total_count_filename.toStdString());
std::ofstream all_channel_out(QStrToSysPath(all_channel_total_count_filename));
all_channel_out << QString(QStringLiteral(u"道址")).toStdString() << "," << QString(QStringLiteral(u"计数")).toStdString() << std::endl;
for (auto address_it = all_channel_address_counts.begin(); address_it != all_channel_address_counts.end(); ++address_it) {
uint address = address_it.key();
uint count = address_it.value();
all_channel_out << address << "," << count << std::endl;
}
all_channel_out.close();
} catch (const std::runtime_error& e) {
QString error = QString(QStringLiteral(u"处理%1发生运行时异常:%2")).arg(all_channel_particle_data_filename).arg(e.what());
LOG_ERROR(error)
@ -345,78 +339,85 @@ struct CsvRow {
unsigned long long time;
size_t chunk_index;
bool operator<(const CsvRow& other) const {
bool operator<(const CsvRow& other) const
{
return time > other.time;
}
};
std::vector<std::string> splitFile(const std::string& inputFile, size_t chunkSize) {
std::vector<std::string> splitFile(const std::string& input_file, size_t chunk_size)
{
std::vector<std::string> chunks;
try {
std::string board_id_str = QString(QStringLiteral(u"板卡号")).toStdString();
std::string channel_id_str = QString(QStringLiteral(u"通道号")).toStdString();
std::string address_str = QString(QStringLiteral(u"道址")).toStdString();
std::string time_str = QString(QStringLiteral(u"时间计数")).toStdString();
// Use csv.h to read the file
io::CSVReader<4, io::trim_chars<' ', '\t'>, io::double_quote_escape<',', '"'>, io::throw_on_overflow, io::empty_line_comment> reader(inputFile);
io::CSVReader<
4,
io::trim_chars<' ', '\t'>,
io::double_quote_escape<',', '"'>,
io::throw_on_overflow,
io::empty_line_comment
> reader(input_file);
reader.read_header(io::ignore_extra_column, board_id_str, channel_id_str, address_str, time_str);
int chunkIndex = 0;
while (true) {
std::vector<CsvRow> rows;
size_t currentSize = 0;
uint board_id;
uint channel_id;
uint address;
unsigned long long time;
while (reader.read_row(board_id, channel_id, address, time)) {
CsvRow row;
row.board_id = board_id;
row.channel_id = channel_id;
row.address = address;
row.time = time;
// Estimate row size
currentSize += std::to_string(board_id).size() +
std::to_string(channel_id).size() +
std::to_string(address).size() +
std::to_string(time).size() + 4; // +4 for commas
if (currentSize > chunkSize && !rows.empty()) {
currentSize += std::to_string(board_id).size() + std::to_string(channel_id).size() + std::to_string(address).size() + std::to_string(time).size() + 4; // +4 for commas
if (currentSize > chunk_size && !rows.empty()) {
break;
}
rows.push_back(row);
}
if (rows.empty()) break;
if (rows.empty())
break;
std::sort(rows.begin(), rows.end(), [](const CsvRow& a, const CsvRow& b) {
return a.time < b.time;
});
std::string chunkFile = inputFile + ".chunk" + std::to_string(chunkIndex);
std::string chunkFile = input_file + ".chunk" + std::to_string(chunkIndex);
std::ofstream outFile(chunkFile);
for (const auto& row : rows) {
outFile << row.board_id << "," << row.channel_id << "," << row.address << "," << row.time << "\n";
}
outFile.close();
chunks.push_back(chunkFile);
chunkIndex++;
}
} catch (const std::exception& e) {
// Handle exception
}
return chunks;
}
void mergeChunks(const std::vector<std::string>& chunks, const std::string& outputFile) {
void mergeChunks(const std::vector<std::string>& chunks, const std::string& output_file)
{
std::vector<std::unique_ptr<io::CSVReader<4>>> chunkReaders;
std::priority_queue<CsvRow> minHeap;
@ -424,13 +425,13 @@ void mergeChunks(const std::vector<std::string>& chunks, const std::string& outp
auto reader = std::make_unique<io::CSVReader<4>>(chunk);
chunkReaders.push_back(std::move(reader));
}
for (size_t i = 0; i < chunkReaders.size(); i++) {
uint board_id;
uint channel_id;
uint address;
unsigned long long time;
if (chunkReaders[i]->read_row(board_id, channel_id, address, time)) {
CsvRow row;
row.board_id = board_id;
@ -441,27 +442,27 @@ void mergeChunks(const std::vector<std::string>& chunks, const std::string& outp
minHeap.push(row);
}
}
std::string board_id_str = QString(QStringLiteral(u"板卡号")).toStdString();
std::string channel_id_str = QString(QStringLiteral(u"通道号")).toStdString();
std::string address_str = QString(QStringLiteral(u"道址")).toStdString();
std::string time_str = QString(QStringLiteral(u"时间计数")).toStdString();
std::ofstream outFile(outputFile);
std::ofstream outFile(output_file);
outFile << board_id_str << "," << channel_id_str << "," << address_str << "," << time_str << "\n";
while (!minHeap.empty()) {
CsvRow current = minHeap.top();
minHeap.pop();
outFile << current.board_id << "," << current.channel_id << "," << current.address << "," << current.time << "\n";
size_t chunk_index = current.chunk_index;
if (chunkReaders[chunk_index]) {
uint board_id;
uint channel_id;
uint address;
unsigned long long time;
if (chunkReaders[chunk_index]->read_row(board_id, channel_id, address, time)) {
CsvRow row;
row.board_id = board_id;
@ -475,7 +476,7 @@ void mergeChunks(const std::vector<std::string>& chunks, const std::string& outp
}
}
}
outFile.close();
for (const auto& chunk : chunks) {
@ -495,21 +496,21 @@ bool ParticleDataSortTask::processEveryChannelParticleData()
try {
const size_t CHUNK_SIZE = 100 * 1024 * 1024; // 100MB chunks
std::vector<std::string> chunks = splitFile(all_channel_particle_data_filename.toStdString(), CHUNK_SIZE);
std::vector<std::string> chunks = splitFile(QStrToSysPath(all_channel_particle_data_filename), CHUNK_SIZE);
if (chunks.empty()) {
std::ifstream inFile(all_channel_particle_data_filename.toStdString());
std::ofstream outFile(sorted_output_filename.toStdString());
std::ifstream in_file(QStrToSysPath(all_channel_particle_data_filename));
std::ofstream out_file(QStrToSysPath(sorted_output_filename));
std::string line;
while (std::getline(inFile, line)) {
outFile << line << "\n";
while (std::getline(in_file, line)) {
out_file << line << "\n";
}
inFile.close();
outFile.close();
in_file.close();
out_file.close();
} else {
mergeChunks(chunks, sorted_output_filename.toStdString());
mergeChunks(chunks, QStrToSysPath(sorted_output_filename));
}
} catch (const std::exception& e) {
QString error = QString(QStringLiteral(u"处理%1异常:%2")).arg(all_channel_particle_data_filename).arg(e.what());
LOG_ERROR(error)

View File

@ -76,4 +76,4 @@ namespace DataProcessWorkPool
};
}
#endif // DATAPROCESSWORKPOOL_H
#endif // DATAPROCESSWORKPOOL_H

View File

@ -22,16 +22,16 @@
<widget class="QTableWidget" name="tablew_scale_data">
<property name="geometry">
<rect>
<x>280</x>
<y>330</y>
<width>256</width>
<height>230</height>
<x>190</x>
<y>420</y>
<width>621</width>
<height>101</height>
</rect>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>230</height>
<height>0</height>
</size>
</property>
<attribute name="horizontalHeaderCascadingSectionResizes">
@ -78,57 +78,50 @@
<rect>
<x>20</x>
<y>10</y>
<width>171</width>
<height>451</height>
<width>151</width>
<height>531</height>
</rect>
</property>
<property name="title">
<string>能量刻度管理列表</string>
</property>
<widget class="QListWidget" name="listWidget">
<property name="geometry">
<rect>
<x>20</x>
<y>20</y>
<width>141</width>
<height>192</height>
</rect>
</property>
</widget>
<widget class="QPushButton" name="pushButton_4">
<property name="geometry">
<rect>
<x>10</x>
<y>410</y>
<width>75</width>
<height>24</height>
</rect>
</property>
<property name="text">
<string>添加</string>
</property>
</widget>
<widget class="QPushButton" name="pushButton_5">
<property name="geometry">
<rect>
<x>90</x>
<y>410</y>
<width>75</width>
<height>24</height>
</rect>
</property>
<property name="text">
<string>删除</string>
</property>
</widget>
<layout class="QVBoxLayout" name="verticalLayout_5">
<item>
<widget class="QTreeWidget" name="treeWidget">
<column>
<property name="text">
<string notr="true">1</string>
</property>
</column>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout_9">
<item>
<widget class="QPushButton" name="pushButton_4">
<property name="text">
<string>添加</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="pushButton_5">
<property name="text">
<string>删除</string>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
<widget class="QWidget" name="">
<widget class="QWidget" name="layoutWidget">
<property name="geometry">
<rect>
<x>191</x>
<y>9</y>
<width>631</width>
<height>314</height>
<height>338</height>
</rect>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_8">

View File

@ -1,8 +1,25 @@
#ifndef OUTPUTINFODEFINE_H
#define OUTPUTINFODEFINE_H
#ifndef GLOBALDEFINE_H
#define GLOBALDEFINE_H
#include "MainWindow.h"
#include "QsLog.h"
#include <QTextCodec>
// 转换Qt字符串路径为系统编码的C字符串解决中文路径问题
static const char* QStrToSysPath(const QString& qstr_path)
{
static std::string sys_path; // 静态变量避免内存释放
#ifdef Q_OS_WIN
// Windows转为GBK编码
QTextCodec* gbkCodec = QTextCodec::codecForName("GBK");
if (!gbkCodec) gbkCodec = QTextCodec::codecForLocale();
sys_path = gbkCodec->fromUnicode(qstr_path).toStdString();
#else
// Linux/Mac转为UTF-8编码
sys_path = qstr_path.toUtf8().toStdString();
#endif
return sys_path.c_str();
}
#define STATUS_BAR_MSG(msg) \
@ -35,4 +52,4 @@
QLOG_DEBUG() << debug_info; \
}
#endif // OUTPUTINFODEFINE_H
#endif // GLOBALDEFINE_H

View File

@ -25,6 +25,7 @@
#include "MeasureDeviceParamsCfgForm.h"
#include "NewMeasureAnalysisDlg.h"
#include "MeasureAnalysisView.h"
#include "MeasureAnalysisActions.h"
using namespace ads;
@ -123,6 +124,9 @@ void MainWindow::initMainWindow()
_dock_manager->addDockWidget(ads::DockWidgetArea::LeftDockWidgetArea, _dockw_measure_analysis_tree);
ui->menu_view->addAction(_dockw_measure_analysis_tree->toggleViewAction());
_tree_actions = new MeasureAnalysisTree::MeasureAnalysisActions(_tree_measure_analysis);
_tree_measure_analysis->SetConnectActions(_tree_actions);
_menu_view_data_table_list = ui->menu_view->addMenu(QStringLiteral(u"查看数据列表"));
_menu_view_analysis_view_list = ui->menu_view->addMenu(QStringLiteral(u"分析视图列表"));
@ -145,17 +149,19 @@ void MainWindow::initAction()
this->_tree_measure_analysis->AddProjectModel(project_model);
if (project_model->GetIsMeasureComplete()) {
const QString& project_name = project_model->GetProjectName();
// const QString& result_data_dir = QDir(project_model->GetProjectDir()).filePath("EveryChannelParticleData");
// auto separate_task = new DataProcessWorkPool::EveryChannelParticleDataSeparateTask;
// separate_task->SetAllChannelParticleDataFilename(project_model->GetAllChannelParticleDataFilename());
// separate_task->SetResultDataDir(result_data_dir);
// separate_task->SetFinishedNotifier(this->_tree_measure_analysis, "onFinishedSeparateEveryChannelParticleData", project_name);
// separate_task->StartTask();
/*
const QString& result_data_dir = QDir(project_model->GetProjectDir()).filePath("EveryChannelParticleData");
auto separate_task = new DataProcessWorkPool::EveryChannelParticleDataSeparateTask;
separate_task->SetAllChannelParticleDataFilename(project_model->GetAllChannelParticleDataFilename());
separate_task->SetResultDataDir(result_data_dir);
separate_task->SetFinishedNotifier(this->_tree_measure_analysis, "onFinishedSeparateEveryChannelParticleData", project_name);
separate_task->StartTask();
*/
auto separate_task = new DataProcessWorkPool::ParticleDataSortTask;
separate_task->SetAllChannelParticleDataFilename(project_model->GetAllChannelParticleDataFilename());
separate_task->SetSortedResultDir(project_model->GetProjectDir());
separate_task->SetFinishedNotifier(this->_tree_measure_analysis, "onFinishedParticleSortData", project_name);
separate_task->StartTask();
const QString& all_ch_count_dir = project_model->GetProjectDir();

View File

@ -16,6 +16,7 @@ class CDockWidget;
class QPlainTextEdit;
namespace MeasureAnalysisTree {
class TreeWidget;
class MeasureAnalysisActions;
}
QT_END_NAMESPACE
@ -59,6 +60,7 @@ private:
ads::CDockAreaWidget* _central_dock_area { nullptr };
QAction* _action_central_dock_widget { nullptr };
MeasureAnalysisTree::TreeWidget* _tree_measure_analysis { nullptr };
MeasureAnalysisTree::MeasureAnalysisActions* _tree_actions { nullptr };
ads::CDockWidget* _dockw_measure_analysis_tree { nullptr };
QMenu* _menu_view_data_table_list { nullptr };
QMenu* _menu_view_analysis_view_list { nullptr };

View File

@ -1,4 +1,5 @@
#include "MeasureAnalysisActions.h"
#include "MeasureAnalysisTreeItem.h"
#include <QAction>
namespace MeasureAnalysisTree {
@ -6,22 +7,22 @@ namespace MeasureAnalysisTree {
MeasureAnalysisActions::MeasureAnalysisActions(QObject* parent)
: QObject(parent)
{
_act_add_measure_analysis_project = new QAction(QStringLiteral("新建测量分析"), this);
_act_add_measure_analysis_project->setStatusTip(QStringLiteral("新建测量分析"));
_act_add_measure_analysis_project = new QAction(QStringLiteral(u"新建测量分析"), this);
_act_add_measure_analysis_project->setStatusTip(QStringLiteral(u"新建测量分析"));
_act_add_measure_analysis_project->setDisabled(false);
connect(_act_add_measure_analysis_project, &QAction::triggered, [this]() {
emit addMeasureAnalysisProject();
});
_act_rm_measure_analysis_project = new QAction(QStringLiteral("删除测量分析"), this);
_act_rm_measure_analysis_project->setStatusTip(QStringLiteral("删除测量分析"));
_act_rm_measure_analysis_project = new QAction(QStringLiteral(u"删除测量分析"), this);
_act_rm_measure_analysis_project->setStatusTip(QStringLiteral(u"删除测量分析"));
_act_rm_measure_analysis_project->setDisabled(true);
connect(_act_rm_measure_analysis_project, &QAction::triggered, [this]() {
emit rmMeasureAnalysisProject();
});
_act_modify_measure_analysis_project = new QAction(QStringLiteral("修改测量分析"), this);
_act_modify_measure_analysis_project->setStatusTip(QStringLiteral("修改测量分析"));
_act_modify_measure_analysis_project = new QAction(QStringLiteral(u"修改测量分析"), this);
_act_modify_measure_analysis_project->setStatusTip(QStringLiteral(u"修改测量分析"));
_act_modify_measure_analysis_project->setDisabled(true);
connect(_act_modify_measure_analysis_project, &QAction::triggered, [this]() {
emit modifyMeasureAnalysisProject();
@ -32,22 +33,22 @@ MeasureAnalysisActions::MeasureAnalysisActions(QObject* parent)
_act_group_measure_analysis_project->addAction(_act_rm_measure_analysis_project);
_act_group_measure_analysis_project->addAction(_act_modify_measure_analysis_project);
_act_add_analyze_view = new QAction(QStringLiteral("添加分析视图"), this);
_act_add_analyze_view->setStatusTip(QStringLiteral("添加分析视图"));
_act_add_analyze_view = new QAction(QStringLiteral(u"添加分析视图"), this);
_act_add_analyze_view->setStatusTip(QStringLiteral(u"添加分析视图"));
_act_add_analyze_view->setDisabled(true);
connect(_act_add_analyze_view, &QAction::triggered, [this]() {
emit addAnalyzeView();
});
_act_rm_analyze_view = new QAction(QStringLiteral("删除分析视图"), this);
_act_rm_analyze_view->setStatusTip(QStringLiteral("删除分析视图"));
_act_rm_analyze_view = new QAction(QStringLiteral(u"删除分析视图"), this);
_act_rm_analyze_view->setStatusTip(QStringLiteral(u"删除分析视图"));
_act_rm_analyze_view->setDisabled(true);
connect(_act_rm_analyze_view, &QAction::triggered, [this]() {
emit rmAnalyzeView();
});
_act_modify_analyze_view = new QAction(QStringLiteral("修改分析视图"), this);
_act_modify_analyze_view->setStatusTip(QStringLiteral("修改分析视图"));
_act_modify_analyze_view = new QAction(QStringLiteral(u"修改分析视图"), this);
_act_modify_analyze_view->setStatusTip(QStringLiteral(u"修改分析视图"));
_act_modify_analyze_view->setDisabled(true);
connect(_act_modify_analyze_view, &QAction::triggered, [this]() {
emit modifyAnalyzeView();
@ -77,37 +78,39 @@ QActionGroup* MeasureAnalysisActions::GetViewActionGroups()
return _act_group_analyze_view;
}
void MeasureAnalysisActions::SetActionsAvailable(const TreeItem::TreeItemType& item_type)
void MeasureAnalysisActions::SetActionsAvailable(const TreeItemType &item_type)
{
for (QActionGroup* act_group : this->GetActionGroups()) {
for (QAction* act_item : act_group->actions()) {
act_item->setDisabled(true);
}
}
_act_add_measure_analysis_project->setEnabled(true);
switch (item_type) {
case TreeItem::TreeItemType::MeasureAnalysisProject:
case TreeItemType::MeasureAnalysisProject:
for (QAction* act_item : _act_group_measure_analysis_project->actions()) {
act_item->setEnabled(true);
}
break;
case TreeItem::TreeItemType::ParticleData:
case TreeItemType::ParticleData:
_act_add_analyze_view->setEnabled(true);
break;
case TreeItem::TreeItemType::ParticleCountData:
case TreeItemType::ParticleCountData:
_act_add_analyze_view->setEnabled(true);
break;
case TreeItem::TreeItemType::ConformParticleData:
case TreeItemType::ConformParticleData:
_act_add_analyze_view->setEnabled(true);
break;
case TreeItem::TreeItemType::AnalyzeViewGroup:
case TreeItemType::AnalyzeViewGroup:
_act_add_analyze_view->setEnabled(true);
break;
case TreeItem::TreeItemType::AnalyzeView:
case TreeItemType::AnalyzeView:
for (QAction* act_item : _act_group_analyze_view->actions()) {
act_item->setEnabled(true);
}
break;
case TreeItem::TreeItemType::None:
case TreeItemType::None:
break;
default:
_act_add_measure_analysis_project->setEnabled(true);

View File

@ -1,13 +1,15 @@
#ifndef MEASUREANALYSISACTIONS_H
#define MEASUREANALYSISACTIONS_H
#include "MeasureAnalysisTreeItem.h"
#include <QObject>
class QAction;
class QActionGroup;
namespace MeasureAnalysisTree {
enum class TreeItemType;
class MeasureAnalysisActions : public QObject {
Q_OBJECT
@ -19,7 +21,7 @@ public:
QActionGroup *GetViewActionGroups();
void SetActionsAvailable(const TreeItem::TreeItemType& item_type);
void SetActionsAvailable(const TreeItemType& item_type);
signals:
void addMeasureAnalysisProject();

View File

@ -1,11 +1,14 @@
#include "MeasureAnalysisDataTableView.h"
#include <QHBoxLayout>
#include "VirtualTable/CsvDataSource.h"
#include "VirtualTable/VirtualTableView.h"
#include "VirtualTable/VirtualTableModel.h"
#include "VirtualTable/VirtualTableView.h"
#include <QHBoxLayout>
MeasureAnalysisDataTableView::MeasureAnalysisDataTableView():
_preload_policy(PreloadPolicy::Balanced), _block_size(1000), _buffer_size(50)
MeasureAnalysisDataTableView::MeasureAnalysisDataTableView(QWidget* parent)
: MeasureAnalysisView { parent }
, _preload_policy(PreloadPolicy::Balanced)
, _block_size(1000)
, _buffer_size(50)
{
this->setAnalyzeViewType(ViewType::DataTable);
QHBoxLayout* layout = new QHBoxLayout(this);
@ -17,12 +20,12 @@ MeasureAnalysisDataTableView::MeasureAnalysisDataTableView():
layout->addWidget(_tableView);
}
void MeasureAnalysisDataTableView::SetAnalyzeDataFilename(const QString &filename)
void MeasureAnalysisDataTableView::SetAnalyzeDataFilename(const QMap<QString, QString> &data_files_set)
{
if (filename.isEmpty()) {
if (data_files_set.isEmpty()) {
return;
}
auto csv_ddata_source = std::make_shared<CsvDataSource>(filename);
auto csv_ddata_source = std::make_shared<CsvDataSource>(data_files_set.first());
if (!csv_ddata_source->isValid()) {
return;
}

View File

@ -14,9 +14,9 @@ class MeasureAnalysisDataTableView : public MeasureAnalysisView
{
Q_OBJECT
public:
MeasureAnalysisDataTableView();
MeasureAnalysisDataTableView(QWidget *parent = nullptr);
virtual void SetAnalyzeDataFilename(const QString& filename);
virtual void SetAnalyzeDataFilename(const QMap<QString, QString>& data_files_set);
private:
// 私有成员变量

View File

@ -0,0 +1,57 @@
#include "MeasureAnalysisParticleCountPlotView.h"
#include "qcustomplot.h"
#include "csv.h"
#include <QVector>
MeasureAnalysisParticleCountPlotView::MeasureAnalysisParticleCountPlotView(QWidget* parent)
: MeasureAnalysisView { parent }
{
this->setAnalyzeViewType(ViewType::CountSpectrum);
_custom_plot = new QCustomPlot(this);
_custom_plot->setGeometry(0, 0, this->width(), this->height());
}
void MeasureAnalysisParticleCountPlotView::SetAnalyzeDataFilename(const QMap<QString, QString>& data_files_set)
{
for (auto it = data_files_set.begin(); it != data_files_set.end(); ++it) {
loadDataFromFile(it.value());
}
}
void MeasureAnalysisParticleCountPlotView::setupCustomPlot()
{
_custom_plot->xAxis->setLabel(QString(QStringLiteral(u"道址")));
_custom_plot->yAxis->setLabel(QString(QStringLiteral(u"计数")));
_custom_plot->legend->setVisible(true);
}
void MeasureAnalysisParticleCountPlotView::loadDataFromFile(const QString& filename)
{
std::string address_str = QString(QStringLiteral(u"道址")).toStdString();
std::string count_str = QString(QStringLiteral(u"计数")).toStdString();
io::CSVReader<
2,
io::trim_chars<' ', '\t'>,
io::double_quote_escape<',', '"'>,
io::throw_on_overflow,
io::empty_line_comment
> reader(filename.toUtf8().toStdString());
reader.read_header(io::ignore_extra_column, address_str, count_str);
int address;
int particle_count;
QVector<double> x, y;
while (reader.read_row(address, particle_count)) {
x.push_back(address);
y.push_back(particle_count);
}
auto graph = _custom_plot->addGraph();
// graph->setPen(QPen(Qt::red));
// graph->setBrush(QBrush(Qt::red));
graph->setData(x, y, true);
_custom_plot->replot();
}

View File

@ -0,0 +1,26 @@
#ifndef MEASUREANALYSISPARTICLECOUNTPLOTVIEW_H
#define MEASUREANALYSISPARTICLECOUNTPLOTVIEW_H
#include <QObject>
#include <QWidget>
#include "MeasureAnalysisView.h"
class QCustomPlot;
class MeasureAnalysisParticleCountPlotView : public MeasureAnalysisView
{
Q_OBJECT
public:
MeasureAnalysisParticleCountPlotView(QWidget *parent = nullptr);
virtual void SetAnalyzeDataFilename(const QMap<QString, QString>& data_files_set);
private:
void setupCustomPlot();
void loadDataFromFile(const QString& filename);
private:
QCustomPlot* _custom_plot { nullptr };
};
#endif // MEASUREANALYSISPARTICLECOUNTPLOTVIEW_H

View File

@ -157,7 +157,7 @@ const QMap<uint, QString>& MeasureAnalysisProjectModel::GetChannelParticleDataFi
const QString& MeasureAnalysisProjectModel::GetChannelParticleDataFilename(uint channel) const
{
return this->_channel_particle_data_filename_list[channel];
return QString(this->_channel_particle_data_filename_list[channel]);
}
const QMap<uint, QString>& MeasureAnalysisProjectModel::GetChannelParticleCountDataFilenameList() const

View File

@ -47,6 +47,7 @@ public:
const QString& GetEneryScaleFilename() const;
const QString& GetEfficiencyScaleFilename() const;
const QString& GetAllChannelParticleDataFilename() const;
const QString& GetSortParticleDataFilename() const;
const QMap<uint, QString>& GetChannelParticleDataFilenameList() const;
const QString& GetChannelParticleDataFilename(uint channel) const;
const QMap<uint, QString>& GetChannelParticleCountDataFilenameList() const;
@ -70,6 +71,7 @@ private:
QString _efficiency_scale_filename;
QString _all_channel_particle_data_filename;
QString _sorted_particle_data_filename;
QMap<uint, QString> _channel_particle_data_filename_list;
QMap<uint, QString> _channel_particle_count_data_filename_list;
QString _all_channel_particle_total_count_data_filename;

View File

@ -3,7 +3,7 @@
#include "MeasureAnalysisTreeItem.h"
#include <functional>
#include "MeasureAnalysisProjectModel.h"
#include "OutputInfoDefine.h"
#include "GlobalDefine.h"
#include "QsLog.h"
#include <QAction>
#include <QDropEvent>
@ -33,25 +33,25 @@ TreeWidget::TreeWidget(QWidget* parent)
connect(this, &TreeWidget::itemDoubleClicked, [this](QTreeWidgetItem* item_tree_node) {
TreeItem* item = dynamic_cast<TreeItem*>(item_tree_node);
if (item) {
TreeItem::TreeItemType item_type = item->GetType();
TreeItemType item_type = item->GetType();
switch (item_type) {
case TreeItem::TreeItemType::None:
break;
case TreeItem::TreeItemType::MeasureAnalysisProject:
this->expandItem(item);
break;
case TreeItem::TreeItemType::MeasureCtrlGroup:
this->expandItem(item);
break;
case TreeItem::TreeItemType::AnalyzeDataGroup:
this->expandItem(item);
break;
case TreeItem::TreeItemType::AnalyzeViewGroup:
this->expandItem(item);
break;
case TreeItem::TreeItemType::ParticleData:
case TreeItem::TreeItemType::ParticleCountData:
case TreeItem::TreeItemType::ConformParticleData: {
// case TreeItem::TreeItemType::None:
// break;
// case TreeItem::TreeItemType::MeasureAnalysisProject:
// this->expandItem(item);
// break;
// case TreeItem::TreeItemType::MeasureCtrlGroup:
// this->expandItem(item);
// break;
// case TreeItem::TreeItemType::AnalyzeDataGroup:
// this->expandItem(item);
// break;
// case TreeItem::TreeItemType::AnalyzeViewGroup:
// this->expandItem(item);
// break;
case TreeItemType::ParticleData:
case TreeItemType::ParticleCountData:
case TreeItemType::ConformParticleData: {
const QString view_type_text = MeasureAnalysisView::GetAnalyzeViewTypeText(MeasureAnalysisView::ViewType::DataTable);
item->NewAnalyzeView(item->GetName(), item->GetDescription(), view_type_text);
MeasureAnalysisView* view = item->GetAnalyzeView();
@ -59,7 +59,7 @@ TreeWidget::TreeWidget(QWidget* parent)
emit currentItemViewWidget(view);
}
} break;
case TreeItem::TreeItemType::AnalyzeView: {
case TreeItemType::AnalyzeView: {
MeasureAnalysisView* view = item->GetAnalyzeView();
if (view) {
emit currentItemViewWidget(view);
@ -100,7 +100,7 @@ TreeWidget::~TreeWidget()
void TreeWidget::SetConnectActions(MeasureAnalysisActions* const actions_analyze)
{
auto updateAnalyzeActionsState = [actions_analyze, this](QTreeWidgetItem* item_tree_node) {
TreeItem::TreeItemType item_type = TreeItem::TreeItemType::None;
TreeItemType item_type = TreeItemType::None;
TreeItem* item = dynamic_cast<TreeItem*>(item_tree_node);
if (item) {
item_type = item->GetType();
@ -147,7 +147,7 @@ void TreeWidget::SetConnectActions(MeasureAnalysisActions* const actions_analyze
});
connect(actions_analyze, &MeasureAnalysisActions::modifyAnalyzeView, [this]() {
TreeItem* item = dynamic_cast<TreeItem*>(this->currentItem());
if (item && (TreeItem::TreeItemType::AnalyzeView == item->GetType())) {
if (item && (TreeItemType::AnalyzeView == item->GetType())) {
}
});
}
@ -162,7 +162,7 @@ void TreeWidget::AddProjectModel(MeasureAnalysisProjectModel* model)
const QString& all_ch_particle_data_filename = model->GetAllChannelParticleDataFilename();
TreeItem* new_item_particle_data = new TreeItem;
new_item_particle_data->SetName(QStringLiteral(u"测量粒子数据"));
new_item_particle_data->SetType(TreeItem::TreeItemType::ParticleData);
new_item_particle_data->SetType(TreeItemType::ParticleData);
new_item_particle_data->SetDescription(all_ch_particle_data_filename);
new_item_particle_data->setData(0, Qt::UserRole, all_ch_particle_data_filename);
tree_item_analyze_data_group->insertChild(0, new_item_particle_data);
@ -232,7 +232,7 @@ void TreeWidget::onFinishedParticleCountData(const QString& project_name)
const QString& all_ch_count_filename = project_model->GetAllChannelParticleTotalCountDataFilename();
TreeItem* new_item_all_ch_count = new TreeItem;
new_item_all_ch_count->SetName(QStringLiteral(u"粒子计数数据"));
new_item_all_ch_count->SetType(TreeItem::TreeItemType::ParticleData);
new_item_all_ch_count->SetType(TreeItemType::ParticleData);
new_item_all_ch_count->SetDescription(all_ch_count_filename);
new_item_all_ch_count->setData(0, Qt::UserRole, all_ch_count_filename);
tree_item_analyze_data_group->addChild(new_item_all_ch_count);
@ -243,7 +243,7 @@ void TreeWidget::onFinishedParticleCountData(const QString& project_name)
const QString& ch_count_filename = it.value();
TreeItem* new_item_every_ch_count_data = new TreeItem;
new_item_every_ch_count_data->SetName(QStringLiteral(u"通道%1粒子计数数据").arg(ch_num));
new_item_every_ch_count_data->SetType(TreeItem::TreeItemType::ParticleData);
new_item_every_ch_count_data->SetType(TreeItemType::ParticleData);
new_item_every_ch_count_data->SetDescription(ch_count_filename);
new_item_every_ch_count_data->setData(0, Qt::UserRole, ch_count_filename);
new_item_all_ch_count->addChild(new_item_every_ch_count_data);
@ -255,54 +255,6 @@ void TreeWidget::onFinishedParticleCountData(const QString& project_name)
}
}
/*
void TreeWidget::mousePressEvent(QMouseEvent* event)
{
_tree_item_drag = nullptr;
auto tree_item = dynamic_cast<TreeItem*>(this->itemAt(event->pos()));
if ((event->button() == Qt::LeftButton) && tree_item) {
if ((TreeItem::TreeItemType::Group == tree_item->GetType()) || (TreeItem::TreeItemType::Analyze == tree_item->GetType())) {
_tree_item_drag = tree_item;
}
}
QTreeWidget::mousePressEvent(event);
}
void TreeWidget::dragMoveEvent(QDragMoveEvent* event)
{
if (nullptr == _tree_item_drag) {
event->ignore();
return;
}
QTreeWidget::dragMoveEvent(event);
}
void TreeWidget::dropEvent(QDropEvent* event)
{
if (Qt::MoveAction == event->dropAction()) {
if (nullptr == _tree_item_drag) {
event->ignore();
return;
} else {
auto tree_item = dynamic_cast<TreeItem*>(this->itemAt(event->pos()));
if (tree_item) {
if (TreeItem::TreeItemType::Group != tree_item->GetType()) {
event->ignore();
return;
}
}
}
}
QTreeWidget::dropEvent(event);
}
void TreeWidget::mouseReleaseEvent(QMouseEvent* event)
{
_tree_item_drag = nullptr;
QTreeWidget::mouseReleaseEvent(event);
}
*/
void TreeWidget::setCurrentItemHighlight()
{
// 清除之前的高亮
@ -334,12 +286,12 @@ void TreeWidget::removeAnalyzeItem()
if (QMessageBox::Yes == QMessageBox::question(nullptr, text_title, text_msg)) {
TreeItem* tree_item = dynamic_cast<TreeItem*>(this->currentItem());
if (tree_item) {
TreeItem::TreeItemType item_type = tree_item->GetType();
if (TreeItem::TreeItemType::MeasureAnalysisProject == item_type) {
TreeItemType item_type = tree_item->GetType();
if (TreeItemType::MeasureAnalysisProject == item_type) {
} else if (TreeItem::TreeItemType::ParticleData == item_type) {
} else if (TreeItemType::ParticleData == item_type) {
} else if (TreeItem::TreeItemType::AnalyzeDataGroup == item_type) {
} else if (TreeItemType::AnalyzeDataGroup == item_type) {
}
MeasureAnalysisView* view = tree_item->GetAnalyzeView();
if (view) {

View File

@ -32,21 +32,11 @@ signals:
void currentItemViewWidget(MeasureAnalysisView* view);
void removeItemViewFromStack(MeasureAnalysisView* view);
/*
protected:
virtual void mousePressEvent(QMouseEvent* event);
virtual void dragMoveEvent(QDragMoveEvent* event);
virtual void dropEvent(QDropEvent* event);
virtual void mouseReleaseEvent(QMouseEvent* event);
*/
private:
void setCurrentItemHighlight();
void removeAnalyzeItem();
void removeTreeItem(QTreeWidgetItem* const item);
// private:
// TreeItem* _tree_item_drag { nullptr };
};
} // namespace MeasureAnalysisTree

View File

@ -3,7 +3,7 @@
namespace MeasureAnalysisTree {
TreeItem::TreeItemType TreeItem::GetType()
TreeItemType TreeItem::GetType()
{
return this->_type;
}
@ -54,7 +54,9 @@ void TreeItem::NewAnalyzeView(const QString &name, const QString &description, c
this->_ptr_analyze_view->SetViewName(name);
this->_ptr_analyze_view->SetViewDescription(description);
const QString& data_filename = this->data(0, Qt::UserRole).toString();
this->_ptr_analyze_view->SetAnalyzeDataFilename(data_filename);
QMap<QString, QString> data_files_set;
data_files_set[name] = data_filename;
this->_ptr_analyze_view->SetAnalyzeDataFilename(data_files_set);
}
QDataStream& operator<<(QDataStream& out, const TreeItem& item)
@ -98,24 +100,24 @@ QDataStream& operator>>(QDataStream& in, TreeItem& item)
TreeMeasureAnalysisProjectItem::TreeMeasureAnalysisProjectItem(const QString& project_name, const QString& description)
{
this->SetType(TreeItem::TreeItemType::MeasureAnalysisProject);
this->SetType(TreeItemType::MeasureAnalysisProject);
this->SetName(project_name);
this->SetDescription(description);
TreeItem* tree_group_item = new TreeItem;
tree_group_item->SetType(TreeItem::TreeItemType::MeasureCtrlGroup);
tree_group_item->SetType(TreeItemType::MeasureCtrlGroup);
tree_group_item->SetName(QStringLiteral(u"测量控制"));
tree_group_item->SetDescription(QStringLiteral(u"测量控制组:包括测量设备参数设置、测量时间设置、能量刻度、效率刻度等配置管理"));
this->insertChild(0, tree_group_item);
tree_group_item = new TreeItem;
tree_group_item->SetType(TreeItem::TreeItemType::AnalyzeDataGroup);
tree_group_item->SetType(TreeItemType::AnalyzeDataGroup);
tree_group_item->SetName(QStringLiteral(u"分析数据"));
tree_group_item->SetDescription(QStringLiteral(u"分析数据组:包括粒子数据、谱计数数据、符合粒子数据等管理"));
this->insertChild(1, tree_group_item);
tree_group_item = new TreeItem;
tree_group_item->SetType(TreeItem::TreeItemType::AnalyzeViewGroup);
tree_group_item->SetType(TreeItemType::AnalyzeViewGroup);
tree_group_item->SetName(QStringLiteral(u"分析视图"));
tree_group_item->SetDescription(QStringLiteral(u"分析视图组:包括粒子数据视图、谱计数数据视图、符合粒子数据视图等管理"));
this->insertChild(2, tree_group_item);

View File

@ -8,22 +8,24 @@ namespace MeasureAnalysisTree {
class TreeAnalyzeViewItem;
enum class TreeItemType {
None,
MeasureAnalysisProject,
MeasureCtrlGroup,
DeviceConfig,
EneryScale,
EfficiencyScale,
AnalyzeDataGroup,
ParticleData,
ParticleCountData,
ConformParticleData,
AnalyzeViewGroup,
AnalyzeView
};
class TreeItem : public QTreeWidgetItem {
public:
enum class TreeItemType {
None,
MeasureAnalysisProject,
MeasureCtrlGroup,
DeviceConfig,
EneryScale,
EfficiencyScale,
AnalyzeDataGroup,
ParticleData,
ParticleCountData,
ConformParticleData,
AnalyzeViewGroup,
AnalyzeView
};
TreeItemType GetType();
void SetType(const TreeItemType& type);

View File

@ -38,7 +38,7 @@ public:
void SetViewDescription(const QString& description);
const QString& GetViewName() const;
const QString& GetViewDescription() const;
virtual void SetAnalyzeDataFilename(const QString& filename) = 0;
virtual void SetAnalyzeDataFilename(const QMap<QString, QString>& data_files_set) = 0;
protected:
void setAnalyzeViewType(ViewType type);

View File

@ -140,7 +140,8 @@ void NewMeasureAnalysisDlg::on_btn_ok_clicked()
project_dir.mkpath(project_dir_path);
// 拷贝粒子数据文件到项目目录
QString all_channel_particle_data_filename = project_dir.filePath("AllChannelParticleData.csv");
QFileInfo data_file_info(data_file_path);
QString all_channel_particle_data_filename = project_dir.filePath(data_file_info.fileName());
if (!QFile::copy(data_file_path, all_channel_particle_data_filename)) {
QMessageBox::warning(this, QStringLiteral(u"警告"), QStringLiteral(u"载入粒子数据文件到项目目录失败!"));
project_dir.removeRecursively();

View File

@ -43,7 +43,7 @@ int main(int argc, char *argv[])
app.setProperty("Description", app_desc.remove(QRegExp("\\s")));
// 设置应用字体
QFont f = app.font();
f.setFamily(QStringLiteral(u"微软雅黑"));
f.setFamily(QStringLiteral("Microsoft YaHei"));
f.setPointSizeF(10.0f);
app.setFont(f);
// 设置应用图标和关闭属性

View File

@ -1,6 +1,6 @@
TARGET = EnergySpectrumAnalyer
QT += core gui widgets concurrent
QT += core gui widgets concurrent printsupport
# You can make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
@ -26,6 +26,7 @@ include($${PROJECT_DIR}/3rdlib/QsLog/QsLog.pri)
# include($${PROJECT_DIR}/3rdlib/qwindowkit/qwindowkit.pri)
include($${PROJECT_DIR}/3rdlib/QtAdvancedDockingSystem/ads.pri)
include($${PROJECT_DIR}/3rdlib/csv/csv.pri)
include($${PROJECT_DIR}/3rdlib/qcustomplot/qcustomplot.pri)
DESTDIR = $${BUILD_BIN}
OBJECTS_DIR = $${BUILD_OBJ}/$${TARGET}/objs
@ -40,6 +41,7 @@ SOURCES += \
MeasureAnalysisActions.cpp \
MeasureAnalysisDataTableView.cpp \
MeasureAnalysisHistoryForm.cpp \
MeasureAnalysisParticleCountPlotView.cpp \
MeasureAnalysisProjectModel.cpp \
MeasureAnalysisTree.cpp \
MeasureAnalysisTreeItem.cpp \
@ -56,17 +58,18 @@ HEADERS += \
AboutDlg.h \
DataProcessWorkPool.h \
EneryScaleForm.h \
GlobalDefine.h \
MainWindow.h \
MeasureAnalysisActions.h \
MeasureAnalysisDataTableView.h \
MeasureAnalysisHistoryForm.h \
MeasureAnalysisParticleCountPlotView.h \
MeasureAnalysisProjectModel.h \
MeasureAnalysisTree.h \
MeasureAnalysisTreeItem.h \
MeasureAnalysisView.h \
MeasureDeviceParamsCfgForm.h \
NewMeasureAnalysisDlg.h \
OutputInfoDefine.h \
VirtualTable/CsvDataSource.h \
VirtualTable/DataSource.h \
VirtualTable/SampleDataSource.h \