瀏覽代碼

保存读取文件功能

master
鹏鹏 李 3 天之前
父節點
當前提交
0b76463cae
共有 15 個檔案被更改,包括 372 行新增24 行删除
  1. +1
    -1
      connection.cpp
  2. +4
    -2
      editor.pro
  3. +1
    -1
      editor.pro.user
  4. +62
    -2
      hmi.cpp
  5. +6
    -1
      hmi.h
  6. +5
    -11
      item.cpp
  7. +8
    -3
      item.h
  8. +89
    -0
      mainwindow.cpp
  9. +8
    -0
      mainwindow.h
  10. +19
    -0
      mygraphicsview.cpp
  11. +1
    -0
      mygraphicsview.h
  12. +66
    -2
      plc.cpp
  13. +6
    -1
      plc.h
  14. +68
    -0
      project.cpp
  15. +28
    -0
      project.h

+ 1
- 1
connection.cpp 查看文件

@@ -8,7 +8,7 @@ Connection::Connection(Item* from, Item::AnchorType fromType,
: QGraphicsLineItem(parent), : QGraphicsLineItem(parent),
from_(from), to_(to), fromType_(fromType), toType_(toType) from_(from), to_(to), fromType_(fromType), toType_(toType)
{ {
setZValue(-1); // 在图元之下
setZValue(-1);
setPen(QPen(Qt::black, 2)); setPen(QPen(Qt::black, 2));
setFlags(QGraphicsItem::ItemIsSelectable); setFlags(QGraphicsItem::ItemIsSelectable);
from_->addConnection(this); from_->addConnection(this);


+ 4
- 2
editor.pro 查看文件

@@ -28,7 +28,8 @@ SOURCES += \
main.cpp \ main.cpp \
mainwindow.cpp \ mainwindow.cpp \
mygraphicsview.cpp \ mygraphicsview.cpp \
plc.cpp
plc.cpp \
project.cpp


HEADERS += \ HEADERS += \
button.h \ button.h \
@@ -42,7 +43,8 @@ HEADERS += \
light.h \ light.h \
mainwindow.h \ mainwindow.h \
mygraphicsview.h \ mygraphicsview.h \
plc.h
plc.h \
project.h


FORMS += \ FORMS += \
hmi.ui \ hmi.ui \


+ 1
- 1
editor.pro.user 查看文件

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE QtCreatorProject> <!DOCTYPE QtCreatorProject>
<!-- Written by QtCreator 4.11.1, 2025-08-07T09:52:05. -->
<!-- Written by QtCreator 4.11.1, 2025-08-07T18:51:27. -->
<qtcreator> <qtcreator>
<data> <data>
<variable>EnvironmentId</variable> <variable>EnvironmentId</variable>


+ 62
- 2
hmi.cpp 查看文件

@@ -16,8 +16,8 @@ HMI::HMI(QWidget *parent) :
{ {
ui->setupUi(this); ui->setupUi(this);
/* 1. 场景 */ /* 1. 场景 */
m_scene = new QGraphicsScene(this);
ui->graphicsView->setScene(m_scene);
hmi_scene_ = new QGraphicsScene(this);
ui->graphicsView->setScene(hmi_scene_);
ui->graphicsView->setSceneRect(0, 0, 800, 600); ui->graphicsView->setSceneRect(0, 0, 800, 600);
ui->graphicsView->setDragMode(QGraphicsView::RubberBandDrag); ui->graphicsView->setDragMode(QGraphicsView::RubberBandDrag);


@@ -100,6 +100,66 @@ void HMI::createComponents()
} }
} }


void HMI::clearScene()
{
hmi_scene_->clear();
}

void HMI::applyProjectToScene(const Project& proj)
{
clearScene();
QVector<Item*> itemObjs;
for (const auto& d : proj.items_) {
Item* item = creatItem(d.type);
if (!item) continue;
item->setPos(d.x, d.y);
connect(item, &Item::requestCopy, ui->graphicsView, &MyGraphicsView::onItemRequestCopy);
connect(item, &Item::requestDelete, ui->graphicsView, &MyGraphicsView::onItemRequestDelete);
hmi_scene_->addItem(item);
itemObjs.append(item);
}
// for (const auto& c : proj.connections_) {
// if (c.from >= 0 && c.from < itemObjs.size() && c.to >= 0 && c.to < itemObjs.size()) {
// Connection* conn = new Connection(
// itemObjs[c.from], static_cast<Item::AnchorType>(c.fromType),
// itemObjs[c.to], static_cast<Item::AnchorType>(c.toType));
// hmi_scene_->addItem(conn);
// }
// }
}

void HMI::extractSceneToProject(Project& proj)
{
proj.clear();
QList<Item*> items;
for (QGraphicsItem* gi : hmi_scene_->items()) {
if (Item* it = dynamic_cast<Item*>(gi)) {
items.append(it);
}
}
for (Item* it : items) {
Project::ItemData d;
d.type = it->itemType();
d.x = it->pos().x();
d.y = it->pos().y();
proj.items_.append(d);
}
for (QGraphicsItem* gi : hmi_scene_->items()) {
if (Connection* conn = dynamic_cast<Connection*>(gi)) {
int fromIdx = items.indexOf(conn->from_);
int toIdx = items.indexOf(conn->to_);
if (fromIdx >= 0 && toIdx >= 0) {
Project::ConnectionData c;
c.from = fromIdx;
c.to = toIdx;
c.fromType = static_cast<int>(conn->fromType_);
c.toType = static_cast<int>(conn->toType_);
proj.connections_.append(c);
}
}
}
}

void HMI::onListwidgetCurrenttextchanged(const QString &text) void HMI::onListwidgetCurrenttextchanged(const QString &text)
{ {
selectedComponentType = text; selectedComponentType = text;


+ 6
- 1
hmi.h 查看文件

@@ -3,6 +3,7 @@


#include <QGraphicsScene> #include <QGraphicsScene>
#include <QWidget> #include <QWidget>
#include <project.h>


namespace Ui { namespace Ui {
class HMI; class HMI;
@@ -17,6 +18,10 @@ public:
~HMI(); ~HMI();
void createComponents(); void createComponents();


void clearScene();
void applyProjectToScene(const Project& proj);
void extractSceneToProject(Project& proj);

protected: protected:
bool eventFilter(QObject *obj, QEvent *event) override; bool eventFilter(QObject *obj, QEvent *event) override;


@@ -25,7 +30,7 @@ private slots:


private: private:
Ui::HMI *ui; Ui::HMI *ui;
QGraphicsScene *m_scene;
QGraphicsScene *hmi_scene_;
QString selectedComponentType; QString selectedComponentType;
}; };




+ 5
- 11
item.cpp 查看文件

@@ -62,6 +62,7 @@ void Item::MenuActions(QMenu *menu)
{ {
menu->addAction("复制"); menu->addAction("复制");
menu->addAction("删除"); menu->addAction("删除");
menu->addAction("对象");
} }


void Item::addMenuActions(QMenu *menu) void Item::addMenuActions(QMenu *menu)
@@ -74,9 +75,12 @@ void Item::handleMenuAction(QAction *action)
if (action->text() == "复制") { if (action->text() == "复制") {
emit requestCopy(this); emit requestCopy(this);
} }
else if (action->text() == "删除") {
if (action->text() == "删除") {
emit requestDelete(this); emit requestDelete(this);
} }
if (action->text() == "对象"){
emit requestBindRegister(this);
}
} }


QVariant Item::itemChange(GraphicsItemChange change, const QVariant &value) QVariant Item::itemChange(GraphicsItemChange change, const QVariant &value)
@@ -90,16 +94,6 @@ QVariant Item::itemChange(GraphicsItemChange change, const QVariant &value)


void Item::contextMenuEvent(QGraphicsSceneContextMenuEvent *event) void Item::contextMenuEvent(QGraphicsSceneContextMenuEvent *event)
{ {
// QMenu menu;
// QAction* copyAct = menu.addAction("复制");
// QAction* deleteAct = menu.addAction("删除");
// QAction* selected = menu.exec(event->screenPos());
// if (selected == copyAct) {
// emit requestCopy(this);
// }
// if (selected == deleteAct) {
// emit requestDelete(this);
// }
QMenu menu; QMenu menu;


// 创建菜单 // 创建菜单


+ 8
- 3
item.h 查看文件

@@ -21,19 +21,24 @@ public:
void removeConnection(Connection* conn); void removeConnection(Connection* conn);
QList<Connection*> connections(); QList<Connection*> connections();
QString itemType(); QString itemType();
virtual void MenuActions(QMenu *menu); // 添加基本菜单项
virtual void addMenuActions(QMenu *menu); // 添加额外菜单项
virtual void handleMenuAction(QAction *action); // 处理菜单动作
void setRegisterId(const QString& id) { registerId_ = id; }
QString registerId() const { return registerId_; }


signals: signals:
void requestCopy(Item*); void requestCopy(Item*);
void requestDelete(Item*); void requestDelete(Item*);
void requestBindRegister(Item*);


protected: protected:
virtual void MenuActions(QMenu *menu);
virtual void addMenuActions(QMenu *menu);
virtual void handleMenuAction(QAction *action);
QVariant itemChange(GraphicsItemChange change, const QVariant &value) override; QVariant itemChange(GraphicsItemChange change, const QVariant &value) override;
void contextMenuEvent(QGraphicsSceneContextMenuEvent *event) override; void contextMenuEvent(QGraphicsSceneContextMenuEvent *event) override;
QString type_; QString type_;
QList<Connection*> connections_; QList<Connection*> connections_;
QString registerId_;
}; };


#endif // ITEM_H #endif // ITEM_H

+ 89
- 0
mainwindow.cpp 查看文件

@@ -11,6 +11,7 @@
#include <QGraphicsView> #include <QGraphicsView>
#include <QMessageBox> #include <QMessageBox>
#include <QAction> #include <QAction>
#include <QFileDialog>
#include "creatitem.h" #include "creatitem.h"


MainWindow::MainWindow(QWidget *parent) MainWindow::MainWindow(QWidget *parent)
@@ -24,6 +25,13 @@ MainWindow::MainWindow(QWidget *parent)
hmi_->hide(); hmi_->hide();
connect(ui->action_plc,&QAction::triggered,this,&MainWindow::plcChange); connect(ui->action_plc,&QAction::triggered,this,&MainWindow::plcChange);
connect(ui->action_hmi,&QAction::triggered,this,&MainWindow::hmiChange); connect(ui->action_hmi,&QAction::triggered,this,&MainWindow::hmiChange);

connect(ui->action_new, &QAction::triggered, this, &MainWindow::newProject);
connect(ui->action_save, &QAction::triggered, this, &MainWindow::saveProject);
connect(ui->action_open, &QAction::triggered, this, &MainWindow::openProject);

plc_->applyProjectToScene(plcProject_); // 初始空
hmi_->applyProjectToScene(hmiProject_);
} }


