modified surfacepanel

This commit is contained in:
pimin 2025-10-27 20:39:49 +08:00
parent 863e0867ce
commit 843d2cf158
8 changed files with 743 additions and 13 deletions

View File

@ -4,9 +4,9 @@
#include "common/SpdLogger.h"
// Forward declarations for future panel types
// #include "SurfacePanel.h"
#include "SurfacePanel.h"
#include "TablePanel.h"
// #include "LightPanel.h"
#include "LightPanel.h"
DataPanel* DataPanelFactory::CreatePanel(FileEntryType fileType, int index, const QString& filePath, QWidget* parent)
{
@ -19,7 +19,7 @@ DataPanel* DataPanelFactory::CreatePanel(FileEntryType fileType, int index, cons
case FileEntryType::Surface:
// TODO: Implement SurfacePanel
LOG_WARN("SurfacePanel not implemented yet, creating base DataPanel");
return new DataPanel(index, fileType, filePath, parent);
return new SurfacePanel(index, filePath, parent);
case FileEntryType::Table:
// TODO: Implement TablePanel
@ -29,7 +29,7 @@ DataPanel* DataPanelFactory::CreatePanel(FileEntryType fileType, int index, cons
case FileEntryType::Light:
// TODO: Implement LightPanel
LOG_WARN("LightPanel not implemented yet, creating base DataPanel");
return new DataPanel(index, fileType, filePath, parent);
return new LightPanel(index, filePath, parent);
default:
LOG_ERROR("Unsupported file type: {}", static_cast<int>(fileType));

View File

@ -0,0 +1,85 @@
#include "ui/Panel/LightPanel.h"
#include "ui/DockWidget.h"
#include "ui/DockTitleBar.h"
#include "common/SpdLogger.h"
#include <QHBoxLayout>
#include <QFileInfo>
#include <QMessageBox>
LightPanel::LightPanel(int index, const QString& filePath, QWidget* parent)
: DataPanel(index, FileEntryType::Curve, filePath, parent)
{
LOG_INFO("Created LightPanel {} for file: {}", index, filePath.toStdString());
}
LightPanel::LightPanel(int index, std::shared_ptr<FileEntryLight> fileEntry, QWidget* parent)
: DataPanel(index, fileEntry, parent)
{
if (fileEntry) {
LOG_INFO("Created LightPanel {} for chart: {}", index, fileEntry->GetName().toStdString());
// Override the title with chart name
title_ = QString("Light Panel %1 - %2").arg(index).arg(fileEntry->GetName());
}
else {
LOG_WARN("Created LightPanel {} with null chart data", index);
}
}
LightPanel::~LightPanel()
{
LOG_INFO("Destroyed LightPanel {}", GetIndex());
}
void LightPanel::RefreshPanel()
{
// Implement curve-specific refresh logic here
DataPanel::RefreshPanel();
if (auto fileEntry = fileEntry_->AsLight()) {
OnDataPanelUpdated(fileEntry);
}
LOG_INFO("Refreshed TablePanel {}", GetIndex());
}
void LightPanel::InitUI()
{
QHBoxLayout* mainLayout = new QHBoxLayout(this);
mainLayout->setContentsMargins(0, 0, 0, 0);
//mainLayout->addWidget(m_pTableWidget);
setLayout(mainLayout);
}
QString LightPanel::GetTypeDisplayName() const
{
return "Light";
}
void LightPanel::OnDataPanelUpdated(FileEntryLight* fileEntry)
{
QString strName = fileEntry->GetName();
updateTitle(strName);
//FileEntryTable::ChartProperties propChart = fileEntry->GetChartProperties();
//QStringList tableHeader = propChart.headerString.split(',', Qt::SkipEmptyParts);
//SetHeader(tableHeader);
//QString strFile = fileEntry->GetPath() + "/" + fileEntry->GetFileName();
//FileEntryTable::TableProperties listCurve = fileEntry->GetTableProperties();
//updateParseFile(strFile, propChart.timeParam, listCurve);
}
void LightPanel::OnTimeChanged(double time)
{
}
void LightPanel::updateTitle(const QString & title)
{
if (nullptr != dockWidget_)
{
dockWidget_->setWindowTitle(title);
}
}

63
src/ui/Panel/LightPanel.h Normal file
View File

@ -0,0 +1,63 @@
#pragma once
#include "DataPanel.h"
#include "workspace/FileEntry.h"
#include <memory>
class LightPanel : public DataPanel
{
Q_OBJECT
public:
/**
* @brief Constructor
* @param index Panel index
* @param filePath Associated file path
* @param parent Parent widget
*/
explicit LightPanel(int index, const QString& filePath, QWidget* parent = nullptr);
/**
* @brief Constructor with chart data
* @param index Panel index
* @param chartData Chart data containing curve information
* @param parent Parent widget
*/
explicit LightPanel(int index, std::shared_ptr<FileEntryLight> fileEntry, QWidget* parent = nullptr);
/**
* @brief Destructor
*/
virtual ~LightPanel();
/**
* @brief Get file type
* @return File type (always Curve for this class)
*/
FileEntryType GetFileType() const override { return FileEntryType::Light; }
/**
* @brief Refresh panel content
*/
void RefreshPanel() override;
protected:
/**
* @brief Initialize UI for curve-specific layout
*/
virtual void InitUI();
/**
* @brief Get type display name
* @return Display name for curve type
*/
QString GetTypeDisplayName() const override;
void OnDataPanelUpdated(FileEntryLight* fileEntry);
virtual void OnTimeChanged(double time);
private:
void updateTitle(const QString& title);
};

View File

@ -0,0 +1,388 @@
#include "ui/Panel/SurfacePanel.h"
#include "ui/DockWidget.h"
#include "ui/DockTitleBar.h"
#include "common/SpdLogger.h"
#include <QHBoxLayout>
#include <QFileInfo>
#include <QMessageBox>
#include <Q3DCamera>
SurfacePanel::SurfacePanel(int index, const QString& filePath, QWidget* parent)
: DataPanel(index, FileEntryType::Curve, filePath, parent)
{
m_iMinX = 0; m_iMaxX = 0;
m_iMinY = 0; m_iMaxY = 0;
m_iMinZ = 0; m_iMaxZ = 0;
LOG_INFO("Created SurfacePanel {} for file: {}", index, filePath.toStdString());
}
SurfacePanel::SurfacePanel(int index, std::shared_ptr<FileEntrySurface> fileEntry, QWidget* parent)
: DataPanel(index, fileEntry, parent)
{
m_iMinX = 0; m_iMaxX = 0;
m_iMinY = 0; m_iMaxY = 0;
m_iMinZ = 0; m_iMaxZ = 0;
if (fileEntry) {
LOG_INFO("Created SurfacePanel {} for chart: {}", index, fileEntry->GetName().toStdString());
// Override the title with chart name
title_ = QString("Surface Panel %1 - %2").arg(index).arg(fileEntry->GetName());
}
else {
LOG_WARN("Created SurfacePanel {} with null chart data", index);
}
}
SurfacePanel::~SurfacePanel()
{
LOG_INFO("Destroyed SurfacePanel {}", GetIndex());
}
void SurfacePanel::RefreshPanel()
{
// Implement curve-specific refresh logic here
DataPanel::RefreshPanel();
if (auto fileEntry = fileEntry_->AsSurface()) {
OnDataPanelUpdated(fileEntry);
}
LOG_INFO("Refreshed TablePanel {}", GetIndex());
}
void SurfacePanel::InitUI()
{
m_Surface.setFlags(m_Surface.flags());
m_Surface.setFlipHorizontalGrid(false);
m_p3DXAxis = new QValue3DAxis;
m_p3DXAxis->setSegmentCount(10);
m_p3DXAxis->setRange(-10, 10);
m_p3DYAxis = new QValue3DAxis;
m_p3DYAxis->setSegmentCount(10);
m_p3DYAxis->setRange(-10, 10);
m_p3DZAxis = new QValue3DAxis;
m_p3DZAxis->setSegmentCount(10);
m_p3DZAxis->setRange(-10, 10);
m_Surface.setAxisX(m_p3DXAxis);
m_Surface.setAxisY(m_p3DYAxis);
m_Surface.setAxisZ(m_p3DZAxis);
m_Surface.activeTheme()->setType(Q3DTheme::Theme(2));
m_pSeries = new QSurface3DSeries;
m_pSeries->setDrawMode(QSurface3DSeries::DrawSurface);
m_Surface.addSeries(m_pSeries);
QWidget* containerHandle = QWidget::createWindowContainer(&m_Surface);
containerHandle->setAutoFillBackground(true);
containerHandle->setAttribute(Qt::WA_OpaquePaintEvent, true);
containerHandle->setAttribute(Qt::WA_NoSystemBackground, false);
containerHandle->setUpdatesEnabled(false);
m_pSeries->setBaseColor(Qt::green);
m_pSeries->setColorStyle(Q3DTheme::ColorStyleUniform);
m_pSeries->setSingleHighlightColor(Qt::green);
m_pSeries->setMeshSmooth(false);
m_pSeries->setFlatShadingEnabled(false);
m_Surface.scene()->activeCamera()->setCameraPreset(Q3DCamera::CameraPreset(13));
QHBoxLayout* mainLayout = new QHBoxLayout(this);
mainLayout->setContentsMargins(0, 0, 0, 0);
mainLayout->addWidget(containerHandle);
setLayout(mainLayout);
}
QString SurfacePanel::GetTypeDisplayName() const
{
return "Surface";
}
void SurfacePanel::OnDataPanelUpdated(FileEntrySurface* fileEntry)
{
QString strName = fileEntry->GetName();
updateTitle(strName);
FileEntrySurface::ChartProperties propChart = fileEntry->GetChartProperties();
updateTitleAxis(propChart.xTitle, propChart.yTitle, propChart.zTitle);
updateMinMaxX(propChart.xMin, propChart.xMax, propChart.xCount);
updateMinMaxY(propChart.yMin, propChart.yMax, propChart.yCount);
updateMinMaxZ(propChart.zMin, propChart.zMax, propChart.zCount);
QString strFile = fileEntry->GetPath() + "/" + fileEntry->GetFileName();
FileEntrySurface::SurfaceProperties listCurve = fileEntry->GetSurfaceProperties();
updateParseFile(strFile, propChart.timeParam, listCurve);
}
void SurfacePanel::OnTimeChanged(double time)
{
if (m_data.size() > 0)
{
m_pSeries->dataProxy()->resetArray(nullptr);
QMap< double, QMap< int, QVector< QVector<QVector3D> > > >::const_iterator ite = m_data.lowerBound(time);
if (ite == m_data.end())
{
ite--;
}
QMap< int, QVector< QVector<QVector3D> > > mapData = ite.value();
for (QMap< int, QVector< QVector<QVector3D> > >::Iterator it = mapData.begin(); it != mapData.end(); it++)
{
int nIndex = it.key();
QVector< QVector<QVector3D> > listRowData = it.value();
QSurfaceDataArray* data = new QSurfaceDataArray;
for (int nI = 0; nI < listRowData.size(); nI++)
{
QSurfaceDataRow* dataRow = new QSurfaceDataRow;
QVector<QVector3D> listColData = listRowData[nI];
for (int nJ = 0; nJ < listColData.size(); nJ++)
{
QVector3D v3d = listColData[nJ];
*dataRow << v3d;
}
*data << dataRow;
}
m_pSeries->dataProxy()->resetArray(data);
}
}
m_Surface.setShadowQuality(QAbstract3DGraph::ShadowQuality::ShadowQualityNone);
}
void SurfacePanel::updateTitle(const QString & title)
{
if (nullptr != dockWidget_)
{
dockWidget_->setWindowTitle(title);
}
}
void SurfacePanel::updateTitleAxis(const QString & xTitle, const QString & yTitle, const QString & zTitle)
{
m_p3DXAxis->setTitle(xTitle);
m_p3DXAxis->setTitleVisible(true);
m_p3DYAxis->setTitle(yTitle);
m_p3DYAxis->setTitleVisible(true);
m_p3DZAxis->setTitle(zTitle);
m_p3DZAxis->setTitleVisible(true);
}
void SurfacePanel::updateMinMaxX(float min, float max, int count)
{
if (max > min)
{
m_iMinX = min;
m_iMaxX = max;
if (count > 0)
{
m_p3DXAxis->setSegmentCount(count);
}
m_p3DXAxis->setRange(min, max);
}
}
void SurfacePanel::updateMinMaxY(float min, float max, int count)
{
if (max > min)
{
m_iMinY = min;
m_iMaxY = max;
if (count > 0)
{
m_p3DYAxis->setSegmentCount(count);
}
m_p3DYAxis->setRange(min, max);
}
}
void SurfacePanel::updateMinMaxZ(float min, float max, int count)
{
if (max > min)
{
m_iMinZ = min;
m_iMaxZ = max;
if (count > 0)
{
m_p3DZAxis->setSegmentCount(count);
}
m_p3DZAxis->setRange(min, max);
}
}
void SurfacePanel::updateParseFile(const QString & strFile, int nT, FileEntrySurface::SurfaceProperties listCurve)
{
if (strFile.isEmpty())
{
QMessageBox::information(nullptr, QString::fromLocal8Bit("提示"), QString::fromLocal8Bit("请检查数据文件路径!"));
return;
}
QFile file(strFile);
if (file.open(QIODevice::ReadOnly))
{
for (int nI = 0; nI < listCurve.size(); nI++)
{
FileEntrySurface::SurfaceProperty surface = listCurve.at(nI);
QLinearGradient gr;
gr.setColorAt(0.0, surface.color);
gr.setColorAt(0.5, Qt::yellow);
gr.setColorAt(0.8, Qt::red);
gr.setColorAt(1.0, Qt::darkRed);
m_pSeries->setBaseGradient(gr);
m_pSeries->setColorStyle(Q3DTheme::ColorStyleRangeGradient);
//m_pSeries->setSingleHighlightColor(Qt::green);
}
bool bResetAxisX = false;
if (m_iMaxX == m_iMinX)
{
bResetAxisX = true;
}
bool bResetAxisY = false;
if (m_iMaxZ == m_iMinZ)
{
bResetAxisY = true;
}
bool bResetAxisZ = false;
if (m_iMaxY == m_iMinY)
{
bResetAxisZ = true;
}
while (!file.atEnd())
{
QString strLine = file.readLine().simplified();
if (!strLine.isEmpty())
{
QStringList listLine = strLine.split(" ");
double t = listLine.at(nT).toDouble();
QMap< int, QVector< QVector<QVector3D> > > mapData;
for (int nI = 0; nI < listCurve.size(); nI++)
{
FileEntrySurface::SurfaceProperty surface = listCurve.at(nI);
int nStart = surface.start;
int nStop = surface.stop;
if (nStart == 0)
{
nStart = 1;
}
if (nStop == 0)
{
nStop = listLine.size();
}
QString strX = surface.x;
QString strY = surface.y;
QString strZ = surface.z;
double xInput = 0;
double yInput = 0;
double zInput = 0.0;
QVector< QVector<QVector3D> > listRowData;
int nRow = 0;
int nCol = 0;
for (int nJ = nStart; nJ < nStop; nJ += 3)
{
int x = listLine.at(nJ).toDouble();
int y = listLine.at(nJ + 1).toDouble();
double z = listLine.at(nJ + 2).toDouble();
if (strX == "x")
{
xInput = x;
}
else if (strX == "y")
{
xInput = y;
}
else if (strX == "z")
{
xInput = z;
}
if (strY == "x")
{
yInput = x;
}
else if (strY == "y")
{
yInput = y;
}
else if (strY == "z")
{
yInput = z;
}
if (strZ == "x")
{
zInput = x;
}
else if (strZ == "y")
{
zInput = y;
}
else if (strZ == "z")
{
zInput = z;
}
QVector3D v3d = QVector3D(xInput, yInput, zInput);
if (nRow == x)
{
int nIndex = listRowData.size() - 1;
QVector<QVector3D> listColData = listRowData[nIndex];
listColData.push_back(v3d);
listRowData.replace(nIndex, listColData);
}
else
{
QVector<QVector3D> listColData;
listColData.push_back(v3d);
listRowData.push_back(listColData);
}
nRow = x;
nCol = y;
}
mapData.insert(nI, listRowData);
}
m_data.insert(t, mapData);
}
}
if (m_iMaxX == m_iMinX)
{
m_p3DXAxis->setAutoAdjustRange(true);
}
if (m_iMaxZ == m_iMinZ)
{
m_p3DZAxis->setAutoAdjustRange(true);
}
if (m_iMaxY == m_iMinY)
{
m_p3DYAxis->setAutoAdjustRange(true);
}
m_Surface.setHorizontalAspectRatio(1.0);
file.close();
}
}

View File

@ -0,0 +1,91 @@
#pragma once
#include "DataPanel.h"
#include "workspace/FileEntry.h"
#include <memory>
#include <Q3DSurface>
#include <QValue3DAxis>
using namespace QtDataVisualization;
class SurfacePanel : public DataPanel
{
Q_OBJECT
public:
/**
* @brief Constructor
* @param index Panel index
* @param filePath Associated file path
* @param parent Parent widget
*/
explicit SurfacePanel(int index, const QString& filePath, QWidget* parent = nullptr);
/**
* @brief Constructor with chart data
* @param index Panel index
* @param chartData Chart data containing curve information
* @param parent Parent widget
*/
explicit SurfacePanel(int index, std::shared_ptr<FileEntrySurface> fileEntry, QWidget* parent = nullptr);
/**
* @brief Destructor
*/
virtual ~SurfacePanel();
/**
* @brief Get file type
* @return File type (always Curve for this class)
*/
FileEntryType GetFileType() const override { return FileEntryType::Surface; }
/**
* @brief Refresh panel content
*/
void RefreshPanel() override;
protected:
/**
* @brief Initialize UI for curve-specific layout
*/
virtual void InitUI();
/**
* @brief Get type display name
* @return Display name for curve type
*/
QString GetTypeDisplayName() const override;
void OnDataPanelUpdated(FileEntrySurface* fileEntry);
virtual void OnTimeChanged(double time);
private:
void updateTitle(const QString& title);
void updateTitleAxis(const QString& xTitle, const QString& yTitle, const QString& zTitle);
void updateMinMaxX(float min, float max, int count);
void updateMinMaxY(float min, float max, int count);
void updateMinMaxZ(float min, float max, int count);
void updateParseFile(const QString& strFile, int nT, FileEntrySurface::SurfaceProperties listCurve);
private:
Q3DSurface m_Surface;
QSurface3DSeries* m_pSeries;
QValue3DAxis* m_p3DXAxis;
QValue3DAxis* m_p3DYAxis;
QValue3DAxis* m_p3DZAxis;
float m_iMinX = 0;
float m_iMaxX = 10;
float m_iMinY = 0;
float m_iMaxY = 10;
float m_iMinZ = 0;
float m_iMaxZ = 10;
QMap< double, QMap< int, QVector< QVector<QVector3D> > > > m_data;
};

View File

@ -375,7 +375,7 @@ void AddSurfaceFileDlg::accept()
}
// Set description
fileEntry->SetDescription(GetDescription());
//fileEntry->SetDescription(GetDescription());
// Add to workspace
WorkSpace* workspace = WorkSpaceManager::Get().GetCurrent();

View File

@ -180,12 +180,115 @@ FileEntrySurface* FileEntrySurface::AsSurface() {
return this;
}
void FileEntrySurface::SetDescription(const QString& description) {
description_ = description;
bool FileEntrySurface::SaveFiles(tinyxml2::XMLElement * scene, tinyxml2::XMLDocument * doc)
{
if (!scene || !doc) {
LOG_ERROR("Invalid XML parameters");
return false;
}
// 创建 <chart> 元素
tinyxml2::XMLElement* chartElement = doc->NewElement("chart");
scene->InsertEndChild(chartElement);
// 设置chart属性
chartElement->SetAttribute("name", name_.toUtf8().constData());
chartElement->SetAttribute("path", fileName_.toUtf8().constData());
chartElement->SetAttribute("xCount", chartProperties_.xCount);
chartElement->SetAttribute("yCount", chartProperties_.yCount);
chartElement->SetAttribute("zCount", chartProperties_.zCount);
chartElement->SetAttribute("xTitle", chartProperties_.xTitle.toUtf8().constData());
chartElement->SetAttribute("yTitle", chartProperties_.yTitle.toUtf8().constData());
chartElement->SetAttribute("zTitle", chartProperties_.zTitle.toUtf8().constData());
chartElement->SetAttribute("xMin", chartProperties_.xMin);
chartElement->SetAttribute("xMax", chartProperties_.xMax);
chartElement->SetAttribute("yMin", chartProperties_.yMin);
chartElement->SetAttribute("yMax", chartProperties_.yMax);
chartElement->SetAttribute("zMin", chartProperties_.zMin);
chartElement->SetAttribute("zMax", chartProperties_.zMax);
chartElement->SetAttribute("t", chartProperties_.timeParam);
// 为每个CurveProperty创建<curve>元素
for (const auto& curve : surfaceProperties_) {
tinyxml2::XMLElement* curveElement = doc->NewElement("curve");
chartElement->InsertEndChild(curveElement);
curveElement->SetAttribute("name", curve.name.toUtf8().constData());
curveElement->SetAttribute("color", QColorToString(curve.color).toUtf8().constData());
curveElement->SetAttribute("start", curve.start);
curveElement->SetAttribute("stop", curve.stop);
curveElement->SetAttribute("x", curve.x.toUtf8().constData());
curveElement->SetAttribute("y", curve.y.toUtf8().constData());
curveElement->SetAttribute("z", curve.z.toUtf8().constData());
}
return true;
}
const QString& FileEntrySurface::GetDescription() const {
return description_;
bool FileEntrySurface::ParseFiles(const tinyxml2::XMLElement * element)
{
if (!element) {
LOG_ERROR("Invalid XML element");
return false;
}
// 解析chart属性
const char* nameAttr = element->Attribute("name");
const char* pathAttr = element->Attribute("path");
if (nameAttr) name_ = QString::fromUtf8(nameAttr);
if (pathAttr) {
QString fullPath = QString::fromUtf8(pathAttr);
QFileInfo fileInfo(fullPath);
fileName_ = fileInfo.fileName();
path_ = fileInfo.absolutePath();
}
chartProperties_.xCount = element->IntAttribute("xCount", 0);
chartProperties_.yCount = element->IntAttribute("yCount", 0);
chartProperties_.zCount = element->IntAttribute("zCount", 0);
const char* xTitleAttr = element->Attribute("xTitle");
const char* yTitleAttr = element->Attribute("yTitle");
const char* zTitleAttr = element->Attribute("zTitle");
if (xTitleAttr) chartProperties_.xTitle = QString::fromUtf8(xTitleAttr);
if (yTitleAttr) chartProperties_.yTitle = QString::fromUtf8(yTitleAttr);
if (zTitleAttr) chartProperties_.zTitle = QString::fromUtf8(zTitleAttr);
chartProperties_.xMin = element->DoubleAttribute("xMin", 0.0);
chartProperties_.xMax = element->DoubleAttribute("xMax", 0.0);
chartProperties_.yMin = element->DoubleAttribute("yMin", 0.0);
chartProperties_.yMax = element->DoubleAttribute("yMax", 0.0);
chartProperties_.zMin = element->DoubleAttribute("zMin", 0.0);
chartProperties_.zMax = element->DoubleAttribute("zMax", 0.0);
chartProperties_.timeParam = element->DoubleAttribute("t", 0.0);
surfaceProperties_.clear();
for (const tinyxml2::XMLElement* curveElement = element->FirstChildElement("curve");
curveElement != nullptr;
curveElement = curveElement->NextSiblingElement("curve")) {
SurfaceProperty curve;
const char* curveNameAttr = curveElement->Attribute("name");
const char* colorAttr = curveElement->Attribute("color");
if (curveNameAttr) curve.name = QString::fromUtf8(curveNameAttr);
if (colorAttr) curve.color = StringToQColor(QString::fromUtf8(colorAttr));
curve.start = curveElement->IntAttribute("start", 0);
curve.stop = curveElement->IntAttribute("stop", 0);
const char* xAttr = curveElement->Attribute("x");
const char* yAttr = curveElement->Attribute("y");
const char* zAttr = curveElement->Attribute("z");
if (xAttr) curve.x = QString::fromUtf8(xAttr);
if (yAttr) curve.y = QString::fromUtf8(yAttr);
if (zAttr) curve.z = QString::fromUtf8(zAttr);
surfaceProperties_.append(curve);
}
return true;
}
// FileEntryTable method implementations
@ -290,6 +393,7 @@ bool FileEntryTable::ParseFiles(const tinyxml2::XMLElement * element)
chartProperties_.timeParam = element->DoubleAttribute("t", 0.0);
tableProperties_.clear();
for (const tinyxml2::XMLElement* curveElement = element->FirstChildElement("curve");
curveElement != nullptr;
curveElement = curveElement->NextSiblingElement("curve")) {

View File

@ -208,14 +208,13 @@ public:
// Type conversion
FileEntrySurface* AsSurface() override;
// Description management
void SetDescription(const QString& description);
const QString& GetDescription() const;
// XML处理方法
bool SaveFiles(tinyxml2::XMLElement* scene, tinyxml2::XMLDocument* doc) override;
bool ParseFiles(const tinyxml2::XMLElement* element) override;
private:
ChartProperties chartProperties_;
SurfaceProperties surfaceProperties_;
QString description_;
};
class FileEntryTable : public FileEntry {