MainWindow::~MainWindow() MainWindow::~MainWindow()
@@ -35,11 +43,92 @@ void MainWindow::plcChange()
{ {
plc_->show(); plc_->show();
hmi_->hide(); hmi_->hide();
currentIsPLC_ = true;
setWindowTitle((plcFilePath_.isEmpty() ? "未命名项目" : QFileInfo(plcFilePath_).fileName()) + " - PLC编辑器");
} }


void MainWindow::hmiChange() void MainWindow::hmiChange()
{ {
hmi_->show(); hmi_->show();
plc_->hide(); plc_->hide();
currentIsPLC_ = false;
setWindowTitle((hmiFilePath_.isEmpty() ? "未命名项目" : QFileInfo(hmiFilePath_).fileName()) + " - HMI编辑器");
}

void MainWindow::newProject()
{
if (currentIsPLC_) {
plcProject_.clear();
plcFilePath_.clear();
plc_->clearScene();
setWindowTitle("未命名项目 - PLC编辑器");
} else {
hmiProject_.clear();
hmiFilePath_.clear();
hmi_->clearScene();
setWindowTitle("未命名项目 - HMI编辑器");
}
} }


void MainWindow::openProject()
{
if (currentIsPLC_)
{
QString filePath = QFileDialog::getOpenFileName(this, "打开项目", "", "项目文件 (*.plcproj)");
if (filePath.isEmpty()) return;
if (plcProject_.loadFromFile(filePath))
{
plcFilePath_ = filePath;
plc_->applyProjectToScene(plcProject_);
setWindowTitle(QFileInfo(plcFilePath_).fileName() + " - PLC编辑器");
}
else
{
QMessageBox::critical(this, "错误", "无法打开PLC项目文件");
}
}
else
{
QString filePath = QFileDialog::getOpenFileName(this, "打开项目", "", "项目文件 (*.hmiproj)");
if (filePath.isEmpty()) return;
if (hmiProject_.loadFromFile(filePath))
{
hmiFilePath_ = filePath;
hmi_->applyProjectToScene(hmiProject_);
setWindowTitle(QFileInfo(hmiFilePath_).fileName() + " - HMI编辑器");
}
else
{
QMessageBox::critical(this, "错误", "无法打开HMI项目文件");
}
}
}

void MainWindow::saveProject()
{
if (currentIsPLC_) {
if (plcFilePath_.isEmpty()) {
QString filePath = QFileDialog::getSaveFileName(this, "保存项目", "", "PLC项目文件 (*.plcproj)");
if (filePath.isEmpty()) return;
if (!filePath.endsWith(".plcproj", Qt::CaseInsensitive))
filePath += ".plcproj";
plcFilePath_ = filePath;
}
plc_->extractSceneToProject(plcProject_);
if (!plcProject_.saveToFile(plcFilePath_)) {
QMessageBox::critical(this, "错误", "保存项目失败");
}
} else {
if (hmiFilePath_.isEmpty()) {
QString filePath = QFileDialog::getSaveFileName(this, "保存项目", "", "HMI项目文件 (*.hmiproj)");
if (filePath.isEmpty()) return;
if (!filePath.endsWith(".hmiproj", Qt::CaseInsensitive))
filePath += ".hmiproj";
hmiFilePath_ = filePath;
}
hmi_->extractSceneToProject(hmiProject_);
if (!hmiProject_.saveToFile(hmiFilePath_)) {
QMessageBox::critical(this, "错误", "保存项目失败");
}
}
}

+ 8
- 0
mainwindow.h 查看文件

@@ -21,11 +21,19 @@ public:
private slots: private slots:
void plcChange(); void plcChange();
void hmiChange(); void hmiChange();
void newProject();
void openProject();
void saveProject();


private: private:
Ui::MainWindow *ui; Ui::MainWindow *ui;
PLC *plc_; PLC *plc_;
HMI *hmi_; HMI *hmi_;
Project plcProject_;
Project hmiProject_;
QString plcFilePath_;
QString hmiFilePath_;
bool currentIsPLC_ = true;
}; };


#endif // MAINWINDOW_H #endif // MAINWINDOW_H

+ 19
- 0
mygraphicsview.cpp 查看文件

@@ -4,6 +4,7 @@
#include <QGraphicsScene> #include <QGraphicsScene>
#include <QDebug> #include <QDebug>
#include <QMenu> #include <QMenu>
#include <QInputDialog>


MyGraphicsView::ClipInfo MyGraphicsView::clipboard_ = {}; MyGraphicsView::ClipInfo MyGraphicsView::clipboard_ = {};


@@ -46,6 +47,7 @@ void MyGraphicsView::dropEvent(QDropEvent *event)
item->setPos(scenePos); item->setPos(scenePos);
connect(item, &Item::requestCopy, this, &MyGraphicsView::onItemRequestCopy); connect(item, &Item::requestCopy, this, &MyGraphicsView::onItemRequestCopy);
connect(item, &Item::requestDelete, this, &MyGraphicsView::onItemRequestDelete); connect(item, &Item::requestDelete, this, &MyGraphicsView::onItemRequestDelete);
connect(item, &Item::requestBindRegister, this, &MyGraphicsView::onItemRequestBindRegister);
scene()->addItem(item); scene()->addItem(item);


event->acceptProposedAction(); event->acceptProposedAction();
@@ -92,6 +94,7 @@ void MyGraphicsView::keyPressEvent(QKeyEvent *event)
newItem->setPos(center); newItem->setPos(center);
connect(newItem, &Item::requestCopy, this, &MyGraphicsView::onItemRequestCopy); connect(newItem, &Item::requestCopy, this, &MyGraphicsView::onItemRequestCopy);
connect(newItem, &Item::requestDelete, this, &MyGraphicsView::onItemRequestDelete); connect(newItem, &Item::requestDelete, this, &MyGraphicsView::onItemRequestDelete);
connect(newItem, &Item::requestBindRegister, this, &MyGraphicsView::onItemRequestBindRegister);
scene()->addItem(newItem); scene()->addItem(newItem);
} }
} else { } else {
@@ -112,6 +115,7 @@ void MyGraphicsView::contextMenuEvent(QContextMenuEvent *event)
newItem->setPos(scenePos); newItem->setPos(scenePos);
connect(newItem, &Item::requestCopy, this, &MyGraphicsView::onItemRequestCopy); connect(newItem, &Item::requestCopy, this, &MyGraphicsView::onItemRequestCopy);
connect(newItem, &Item::requestDelete, this, &MyGraphicsView::onItemRequestDelete); connect(newItem, &Item::requestDelete, this, &MyGraphicsView::onItemRequestDelete);
connect(newItem, &Item::requestBindRegister, this, &MyGraphicsView::onItemRequestBindRegister);
scene()->addItem(newItem); scene()->addItem(newItem);
} }
} else { } else {
@@ -159,6 +163,21 @@ void MyGraphicsView::onItemRequestDelete(Item *item)
delete item; delete item;
} }


void MyGraphicsView::onItemRequestBindRegister(Item *item)
{
bool ok = false;
QString reg = QInputDialog::getText(this,
"寄存器", "编号:",
QLineEdit::Normal,
item->registerId(),
&ok);
if (ok && !reg.isEmpty()) {
item->setRegisterId(reg);
// 可选:在图元上显示寄存器编号
item->update();
}
}

void MyGraphicsView::mousePressEvent(QMouseEvent *event) void MyGraphicsView::mousePressEvent(QMouseEvent *event)
{ {
if (event->button() == Qt::LeftButton) { if (event->button() == Qt::LeftButton) {


+ 1
- 0
mygraphicsview.h 查看文件

@@ -44,6 +44,7 @@ private:
public slots: public slots:
void onItemRequestCopy(Item*); void onItemRequestCopy(Item*);
void onItemRequestDelete(Item*); void onItemRequestDelete(Item*);
void onItemRequestBindRegister(Item*);
}; };


#endif // MYGRAPHICSVIEW_H #endif // MYGRAPHICSVIEW_H

+ 66
- 2
plc.cpp 查看文件

@@ -18,8 +18,8 @@ PLC::PLC(QWidget *parent) :
{ {
ui->setupUi(this); ui->setupUi(this);
/* 1. 场景 */ /* 1. 场景 */
m_scene = new QGraphicsScene(this);
ui->graphicsView->setScene(m_scene);
plc_scene_ = new QGraphicsScene(this);
ui->graphicsView->setScene(plc_scene_);
ui->graphicsView->setSceneRect(0, 0, 800, 600); ui->graphicsView->setSceneRect(0, 0, 800, 600);
ui->graphicsView->setDragMode(QGraphicsView::RubberBandDrag); ui->graphicsView->setDragMode(QGraphicsView::RubberBandDrag);


@@ -105,6 +105,70 @@ void PLC::createComponents()
} }
} }


void PLC::clearScene()
{
plc_scene_->clear();
}

void PLC::applyProjectToScene(const Project& proj)
{
clearScene();
QVector<Item*> itemObjs;
for (const auto& d : proj.items_) {
Item* item = creatItem(d.type);
if (!item) continue;
item->setPos(d.x, d.y);
connect(item, &Item::requestCopy, ui->graphicsView, &MyGraphicsView::onItemRequestCopy);
connect(item, &Item::requestDelete, ui->graphicsView, &MyGraphicsView::onItemRequestDelete);
connect(item, &Item::requestBindRegister, ui->graphicsView, &MyGraphicsView::onItemRequestBindRegister);
plc_scene_->addItem(item);
itemObjs.append(item);
}
for (const auto& c : proj.connections_) {
if (c.from >= 0 && c.from < itemObjs.size() && c.to >= 0 && c.to < itemObjs.size()) {
Connection* conn = new Connection(
itemObjs[c.from], static_cast<Item::AnchorType>(c.fromType),
itemObjs[c.to], static_cast<Item::AnchorType>(c.toType));
plc_scene_->addItem(conn);
}
}
}

void PLC::extractSceneToProject(Project& proj)
{
proj.clear();
QList<Item*> items;
// (1) 先收集所有Item
for (QGraphicsItem* gi : plc_scene_->items()) {
if (Item* it = dynamic_cast<Item*>(gi)) {
items.append(it);
}
}
// (2) 存Item数据
for (Item* it : items) {
Project::ItemData d;
d.type = it->itemType();
d.x = it->pos().x();
d.y = it->pos().y();
proj.items_.append(d);
}
// (3) 存连线数据
for (QGraphicsItem* gi : plc_scene_->items()) {
if (Connection* conn = dynamic_cast<Connection*>(gi)) {
int fromIdx = items.indexOf(conn->from_);
int toIdx = items.indexOf(conn->to_);
if (fromIdx >= 0 && toIdx >= 0) {
Project::ConnectionData c;
c.from = fromIdx;
c.to = toIdx;
c.fromType = static_cast<int>(conn->fromType_);
c.toType = static_cast<int>(conn->toType_);
proj.connections_.append(c);
}
}
}
}

void PLC::onListwidgetCurrenttextchanged(const QString &text) void PLC::onListwidgetCurrenttextchanged(const QString &text)
{ {
selectedComponentType = text; selectedComponentType = text;


+ 6
- 1
plc.h 查看文件

@@ -3,6 +3,7 @@


#include <QGraphicsScene> #include <QGraphicsScene>
#include <QWidget> #include <QWidget>
#include "project.h"


namespace Ui { namespace Ui {
class PLC; class PLC;
@@ -17,6 +18,10 @@ public:
~PLC(); ~PLC();
void createComponents(); void createComponents();


void clearScene();
void applyProjectToScene(const Project& proj); // 加载工程到scene
void extractSceneToProject(Project& proj); // 从scene导出工程数据

protected: protected:
bool eventFilter(QObject *obj, QEvent *event) override; bool eventFilter(QObject *obj, QEvent *event) override;


@@ -26,7 +31,7 @@ private slots:


private: private:
Ui::PLC *ui; Ui::PLC *ui;
QGraphicsScene *m_scene;
QGraphicsScene *plc_scene_;
QString selectedComponentType; QString selectedComponentType;
}; };




+ 68
- 0
project.cpp 查看文件

@@ -0,0 +1,68 @@
#include "project.h"
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonArray>
#include <QFile>

bool Project::saveToFile(const QString& filePath) const {
QJsonObject root;
QJsonArray itemsArray;
for (const ItemData& item : items_) {
QJsonObject obj;
obj["type"] = item.type;
obj["x"] = item.x;
obj["y"] = item.y;
itemsArray.append(obj);
}
root["items"] = itemsArray;

QJsonArray connArray;
for (const ConnectionData& c : connections_) {
QJsonObject obj;
obj["from"] = c.from;
obj["to"] = c.to;
obj["fromType"] = c.fromType;
obj["toType"] = c.toType;
connArray.append(obj);
}
root["connections"] = connArray;

QFile file(filePath);
if (!file.open(QIODevice::WriteOnly))
return false;
file.write(QJsonDocument(root).toJson());
file.close();
return true;
}

bool Project::loadFromFile(const QString& filePath) {
clear();
QFile file(filePath);
if (!file.open(QIODevice::ReadOnly))
return false;
QJsonDocument doc = QJsonDocument::fromJson(file.readAll());
file.close();
if (doc.isNull()) return false;

QJsonObject root = doc.object();
QJsonArray itemsArray = root["items"].toArray();
for (const QJsonValue& v : itemsArray) {
QJsonObject obj = v.toObject();
ItemData d;
d.type = obj["type"].toString();
d.x = obj["x"].toDouble();
d.y = obj["y"].toDouble();
items_.append(d);
}
QJsonArray connArray = root["connections"].toArray();
for (const QJsonValue& v : connArray) {
QJsonObject obj = v.toObject();
ConnectionData d;
d.from = obj["from"].toInt();
d.to = obj["to"].toInt();
d.fromType = obj["fromType"].toInt();
d.toType = obj["toType"].toInt();
connections_.append(d);
}
return true;
}

+ 28
- 0
project.h 查看文件

@@ -0,0 +1,28 @@
#ifndef PROJECT_H
#define PROJECT_H

#include <QString>
#include <QList>

// PLC工程数据模型
class Project
{
public:
struct ItemData {
QString type;
double x, y;
};
struct ConnectionData {
int from, to;
int fromType, toType;
};

void clear() { items_.clear(); connections_.clear(); }
bool saveToFile(const QString& filePath) const;
bool loadFromFile(const QString& filePath);

QList<ItemData> items_;
QList<ConnectionData> connections_;
};

#endif // PROJECT_H

Loading…
取消
儲存