From deec2c2d635f945e013183535fbf6466e6d506c2 Mon Sep 17 00:00:00 2001 From: baiYue Date: Sat, 7 Dec 2024 17:24:36 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=9E=E7=8E=B0=E5=9B=BE=E5=85=83=E5=9F=BA?= =?UTF-8?q?=E7=A1=80=E8=BF=9E=E7=BA=BF=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CMakeLists.txt | 14 + include/designerView.h | 4 +- include/drawingPanel.h | 5 +- include/global.h | 9 +- include/graphicsDataModel/fixedPortsModel.h | 131 +++++ .../graphicsDataModel/triangleDelegateModel.h | 54 ++ .../graphicsItem/electricConnectLineItem.h | 80 +++ include/graphicsItem/electricSvgItemBus.h | 2 + include/graphicsItem/graphicsBaseItem.h | 191 ++++--- include/graphicsItem/itemControlHandle.h | 23 +- include/graphicsItem/itemPort.h | 31 + include/statusBar.h | 20 + include/util/baseSelector.h | 10 + include/util/connectingSelector.h | 7 +- include/util/movingSelector.h | 1 + include/util/selectorManager.h | 2 +- source/designerScene.cpp | 1 - source/designerView.cpp | 9 + source/drawingPanel.cpp | 6 +- .../NumberDisplayDataModel.cpp | 71 +++ source/graphicsDataModel/fixedPortsModel.cpp | 530 ++++++++++++++++++ .../graphicsItem/electricConnectLineItem.cpp | 57 ++ source/graphicsItem/electricSvgItem.cpp | 7 +- source/graphicsItem/electricSvgItemBus.cpp | 5 + source/graphicsItem/electricSvgItemRect.cpp | 14 +- .../graphicsItem/electricSvgItemTriangle.cpp | 24 +- source/graphicsItem/graphicsBaseItem.cpp | 49 ++ source/graphicsItem/itemControlHandle.cpp | 4 +- source/graphicsItem/itemPort.cpp | 77 +++ source/statusBar.cpp | 21 + source/util/baseSelector.cpp | 5 +- source/util/connectingSelector.cpp | 159 +++++- source/util/creatingSelector.cpp | 15 +- source/util/movingSelector.cpp | 29 + source/util/selectorManager.cpp | 8 + 35 files changed, 1545 insertions(+), 130 deletions(-) create mode 100644 include/graphicsDataModel/fixedPortsModel.h create mode 100644 include/graphicsDataModel/triangleDelegateModel.h create mode 100644 include/graphicsItem/electricConnectLineItem.h create mode 100644 include/graphicsItem/itemPort.h create mode 100644 include/statusBar.h create mode 100644 source/graphicsDataModel/NumberDisplayDataModel.cpp create mode 100644 source/graphicsDataModel/fixedPortsModel.cpp create mode 100644 source/graphicsItem/electricConnectLineItem.cpp create mode 100644 source/graphicsItem/itemPort.cpp create mode 100644 source/statusBar.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 4eb6fe7..dcf230d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -48,6 +48,7 @@ set(H_HEADER_FILES include/operationCommand.h include/toolPage.h include/toolBox.h + include/statusBar.h include/util/baseSelector.h include/util/creatingSelector.h @@ -58,7 +59,10 @@ set(H_HEADER_FILES include/util/connectingSelector.h include/util/selectorManager.h + include/graphicsDataModel/fixedPortsModel.h + include/graphicsItem/itemControlHandle.h + include/graphicsItem/itemPort.h include/graphicsItem/graphicsBaseItem.h include/graphicsItem/graphicsRectItem.h include/graphicsItem/graphicsPolygonItem.h @@ -67,6 +71,8 @@ set(H_HEADER_FILES include/graphicsItem/electricSvgItemBus.h include/graphicsItem/electricSvgItemRect.h include/graphicsItem/electricSvgItemTriangle.h + include/graphicsItem/electricConnectLineItem.h + include/abstractGraphModel.h include/connectionIdUtils.h include/serializable.h @@ -108,6 +114,7 @@ set(CPP_SOURCE_FILES source/operationCommand.cpp source/toolPage.cpp source/toolBox.cpp + source/statusBar.cpp source/util/baseSelector.cpp source/util/creatingSelector.cpp @@ -118,7 +125,10 @@ set(CPP_SOURCE_FILES source/util/connectingSelector.cpp source/util/selectorManager.cpp + source/graphicsDataModel/fixedPortsModel.cpp + source/graphicsItem/itemControlHandle.cpp + source/graphicsItem/itemPort.cpp source/graphicsItem/graphicsBaseItem.cpp source/graphicsItem/graphicsRectItem.cpp source/graphicsItem/graphicsPolygonItem.cpp @@ -127,6 +137,8 @@ set(CPP_SOURCE_FILES source/graphicsItem/electricSvgItemBus.cpp source/graphicsItem/electricSvgItemRect.cpp source/graphicsItem/electricSvgItemTriangle.cpp + source/graphicsItem/electricConnectLineItem.cpp + source/abstractGraphModel.cpp source/dataFlowGraphModel.cpp source/nodeDelegateModel.cpp @@ -164,6 +176,8 @@ if(${QT_VERSION_MAJOR} GREATER_EQUAL 6) ${CPP_SOURCE_FILES} ${UI_FILES} resource/DiagramDesigner.qrc + include/graphicsDataModel/fixedPortsModel.h + source/graphicsDataModel/fixedPortsModel.cpp ) else() if(ANDROID) diff --git a/include/designerView.h b/include/designerView.h index 4f124a0..27d359d 100644 --- a/include/designerView.h +++ b/include/designerView.h @@ -30,11 +30,13 @@ private: bool zoomLimit(double&); double getScaleFactor(); void translate(const QPointF&); - +signals: + void onScaleChanged(double d); private: bool m_bMousePress; double m_dScale; QPointF m_ptLatstMouse_view; //鼠标最后按下在view中的位置 + int m_nLevel; }; #endif diff --git a/include/drawingPanel.h b/include/drawingPanel.h index 8097630..9ced31c 100644 --- a/include/drawingPanel.h +++ b/include/drawingPanel.h @@ -13,8 +13,7 @@ class DesignerView; class DesignerScene; class SelectorManager; class GraphicsItemGroup; -//class NodeDelegateModelRegistry; - +class StatusBar; class DrawingPanel : public QWidget { @@ -45,7 +44,7 @@ private: DesignerView* m_pGraphicsView; DesignerScene* m_pGraphicsScene; SelectorManager* m_pSelectorManager; - + StatusBar* m_pStatusBar; }; #endif diff --git a/include/global.h b/include/global.h index 0928643..ea69cc9 100644 --- a/include/global.h +++ b/include/global.h @@ -21,7 +21,8 @@ enum GraphicsItemType //====================================== GIT_bus = QGraphicsItem::UserType + 50, GIT_itemRect = QGraphicsItem::UserType + 51, - GIT_itemTri = QGraphicsItem::UserType + 52 + GIT_itemTri = QGraphicsItem::UserType + 52, + GIT_connectLine = QGraphicsItem::UserType + 53 }; //Q_ENUM_NS(GraphicsItemType) @@ -87,6 +88,12 @@ enum class PortType { }; //Q_ENUM_NS(PortType) +enum PortState +{ + P_const = 0, //固定端口 + p_movable, //移动端口 +}; + using PortCount = int; /// ports are consecutively numbered starting from zero. diff --git a/include/graphicsDataModel/fixedPortsModel.h b/include/graphicsDataModel/fixedPortsModel.h new file mode 100644 index 0000000..65ae02c --- /dev/null +++ b/include/graphicsDataModel/fixedPortsModel.h @@ -0,0 +1,131 @@ +#pragma once + +#include "abstractGraphModel.h" +#include "connectionIdUtils.h" +#include "nodeDelegateModelRegistry.h" +#include "serializable.h" +#include "styleCollection.h" + +#include +#include + + +class FixedPortsModel : public AbstractGraphModel, public Serializable +{ + Q_OBJECT + +public: + struct NodeGeometryData + { + QSize size; + QPointF pos; + }; + +public: + FixedPortsModel(QSharedPointer registry); + + QSharedPointer dataModelRegistry() { return _registry; } + +public: + QSet allNodeIds() const override; + + QSet allConnectionIds(NodeId const nodeId) const override; + + QSet connections(NodeId nodeId, + PortType portType, + PortIndex portIndex) const override; + + bool connectionExists(ConnectionId const connectionId) const override; + + NodeId addNode(QString const nodeType) override; + + bool connectionPossible(ConnectionId const connectionId) const override; + + void addConnection(ConnectionId const connectionId) override; + + bool nodeExists(NodeId const nodeId) const override; + + QVariant nodeData(NodeId nodeId, NodeRole role) const override; + + NodeFlags nodeFlags(NodeId nodeId) const override; + + bool setNodeData(NodeId nodeId, NodeRole role, QVariant value) override; + + QVariant portData(NodeId nodeId, + PortType portType, + PortIndex portIndex, + PortRole role) const override; + + bool setPortData(NodeId nodeId, + PortType portType, + PortIndex portIndex, + QVariant const &value, + PortRole role = PortRole::Data) override; + + bool deleteConnection(ConnectionId const connectionId) override; + + bool deleteNode(NodeId const nodeId) override; + + QJsonObject saveNode(NodeId const) const override; + + QJsonObject save() const override; + + void loadNode(QJsonObject const &nodeJson) override; + + void load(QJsonObject const &json) override; + + /** + * Fetches the NodeDelegateModel for the given `nodeId` and tries to cast the + * stored pointer to the given type + */ + template + NodeDelegateModelType *delegateModel(NodeId const nodeId) + { + auto it = _models.find(nodeId); + if (it == _models.end()) + return nullptr; + + //auto model = dynamic_cast(it->second.get()); + auto model = dynamic_cast(*it); + + return model; + } + +Q_SIGNALS: + void inPortDataWasSet(NodeId const, PortType const, PortIndex const); + +private: + NodeId newNodeId() override { return _nextNodeId++; } + + void sendConnectionCreation(ConnectionId const connectionId); + + void sendConnectionDeletion(ConnectionId const connectionId); + +private Q_SLOTS: + /** + * Fuction is called in three cases: + * + * - By underlying NodeDelegateModel when a node has new data to propagate. + * @see DataFlowGraphModel::addNode + * - When a new connection is created. + * @see DataFlowGraphModel::addConnection + * - When a node restored from JSON an needs to send data downstream. + * @see DataFlowGraphModel::loadNode + */ + void onOutPortDataUpdated(NodeId const nodeId, PortIndex const portIndex); + + /// Function is called after detaching a connection. + void propagateEmptyDataTo(NodeId const nodeId, PortIndex const portIndex); + +private: + QSharedPointer _registry; + + NodeId _nextNodeId; + + QMap> _models; + + QSet _connectivity; + + mutable QMap _nodeGeometryData; +}; + diff --git a/include/graphicsDataModel/triangleDelegateModel.h b/include/graphicsDataModel/triangleDelegateModel.h new file mode 100644 index 0000000..78f984f --- /dev/null +++ b/include/graphicsDataModel/triangleDelegateModel.h @@ -0,0 +1,54 @@ +#pragma once + +#include + +#include + +#include + +#include "DecimalData.hpp" + +using QtNodes::NodeData; +using QtNodes::NodeDataType; +using QtNodes::NodeDelegateModel; +using QtNodes::PortIndex; +using QtNodes::PortType; + +class QLabel; + +/// The model dictates the number of inputs and outputs for the Node. +/// In this example it has no logic. +class NumberDisplayDataModel : public NodeDelegateModel +{ + Q_OBJECT + +public: + NumberDisplayDataModel(); + + ~NumberDisplayDataModel() = default; + +public: + QString caption() const override { return QStringLiteral("Result"); } + + bool captionVisible() const override { return false; } + + QString name() const override { return QStringLiteral("Result"); } + +public: + unsigned int nPorts(PortType portType) const override; + + NodeDataType dataType(PortType portType, PortIndex portIndex) const override; + + std::shared_ptr outData(PortIndex port) override; + + void setInData(std::shared_ptr data, PortIndex portIndex) override; + + QWidget *embeddedWidget() override; + + double number() const; + +private: + std::shared_ptr _numberData; + + QLabel *_label; +}; diff --git a/include/graphicsItem/electricConnectLineItem.h b/include/graphicsItem/electricConnectLineItem.h new file mode 100644 index 0000000..ba61ac5 --- /dev/null +++ b/include/graphicsItem/electricConnectLineItem.h @@ -0,0 +1,80 @@ +#ifndef ELECTRICCONNECTLINEITEM_H +#define ELECTRICCONNECTLINEITEM_H + +#include +#include "graphicsBaseItem.h" + +struct Connection +{ + int nSrcNodeId; + int nSrcPort; + HandleType srcType; + int nDestNodeId; + int nDestPort; + HandleType destType; + + Connection() + { + + nSrcNodeId = -1; + nSrcPort = -1; + srcType = T_none; + nDestNodeId = -1; + nDestPort = -1; + destType = T_none; + } + + Connection(int nSNI,int nSP,HandleType sT,int nDNI,int nDP,HandleType dT) + { + nSrcNodeId = nSNI; + nSrcPort = nSP; + srcType = sT; + nDestNodeId = nDNI; + nDestPort = nDP; + destType = dT; + } + bool operator==(Connection& obj) + { + return ((obj.nSrcNodeId == nSrcNodeId)&&(obj.nSrcPort == nSrcPort)&&(obj.srcType == srcType)&&(obj.nDestNodeId == nDestNodeId)&&(obj.nDestPort == nDestPort)&&(obj.destType == destType)); + } + + Connection& operator=(Connection& obj) + { + if(*this == obj) + return *this; + nSrcNodeId = obj.nSrcNodeId; + nSrcPort = obj.nSrcPort; + srcType = obj.srcType; + nDestNodeId = obj.nDestNodeId; + nDestPort = obj.nDestPort; + destType = obj.destType; + return *this; + } +}; + +class ElectricConnectLineItem : public GraphicsBaseItem +{ +public: + ElectricConnectLineItem(QGraphicsItem *parent = 0); + virtual ~ElectricConnectLineItem(); + + void setStartPoint(const QPointF& p){m_pStart = p;} + void setEndPoint(const QPointF& p){m_pEnd = p;} + QPainterPath getPoints(void) const { return m_points; } + + void calculatePath(); + bool addConnection(); + + void updateConnection(int callerId,QPointF pos); //外部调用的更新函数,id为调用者id + void setConnection(Connection con){m_connectState = con;} +protected: + virtual QPainterPath shape(); + virtual void paint(QPainter*, const QStyleOptionGraphicsItem*, QWidget*); +private: + Connection m_connectState; + QPainterPath m_points; + QPointF m_pStart; + QPointF m_pEnd; +}; + +#endif diff --git a/include/graphicsItem/electricSvgItemBus.h b/include/graphicsItem/electricSvgItemBus.h index f00bf31..8052f77 100644 --- a/include/graphicsItem/electricSvgItemBus.h +++ b/include/graphicsItem/electricSvgItemBus.h @@ -9,6 +9,8 @@ class ElectricSvgItemBus :public ElectricSvgItem public: ElectricSvgItemBus(const QRect &rect, QGraphicsItem *parent = 0); virtual ~ElectricSvgItemBus(); + + void addPort(); protected: virtual void paint(QPainter*, const QStyleOptionGraphicsItem*, QWidget*); private: diff --git a/include/graphicsItem/graphicsBaseItem.h b/include/graphicsItem/graphicsBaseItem.h index 2f61ae2..51a7ba2 100644 --- a/include/graphicsItem/graphicsBaseItem.h +++ b/include/graphicsItem/graphicsBaseItem.h @@ -2,6 +2,7 @@ #define GRAPHICSBASEITEM_H #include "itemControlHandle.h" +#include "global.h" #include #include @@ -20,10 +21,10 @@ enum ShapeType enum ItemState { S_normal = 0, - S_lineOut, - s_lineIn + S_prepareConnect, }; + //基类采用模板形式,QGraphicsItem是默认值,也可以是别的类型,比如QGraphicsItemGroup,这样不同的基类继承可以共用一些高层的行为定义 template class AbstractShapeType : public BaseType @@ -38,6 +39,7 @@ public: m_dWidth = m_dHeight = 0; m_pOperationCopy = nullptr; m_dSyncRotationByParent = 0.0; + m_touched = false; } virtual ~AbstractShapeType() @@ -105,7 +107,10 @@ public: { QPointF pt = pHandle->mapFromScene(point); if(pHandle->contains(pt)) - return pHandle->getTag(); + { + if(pHandle->enable()) + return pHandle->getTag(); + } } } return HandleTag::H_none; @@ -166,10 +171,72 @@ public: ItemControlHandle* pHandle = m_vecHanle.value(key); if(pHandle) { - if(bVisible) - pHandle->show(); - else - pHandle->hide(); + if(pHandle->ifShow()) + { + if(bVisible) + pHandle->show(); + else + pHandle->hide(); + } + } + } + } + virtual void setHandleVisible(int tag,bool bVisible) + { + foreach (int key, m_vecHanle.keys()) + { + ItemControlHandle* pHandle = m_vecHanle.value(key); + if(pHandle) + { + if(pHandle->getTag() == tag) + { + if(bVisible) + pHandle->show(); + else + pHandle->hide(); + break; + } + } + } + } + virtual void setFunctionHandleIfShow(bool bVisible) //是否参与显示判断 + { + foreach (int key, m_vecHanle.keys()) + { + ItemControlHandle* pHandle = m_vecHanle.value(key); + if(pHandle) + { + if(pHandle->getTag() < H_connect) + { + pHandle->setIfShow(bVisible); + } + } + } + } + virtual void setFunctionHandleEnaable(bool val) + { + foreach (int key, m_vecHanle.keys()) + { + ItemControlHandle* pHandle = m_vecHanle.value(key); + if(pHandle) + { + if(pHandle->getTag() < H_connect) //设置port以外端点是否交互 + pHandle->setEnable(val); + } + } + } + virtual void setHandleEnaable(HandleTag tag,bool val) + { + foreach (int key, m_vecHanle.keys()) + { + ItemControlHandle* pHandle = m_vecHanle.value(key); + if(pHandle) + { + if(pHandle->getTag() == tag) //设置端点是否交互 + { + pHandle->setEnable(val); + break; + } } } } @@ -221,93 +288,6 @@ public: { int nMargin = 5; const QRectF& boundRect = this->boundingRect(); - /*for(auto it = m_vecHanle.begin(); it != m_vecHanle.end(); it++) - { - switch ((*it)->getTag()) { - case H_leftTop: - (*it)->move(boundRect.x() - nMargin, boundRect.y() - nMargin); - break; - case H_top: - (*it)->move(boundRect.x() + boundRect.width() * 0.5, boundRect.y() - nMargin); - break; - case H_rightTop: - (*it)->move(boundRect.x() + boundRect.width() + nMargin, boundRect.y() - nMargin); - break; - case H_right: - (*it)->move(boundRect.x() + boundRect.width() + nMargin, boundRect.y() + boundRect.height() * 0.5 + nMargin); - break; - case H_rightBottom: - (*it)->move(boundRect.x() + boundRect.width() + nMargin, boundRect.y() + boundRect.height() + nMargin); - break; - case H_bottom: - (*it)->move(boundRect.x() + boundRect.width() * 0.5, boundRect.y() + boundRect.height()+ nMargin); - break; - case H_leftBottom: - (*it)->move(boundRect.x() - nMargin, boundRect.y() + boundRect.height() + nMargin); - break; - case H_left: - (*it)->move(boundRect.x() - nMargin, boundRect.y() + boundRect.height() * 0.5); - break; - case H_rotate_leftTop: - { - ItemControlHandle* handle = getHandle(H_leftTop); - if(handle) - { - int nSize = handle->getSize(); - QPointF pt = handle->pos(); - (*it)->move(pt.x() - nSize - 1, pt.y() - nSize - 1); - } - else - (*it)->setVisible(false); - - break; - } - case H_rotate_rightTop: - { - ItemControlHandle* handle = getHandle(H_rightTop); - if(handle) - { - int nSize = handle->getSize(); - QPointF pt = handle->pos(); - (*it)->move(pt.x() + nSize + 1, pt.y() - nSize - 1); - } - else - (*it)->setVisible(false); - - break; - } - case H_rotate_rightBottom: - { - ItemControlHandle* handle = getHandle(H_rightBottom); - if(handle) - { - int nSize = handle->getSize(); - QPointF pt = handle->pos(); - (*it)->move(pt.x() + nSize + 1, pt.y() + nSize + 1); - } - else - (*it)->setVisible(false); - - break; - } - case H_rotate_leftBottom: - { - ItemControlHandle* handle = getHandle(H_leftBottom); - if(handle) - { - int nSize = handle->getSize(); - QPointF pt = handle->pos(); - (*it)->move(pt.x() - nSize - 1, pt.y() + nSize + 1); - } - else - (*it)->setVisible(false); - - break; - } - default: - break; - } - }*/ foreach (int key, m_vecHanle.keys()) { @@ -417,7 +397,7 @@ public: virtual void syncRotationDataFromParent(const double&) {} virtual double getSyncRotationDataFromParent() {return m_dSyncRotationByParent;} - + virtual void setTouched(bool b){m_touched = b;} protected: ShapeType m_type; QPen m_pen; @@ -426,6 +406,7 @@ protected: double m_dHeight; QRectF m_boundingRect; QRectF m_boundingRect_selected; //选中矩形框 + bool m_touched; //被触碰状态 double m_dSyncRotationByParent; //父项(被加入到某一组)的旋转数据,因为加入某一组后,对该组进行旋转,自身的旋转数据不会同步更新 @@ -436,6 +417,8 @@ protected: QMap m_vecHanle; }; +class ItemPort; + typedef AbstractShapeType AbstractShape; class GraphicsBaseItem : public QObject, public AbstractShapeType @@ -454,18 +437,34 @@ public: //多边形、线段等点选创建的对象需要的函数 virtual void addPoint(const QPointF&) {} virtual bool endDrawing() { return true; } + + + virtual int addPort(PortState typ,QPointF vec); //新建,返回-1失败 + virtual void addPort(PortState typ,int ntagId,QPointF vec); //载入 PortState为P_const时,QPointF中为(0~1,0~1)的相对位置;PortState为p_movable时,QPointF为坐标值 + virtual uint itemId() const {return m_itemId;} + virtual void setItemId(uint n){m_itemId = n;} virtual void setState(ItemState s){m_state = s;} virtual void setBeginConnectPos(QPointF p){m_beginConnectPoint = p;} virtual void setEndConnectPos(QPointF p){m_endConnectPoint = p;} + virtual void setItemType(GraphicsItemType type){m_Itemtype = type;} + virtual GraphicsItemType getItemType() const {return m_Itemtype;} + virtual void setLastPort(int n){_lastPort = n;} + virtual int getLastPort() const {return _lastPort;} + virtual ItemPort* getPortPtr(int) const; + virtual QMap& getPorts() {return m_mapPort;} protected: virtual QVariant itemChange(QGraphicsItem::GraphicsItemChange, const QVariant&); virtual void contextMenuEvent(QGraphicsSceneContextMenuEvent*); protected: - + uint m_itemId; + GraphicsItemType m_Itemtype; ItemState m_state; + QMap m_mapPort; //单独存放port QPointF m_beginConnectPoint; QPointF m_endConnectPoint; + uint _portId; //port编号 + int _lastPort; //最后触碰的port }; #endif diff --git a/include/graphicsItem/itemControlHandle.h b/include/graphicsItem/itemControlHandle.h index 1cadd4a..aaf5be8 100644 --- a/include/graphicsItem/itemControlHandle.h +++ b/include/graphicsItem/itemControlHandle.h @@ -5,11 +5,13 @@ enum HandleType { + T_none = 0, T_resize, //调整大小 T_rotate, //旋转 T_editShape, //编辑形状 T_lineIn, //入线口 - T_lineOut //出线口 + T_lineOut, //出线口 + T_lineInOut //双端线 }; enum HandleTag @@ -31,6 +33,15 @@ enum HandleTag H_connect = 50 //连接操作点从50开始,前面预留 }; +enum PortPos +{ + P_top = 0, + P_down, + P_left, + P_right +}; + +const int HNDLE_SIZE = 8; class ItemControlHandle : public QObject,public QGraphicsRectItem { @@ -50,15 +61,21 @@ public: int getSize(); void move(double, double); + void setEnable(bool b){m_enable = b;} + bool enable(){return m_enable;} + + void setIfShow(bool b){m_ifShow = b;} + bool ifShow(){return m_ifShow;} protected: virtual void hoverEnterEvent(QGraphicsSceneHoverEvent*) override; virtual void hoverLeaveEvent(QGraphicsSceneHoverEvent*) override; virtual void paint(QPainter*, const QStyleOptionGraphicsItem*, QWidget*) override; -private: +protected: HandleType m_type; int m_tag; - + bool m_enable; + bool m_ifShow; }; #endif diff --git a/include/graphicsItem/itemPort.h b/include/graphicsItem/itemPort.h new file mode 100644 index 0000000..dfd9a66 --- /dev/null +++ b/include/graphicsItem/itemPort.h @@ -0,0 +1,31 @@ +#ifndef ITEMPORT_H +#define ITEMPORT_H + +#include "graphicsItem/itemControlHandle.h" + +class ElectricConnectLineItem; + +class ItemPort : public ItemControlHandle +{ + Q_OBJECT + +public: + ItemPort(QGraphicsItem *parent); + virtual ~ItemPort(); + +public: + void setPortPos(PortPos p){_pos = p;} + PortPos portPos() const {return _pos;} + void setConnect(ElectricConnectLineItem* ptr){_ptr = ptr;} + void disConnect(){_ptr = nullptr;} + bool connected() const {return _ptr == nullptr?false:true;} + ElectricConnectLineItem* getConnectPtr() const {return _ptr;} +protected: + virtual void paint(QPainter*, const QStyleOptionGraphicsItem*, QWidget*) override; + +private: + PortPos _pos; + ElectricConnectLineItem* _ptr; +}; + +#endif diff --git a/include/statusBar.h b/include/statusBar.h new file mode 100644 index 0000000..a9ab80f --- /dev/null +++ b/include/statusBar.h @@ -0,0 +1,20 @@ +#ifndef STATUSBAR_H +#define STATUSBAR_H + +#include + +class QLabel; + +class StatusBar : public QStatusBar +{ + Q_OBJECT + +public: + explicit StatusBar(QWidget *parent = nullptr); + ~StatusBar(); +public slots: + void onScaleLevelChanged(double f); +private: + QLabel *m_pScaleLevel; +}; +#endif // STATUSBAR_H diff --git a/include/util/baseSelector.h b/include/util/baseSelector.h index 8179601..47237eb 100644 --- a/include/util/baseSelector.h +++ b/include/util/baseSelector.h @@ -34,6 +34,10 @@ enum OperationMode OM_connect, //连接 }; +class GraphicsBaseItem; + +using ItemMap = QMap>; + class BaseSelector : public QObject { Q_OBJECT @@ -53,7 +57,11 @@ public: OperationMode getOperationMode() { return ms_opMode; } void setCursor(DesignerScene*, const QCursor&); + void setSceneName(const QString& str) {m_sceneName = str;} + QString sceneName() const {return m_sceneName;} +public: + static ItemMap m_graphicsItem; //存储所有对象 类型 <图名> signals: void setWorkingSelector(SelectorType); @@ -64,8 +72,10 @@ protected: static QPointF ms_ptMouseLast; static double ms_dAngleMouseDownToItem; //鼠标按下时其位置和item中心点形成的夹角 static int ms_nDragHandle; //当前抓取的控制点 + static uint _Id; SelectorType m_type; + QString m_sceneName; private: bool m_bHoverOnHandel; //鼠标是否悬停在handel OperationMode m_opMode; diff --git a/include/util/connectingSelector.h b/include/util/connectingSelector.h index 355ea06..ea2b609 100644 --- a/include/util/connectingSelector.h +++ b/include/util/connectingSelector.h @@ -21,13 +21,18 @@ class ConnectingSelector : public BaseSelector public: explicit ConnectingSelector(QObject *parent = 0); virtual ~ConnectingSelector(); - +public: + bool targetCouldConnect(GraphicsBaseItem* p,QPointF pos); + void setTargetHighLight(bool val); //设置目标高亮 + void createConnectLline(GraphicsBaseItem* connecting,GraphicsBaseItem* touched,DesignerScene* scene); public: void mousePressEvent(QGraphicsSceneMouseEvent*, DesignerScene*); void mouseMoveEvent(QGraphicsSceneMouseEvent*, DesignerScene*); void mouseReleaseEvent(QGraphicsSceneMouseEvent*, DesignerScene*); private: GraphicsBaseItem* m_pConnectingItem; + GraphicsBaseItem* m_pTouchedItem; //连线时接触的对象 + bool m_bReadyConnect; //准备连接 }; #endif diff --git a/include/util/movingSelector.h b/include/util/movingSelector.h index 93aefe8..20f87f1 100644 --- a/include/util/movingSelector.h +++ b/include/util/movingSelector.h @@ -19,6 +19,7 @@ public: explicit MovingSelector(QObject *parent = 0); virtual ~MovingSelector(); + void updateConnectLine(QList); public: void mousePressEvent(QGraphicsSceneMouseEvent*, DesignerScene*); void mouseMoveEvent(QGraphicsSceneMouseEvent*, DesignerScene*); diff --git a/include/util/selectorManager.h b/include/util/selectorManager.h index 4e43a57..845c583 100644 --- a/include/util/selectorManager.h +++ b/include/util/selectorManager.h @@ -27,7 +27,7 @@ public: BaseSelector* getWorkingSelector(); //根据操作方式获取selector void setDrawGraphicsItem(GraphicsItemType); - + void setName(const QString&); public slots: void onSignal_setWorkingSelector(SelectorType); diff --git a/source/designerScene.cpp b/source/designerScene.cpp index 21cc664..ecba920 100644 --- a/source/designerScene.cpp +++ b/source/designerScene.cpp @@ -30,7 +30,6 @@ DesignerScene::DesignerScene(DataFlowGraphModel &graphModel, QObject *parent) m_bGridVisible = true; m_pView = nullptr; m_pDrawingPanel = dynamic_cast(parent); - connect(&_graphModel, &DataFlowGraphModel::inPortDataWasSet, [this](NodeId const nodeId, PortType const, PortIndex const) { onNodeUpdated(nodeId); }); diff --git a/source/designerView.cpp b/source/designerView.cpp index 7b4d97d..b654767 100644 --- a/source/designerView.cpp +++ b/source/designerView.cpp @@ -10,6 +10,7 @@ DesignerView::DesignerView(QWidget *parent) m_bMousePress = false; m_dScale = 1.0; initialize(); + m_nLevel = 10; } DesignerView::~DesignerView() { @@ -80,6 +81,7 @@ void DesignerView::wheelEvent(QWheelEvent* event) //滚轮进行放大缩小 QPointF mousePos = event->position(); double angleDeltaY = event->angleDelta().y(); double zoomFactor = qPow(1.0015, angleDeltaY); //可以实现更平滑的缩放 + zoom(mousePos, zoomFactor); //注意不要调用基类的滚轮函数,否则滚轮事件会映射到滚动条操作 @@ -109,6 +111,12 @@ bool DesignerView::zoomLimit(double& value) if(qFabs(value - 1) < 0.01) //缩放因子近似为1 return true; + if(value > 1) + m_nLevel +=1; + else + m_nLevel -=1; + + emit onScaleChanged(m_nLevel); return false; } @@ -130,6 +138,7 @@ void DesignerView::zoom(const QPointF& mousePos, double zoomFactor) trans.translate(-targetScenePos.x(), -targetScenePos.y()); setTransform(trans); setTransformationAnchor(lastAnchor); + //emit onScaleChanged(m_nLevel); } void DesignerView::zoomIn() diff --git a/source/drawingPanel.cpp b/source/drawingPanel.cpp index eab82cf..c2ae7e6 100644 --- a/source/drawingPanel.cpp +++ b/source/drawingPanel.cpp @@ -4,7 +4,7 @@ #include "dataFlowGraphModel.h" #include "nodeDelegateModelRegistry.h" #include "util/selectorManager.h" - +#include "statusBar.h" DrawingPanel::DrawingPanel(QWidget *parent) : QWidget(parent) @@ -26,7 +26,9 @@ DrawingPanel::DrawingPanel(QWidget *parent) m_pGraphicsScene->setView(m_pGraphicsView); ui->mainLayout->addWidget(m_pGraphicsView); - + m_pStatusBar = new StatusBar(this); + ui->mainLayout->addWidget(m_pStatusBar); + connect(m_pGraphicsView,&DesignerView::onScaleChanged,m_pStatusBar,&StatusBar::onScaleLevelChanged); } DrawingPanel::~DrawingPanel() diff --git a/source/graphicsDataModel/NumberDisplayDataModel.cpp b/source/graphicsDataModel/NumberDisplayDataModel.cpp new file mode 100644 index 0000000..5086050 --- /dev/null +++ b/source/graphicsDataModel/NumberDisplayDataModel.cpp @@ -0,0 +1,71 @@ +#include "NumberDisplayDataModel.hpp" + +#include + +NumberDisplayDataModel::NumberDisplayDataModel() + : _label{nullptr} +{} + +unsigned int NumberDisplayDataModel::nPorts(PortType portType) const +{ + unsigned int result = 1; + + switch (portType) { + case PortType::In: + result = 1; + break; + + case PortType::Out: + result = 0; + + default: + break; + } + + return result; +} + +NodeDataType NumberDisplayDataModel::dataType(PortType, PortIndex) const +{ + return DecimalData().type(); +} + +std::shared_ptr NumberDisplayDataModel::outData(PortIndex) +{ + std::shared_ptr ptr; + return ptr; +} + +void NumberDisplayDataModel::setInData(std::shared_ptr data, PortIndex portIndex) +{ + _numberData = std::dynamic_pointer_cast(data); + + if (!_label) + return; + + if (_numberData) { + _label->setText(_numberData->numberAsText()); + } else { + _label->clear(); + } + + _label->adjustSize(); +} + +QWidget *NumberDisplayDataModel::embeddedWidget() +{ + if (!_label) { + _label = new QLabel(); + _label->setMargin(3); + } + + return _label; +} + +double NumberDisplayDataModel::number() const +{ + if (_numberData) + return _numberData->number(); + + return 0.0; +} diff --git a/source/graphicsDataModel/fixedPortsModel.cpp b/source/graphicsDataModel/fixedPortsModel.cpp new file mode 100644 index 0000000..4248789 --- /dev/null +++ b/source/graphicsDataModel/fixedPortsModel.cpp @@ -0,0 +1,530 @@ +#include "graphicsDataModel/fixedPortsModel.h" + +#include + + +FixedPortsModel::FixedPortsModel(QSharedPointer registry) + : _registry(registry) + , _nextNodeId{0} +{} + +QSet FixedPortsModel::allNodeIds() const +{ + QSet nodeIds; + //for_each(_models.begin(), _models.end(), [&nodeIds](auto const &p) { nodeIds.insert(p.first); }); + + for(auto iter = _models.begin();iter != _models.end();++iter) + { + nodeIds.insert(iter.key()); + } + return nodeIds; +} + +QSet FixedPortsModel::allConnectionIds(NodeId const nodeId) const +{ + QSet result; + + std::copy_if(_connectivity.begin(), + _connectivity.end(), + std::inserter(result, std::end(result)), + [&nodeId](ConnectionId const &cid) { + return cid.inNodeId == nodeId || cid.outNodeId == nodeId; + }); + + return result; +} + +QSet FixedPortsModel::connections(NodeId nodeId, + PortType portType, + PortIndex portIndex) const +{ + QSet result; + + std::copy_if(_connectivity.begin(), + _connectivity.end(), + std::inserter(result, std::end(result)), + [&portType, &portIndex, &nodeId](ConnectionId const &cid) { + return (getNodeId(portType, cid) == nodeId + && getPortIndex(portType, cid) == portIndex); + }); + + return result; +} + +bool FixedPortsModel::connectionExists(ConnectionId const connectionId) const +{ + return (_connectivity.find(connectionId) != _connectivity.end()); +} + +NodeId FixedPortsModel::addNode(QString const nodeType) +{ + QSharedPointer model = _registry->create(nodeType); + + if (model) { + NodeId newId = newNodeId(); + + connect(model.get(), + &NodeDelegateModel::dataUpdated, + [newId, this](PortIndex const portIndex) { + onOutPortDataUpdated(newId, portIndex); + }); + + connect(model.get(), + &NodeDelegateModel::portsAboutToBeDeleted, + this, + [newId, this](PortType const portType, PortIndex const first, PortIndex const last) { + portsAboutToBeDeleted(newId, portType, first, last); + }); + + connect(model.get(), + &NodeDelegateModel::portsDeleted, + this, + &FixedPortsModel::portsDeleted); + + connect(model.get(), + &NodeDelegateModel::portsAboutToBeInserted, + this, + [newId, this](PortType const portType, PortIndex const first, PortIndex const last) { + portsAboutToBeInserted(newId, portType, first, last); + }); + + connect(model.get(), + &NodeDelegateModel::portsInserted, + this, + &FixedPortsModel::portsInserted); + + _models[newId] = model; + + Q_EMIT nodeCreated(newId); + + return newId; + } + + return InvalidNodeId; +} + +bool FixedPortsModel::connectionPossible(ConnectionId const connectionId) const +{ + auto getDataType = [&](PortType const portType) { + return portData(getNodeId(portType, connectionId), + portType, + getPortIndex(portType, connectionId), + PortRole::DataType) + .value(); + }; + + auto portVacant = [&](PortType const portType) { + NodeId const nodeId = getNodeId(portType, connectionId); + PortIndex const portIndex = getPortIndex(portType, connectionId); + auto const connected = connections(nodeId, portType, portIndex); + + auto policy = portData(nodeId, portType, portIndex, PortRole::ConnectionPolicyRole) + .value(); + + return connected.empty() || (policy == ConnectionPolicy::Many); + }; + + return getDataType(PortType::Out).id == getDataType(PortType::In).id + && portVacant(PortType::Out) && portVacant(PortType::In); +} + +void FixedPortsModel::addConnection(ConnectionId const connectionId) +{ + _connectivity.insert(connectionId); + + sendConnectionCreation(connectionId); + + QVariant const portDataToPropagate = portData(connectionId.outNodeId, + PortType::Out, + connectionId.outPortIndex, + PortRole::Data); + + setPortData(connectionId.inNodeId, + PortType::In, + connectionId.inPortIndex, + portDataToPropagate, + PortRole::Data); +} + +void FixedPortsModel::sendConnectionCreation(ConnectionId const connectionId) +{ + Q_EMIT connectionCreated(connectionId); + + auto iti = _models.find(connectionId.inNodeId); + auto ito = _models.find(connectionId.outNodeId); + if (iti != _models.end() && ito != _models.end()) { + auto &modeli = *iti; + auto &modelo = *ito; + modeli->inputConnectionCreated(connectionId); + modelo->outputConnectionCreated(connectionId); + } +} + +void FixedPortsModel::sendConnectionDeletion(ConnectionId const connectionId) +{ + Q_EMIT connectionDeleted(connectionId); + + auto iti = _models.find(connectionId.inNodeId); + auto ito = _models.find(connectionId.outNodeId); + if (iti != _models.end() && ito != _models.end()) { + auto &modeli = *iti; + auto &modelo = *ito; + modeli->inputConnectionDeleted(connectionId); + modelo->outputConnectionDeleted(connectionId); + } +} + +bool FixedPortsModel::nodeExists(NodeId const nodeId) const +{ + return (_models.find(nodeId) != _models.end()); +} + +QVariant FixedPortsModel::nodeData(NodeId nodeId, NodeRole role) const +{ + QVariant result; + + auto it = _models.find(nodeId); + if (it == _models.end()) + return result; + + auto &model = *it; + + switch (role) { + case NodeRole::Type: + result = model->name(); + break; + + case NodeRole::Position: + result = _nodeGeometryData[nodeId].pos; + break; + + case NodeRole::Size: + result = _nodeGeometryData[nodeId].size; + break; + + case NodeRole::CaptionVisible: + result = model->captionVisible(); + break; + + case NodeRole::Caption: + result = model->caption(); + break; + + case NodeRole::Style: { + auto style = StyleCollection::nodeStyle(); + result = style.toJson().toVariantMap(); + } break; + + case NodeRole::InternalData: { + QJsonObject nodeJson; + + nodeJson["internal-data"] = _models[nodeId]->save(); + + result = nodeJson.toVariantMap(); + break; + } + + case NodeRole::InPortCount: + result = model->nPorts(PortType::In); + break; + + case NodeRole::OutPortCount: + result = model->nPorts(PortType::Out); + break; + + case NodeRole::Widget: { + auto w = model->embeddedWidget(); + result = QVariant::fromValue(w); + } break; + } + + return result; +} + +NodeFlags FixedPortsModel::nodeFlags(NodeId nodeId) const +{ + auto it = _models.find(nodeId); + + if (it != _models.end() && it->data()->resizable()) + return NodeFlag::Resizable; + + return NodeFlag::NoFlags; +} + +bool FixedPortsModel::setNodeData(NodeId nodeId, NodeRole role, QVariant value) +{ + Q_UNUSED(nodeId); + Q_UNUSED(role); + Q_UNUSED(value); + + bool result = false; + + switch (role) { + case NodeRole::Type: + break; + case NodeRole::Position: { + _nodeGeometryData[nodeId].pos = value.value(); + + Q_EMIT nodePositionUpdated(nodeId); + + result = true; + } break; + + case NodeRole::Size: { + _nodeGeometryData[nodeId].size = value.value(); + result = true; + } break; + + case NodeRole::CaptionVisible: + break; + + case NodeRole::Caption: + break; + + case NodeRole::Style: + break; + + case NodeRole::InternalData: + break; + + case NodeRole::InPortCount: + break; + + case NodeRole::OutPortCount: + break; + + case NodeRole::Widget: + break; + } + + return result; +} + +QVariant FixedPortsModel::portData(NodeId nodeId, + PortType portType, + PortIndex portIndex, + PortRole role) const +{ + QVariant result; + + auto it = _models.find(nodeId); + if (it == _models.end()) + return result; + + auto &model = *it; + + switch (role) { + case PortRole::Data: + if (portType == PortType::Out) + result = QVariant::fromValue(model->outData(portIndex)); + break; + + case PortRole::DataType: + result = QVariant::fromValue(model->dataType(portType, portIndex)); + break; + + case PortRole::ConnectionPolicyRole: + result = QVariant::fromValue(model->portConnectionPolicy(portType, portIndex)); + break; + + case PortRole::CaptionVisible: + result = model->portCaptionVisible(portType, portIndex); + break; + + case PortRole::Caption: + result = model->portCaption(portType, portIndex); + + break; + } + + return result; +} + +bool FixedPortsModel::setPortData( + NodeId nodeId, PortType portType, PortIndex portIndex, QVariant const &value, PortRole role) +{ + Q_UNUSED(nodeId); + + QVariant result; + + auto it = _models.find(nodeId); + if (it == _models.end()) + return false; + + auto &model = *it; + + switch (role) { + case PortRole::Data: + if (portType == PortType::In) { + model->setInData(value.value>(), portIndex); + + // Triggers repainting on the scene. + Q_EMIT inPortDataWasSet(nodeId, portType, portIndex); + } + break; + + default: + break; + } + + return false; +} + +bool FixedPortsModel::deleteConnection(ConnectionId const connectionId) +{ + bool disconnected = false; + + auto it = _connectivity.find(connectionId); + + if (it != _connectivity.end()) { + disconnected = true; + + _connectivity.erase(it); + } + + if (disconnected) { + sendConnectionDeletion(connectionId); + + propagateEmptyDataTo(getNodeId(PortType::In, connectionId), + getPortIndex(PortType::In, connectionId)); + } + + return disconnected; +} + +bool FixedPortsModel::deleteNode(NodeId const nodeId) +{ + // Delete connections to this node first. + auto connectionIds = allConnectionIds(nodeId); + for (auto &cId : connectionIds) { + deleteConnection(cId); + } + + _nodeGeometryData.take(nodeId); + _models.take(nodeId); + + Q_EMIT nodeDeleted(nodeId); + + return true; +} + +QJsonObject FixedPortsModel::saveNode(NodeId const nodeId) const +{ + QJsonObject nodeJson; + + nodeJson["id"] = static_cast(nodeId); + + nodeJson["internal-data"] = _models[nodeId]->save(); + + { + QPointF const pos = nodeData(nodeId, NodeRole::Position).value(); + + QJsonObject posJson; + posJson["x"] = pos.x(); + posJson["y"] = pos.y(); + nodeJson["position"] = posJson; + } + + return nodeJson; +} + +QJsonObject FixedPortsModel::save() const +{ + QJsonObject sceneJson; + + QJsonArray nodesJsonArray; + for (auto const nodeId : allNodeIds()) { + nodesJsonArray.append(saveNode(nodeId)); + } + sceneJson["nodes"] = nodesJsonArray; + + QJsonArray connJsonArray; + for (auto const &cid : _connectivity) { + connJsonArray.append(toJson(cid)); + } + sceneJson["connections"] = connJsonArray; + + return sceneJson; +} + +void FixedPortsModel::loadNode(QJsonObject const &nodeJson) +{ + // Possibility of the id clash when reading it from json and not generating a + // new value. + // 1. When restoring a scene from a file. + // Conflict is not possible because the scene must be cleared by the time of + // loading. + // 2. When undoing the deletion command. Conflict is not possible + // because all the new ids were created past the removed nodes. + NodeId restoredNodeId = nodeJson["id"].toInt(); + + _nextNodeId = std::max(_nextNodeId, restoredNodeId + 1); + + QJsonObject const internalDataJson = nodeJson["internal-data"].toObject(); + + QString delegateModelName = internalDataJson["model-name"].toString(); + + QSharedPointer model = _registry->create(delegateModelName); + + if (model) { + connect(model.get(), + &NodeDelegateModel::dataUpdated, + [restoredNodeId, this](PortIndex const portIndex) { + onOutPortDataUpdated(restoredNodeId, portIndex); + }); + + _models[restoredNodeId] = std::move(model); + + Q_EMIT nodeCreated(restoredNodeId); + + QJsonObject posJson = nodeJson["position"].toObject(); + QPointF const pos(posJson["x"].toDouble(), posJson["y"].toDouble()); + + setNodeData(restoredNodeId, NodeRole::Position, pos); + + _models[restoredNodeId]->load(internalDataJson); + } else { + throw std::logic_error(std::string("No registered model with name ") + + delegateModelName.toLocal8Bit().data()); + } +} + +void FixedPortsModel::load(QJsonObject const &jsonDocument) +{ + QJsonArray nodesJsonArray = jsonDocument["nodes"].toArray(); + + for (QJsonValueRef nodeJson : nodesJsonArray) { + loadNode(nodeJson.toObject()); + } + + QJsonArray connectionJsonArray = jsonDocument["connections"].toArray(); + + for (QJsonValueRef connection : connectionJsonArray) { + QJsonObject connJson = connection.toObject(); + + ConnectionId connId = fromJson(connJson); + + // Restore the connection + addConnection(connId); + } +} + +void FixedPortsModel::onOutPortDataUpdated(NodeId const nodeId, PortIndex const portIndex) +{ + QSet const &connected = connections(nodeId, + PortType::Out, + portIndex); + + QVariant const portDataToPropagate = portData(nodeId, PortType::Out, portIndex, PortRole::Data); + + for (auto const &cn : connected) { + setPortData(cn.inNodeId, PortType::In, cn.inPortIndex, portDataToPropagate, PortRole::Data); + } +} + +void FixedPortsModel::propagateEmptyDataTo(NodeId const nodeId, PortIndex const portIndex) +{ + QVariant emptyData{}; + + setPortData(nodeId, PortType::In, portIndex, emptyData, PortRole::Data); +} diff --git a/source/graphicsItem/electricConnectLineItem.cpp b/source/graphicsItem/electricConnectLineItem.cpp new file mode 100644 index 0000000..d05acbc --- /dev/null +++ b/source/graphicsItem/electricConnectLineItem.cpp @@ -0,0 +1,57 @@ +#include "graphicsItem/electricConnectLineItem.h" +#include +#include + + +ElectricConnectLineItem::ElectricConnectLineItem(QGraphicsItem *parent) + : GraphicsBaseItem(parent) +{ + m_pen = QPen(Qt::black); + m_brush = QBrush(Qt::NoBrush); + setHandleVisible(false); + setFunctionHandleIfShow(false); + setFunctionHandleEnaable(false); +} + +ElectricConnectLineItem::~ElectricConnectLineItem() +{ +} + +QPainterPath ElectricConnectLineItem::shape() +{ + QPainterPath path; + path.addPath(m_points); + path.closeSubpath(); //将路径闭合 + return path; +} + +void ElectricConnectLineItem::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget) +{ + painter->setPen(m_pen); + painter->setBrush(m_brush); + + painter->drawPath(m_points); +} + + +void ElectricConnectLineItem::calculatePath() +{ + prepareGeometryChange(); + m_points.clear(); + + m_points.moveTo(m_pStart); + m_points.lineTo(m_pEnd.x(),m_pStart.y()); + m_points.lineTo(m_pEnd); +} + +void ElectricConnectLineItem::updateConnection(int callerId,QPointF pos) +{ + qDebug()<setPen(m_pen); painter->setBrush(m_brush); - if(m_state == S_lineOut) + if(m_state == S_prepareConnect) { painter->setPen(QPen(QColor(255,51,153,180))); painter->drawLine(m_beginConnectPoint,m_endConnectPoint); } + if(m_touched) + { + painter->setPen(QPen(QColor(238,58,140,220))); + painter->drawRect(m_boundingRect); + } if (option->state & QStyle::State_Selected) //是选中状态,绘制选中框 { diff --git a/source/graphicsItem/electricSvgItemBus.cpp b/source/graphicsItem/electricSvgItemBus.cpp index ceab1c7..0a5557c 100644 --- a/source/graphicsItem/electricSvgItemBus.cpp +++ b/source/graphicsItem/electricSvgItemBus.cpp @@ -8,6 +8,11 @@ ElectricSvgItemBus::ElectricSvgItemBus(const QRect &rect, QGraphicsItem *parent) : ElectricSvgItem(rect,parent) { loadSvg(":/images/element/svg_bus.svg"); + setHandleVisible(false); + setFunctionHandleIfShow(false); + setFunctionHandleEnaable(false); + setHandleEnaable(H_right,true); + setHandleEnaable(H_left,true); } ElectricSvgItemBus::~ElectricSvgItemBus() diff --git a/source/graphicsItem/electricSvgItemRect.cpp b/source/graphicsItem/electricSvgItemRect.cpp index 4417bec..2a18a26 100644 --- a/source/graphicsItem/electricSvgItemRect.cpp +++ b/source/graphicsItem/electricSvgItemRect.cpp @@ -1,5 +1,5 @@ #include "graphicsItem/electricSvgItemRect.h" -#include "graphicsItem/itemControlHandle.h" +#include "graphicsItem/itemPort.h" #include #include @@ -8,19 +8,27 @@ ElectricSvgItemRect::ElectricSvgItemRect(const QRect &rect, QGraphicsItem *paren : ElectricSvgItem(rect,parent) { loadSvg(":/images/element/svg_rect.svg"); + setHandleVisible(false); + setFunctionHandleIfShow(false); + setFunctionHandleEnaable(false); //入线口 - ItemControlHandle* pHandle1 = new ItemControlHandle(this); + ItemPort* pHandle1 = new ItemPort(this); pHandle1->setType(T_lineIn); pHandle1->setTag(H_connect); + pHandle1->setPortPos(P_top); m_vecHanle.insert(H_connect,pHandle1); //出线口 - ItemControlHandle* pHandle2 = new ItemControlHandle(this); + ItemPort* pHandle2 = new ItemPort(this); pHandle2->setType(T_lineOut); pHandle2->setTag(H_connect+1); + pHandle2->setPortPos(P_down); m_vecHanle.insert(H_connect+1,pHandle2); m_dRatioX = 0.5; + + m_mapPort.insert(QString::number(_portId++),pHandle1); + m_mapPort.insert(QString::number(_portId++),pHandle2); } ElectricSvgItemRect::~ElectricSvgItemRect() diff --git a/source/graphicsItem/electricSvgItemTriangle.cpp b/source/graphicsItem/electricSvgItemTriangle.cpp index 8c13d14..c95a6b3 100644 --- a/source/graphicsItem/electricSvgItemTriangle.cpp +++ b/source/graphicsItem/electricSvgItemTriangle.cpp @@ -1,5 +1,5 @@ #include "graphicsItem/electricSvgItemTriangle.h" -#include "graphicsItem/itemControlHandle.h" +#include "graphicsItem/itemPort.h" #include #include @@ -8,25 +8,35 @@ ElectricSvgItemTriangle::ElectricSvgItemTriangle(const QRect &rect, QGraphicsIte : ElectricSvgItem(rect,parent) { loadSvg(":/images/element/svg_triangle.svg"); + setHandleVisible(false); + setFunctionHandleIfShow(false); + setFunctionHandleEnaable(false); //入线口 - ItemControlHandle* pHandle1 = new ItemControlHandle(this); - pHandle1->setType(T_lineIn); + ItemPort* pHandle1 = new ItemPort(this); + pHandle1->setType(T_lineOut); pHandle1->setTag(H_connect); + pHandle1->setPortPos(P_top); m_vecHanle.insert(H_connect,pHandle1); //出线口 - ItemControlHandle* pHandle2 = new ItemControlHandle(this); - pHandle2->setType(T_lineOut); + ItemPort* pHandle2 = new ItemPort(this); + pHandle2->setType(T_lineIn); pHandle2->setTag(H_connect+1); + pHandle2->setPortPos(P_down); m_vecHanle.insert(H_connect+1,pHandle2); - ItemControlHandle* pHandle3 = new ItemControlHandle(this); - pHandle3->setType(T_lineOut); + ItemPort* pHandle3 = new ItemPort(this); + pHandle3->setType(T_lineIn); pHandle3->setTag(H_connect+2); + pHandle3->setPortPos(P_down); m_vecHanle.insert(H_connect+2,pHandle3); m_dTopRatioX = 0.5; m_dBottomRatioX = 0.333; + + m_mapPort.insert(QString::number(_portId++),pHandle1); + m_mapPort.insert(QString::number(_portId++),pHandle2); + m_mapPort.insert(QString::number(_portId++),pHandle3); } ElectricSvgItemTriangle::~ElectricSvgItemTriangle() diff --git a/source/graphicsItem/graphicsBaseItem.cpp b/source/graphicsItem/graphicsBaseItem.cpp index e9e0aeb..4892d02 100644 --- a/source/graphicsItem/graphicsBaseItem.cpp +++ b/source/graphicsItem/graphicsBaseItem.cpp @@ -1,4 +1,5 @@ #include "graphicsItem/graphicsBaseItem.h" +#include "graphicsItem/itemPort.h" #include @@ -6,6 +7,8 @@ GraphicsBaseItem::GraphicsBaseItem(QGraphicsItem *parent) : AbstractShapeType(parent) { m_type = T_item; + _portId = 1; + _lastPort = -1; //初始化缩放操作用的handle //m_vecHanle.reserve(H_left); for(int i = H_leftTop; i <= H_left; i++) @@ -100,6 +103,7 @@ QVariant GraphicsBaseItem::itemChange(QGraphicsItem::GraphicsItemChange change, QGraphicsItemGroup *group = dynamic_cast(parentItem()); if(!group) setHandleVisible(value.toBool()); + //setFunctionHandleVisible(false); else //在某一组群中,由组群展示是否选中,自身不做展示 { setSelected(false); @@ -114,3 +118,48 @@ void GraphicsBaseItem::contextMenuEvent(QGraphicsSceneContextMenuEvent* event) Q_UNUSED(event); } +int GraphicsBaseItem::addPort(PortState typ,QPointF vec) +{ + int ntagId = -1; + for(ntagId = H_connect;ntagId < 999;++ntagId) //添加到未占用位置 + { + if(!m_vecHanle.contains(ntagId)) + break; + } + if(typ == p_movable) + { + ItemPort* pPort = new ItemPort(this); + pPort->setType(T_lineInOut); + pPort->setTag(ntagId); + m_vecHanle.insert(ntagId,pPort); + pPort->setPos(vec); + + m_mapPort.insert(QString::number(_portId++),pPort); + } + return ntagId; +} + +void GraphicsBaseItem::addPort(PortState typ,int ntagId,QPointF vec) +{ + if(typ == p_movable) + { + ItemPort* pPort = new ItemPort(this); + pPort->setType(T_lineInOut); + pPort->setTag(ntagId); + m_vecHanle.insert(ntagId,pPort); + pPort->setPos(vec); + + m_mapPort.insert(QString::number(_portId++),pPort); + } +} + +ItemPort* GraphicsBaseItem::getPortPtr(int n) const +{ + for(auto iter:m_mapPort) + { + int tag = iter->getTag(); + if(tag == n) + return iter; + } + return nullptr; +} diff --git a/source/graphicsItem/itemControlHandle.cpp b/source/graphicsItem/itemControlHandle.cpp index 768f80e..99bead1 100644 --- a/source/graphicsItem/itemControlHandle.cpp +++ b/source/graphicsItem/itemControlHandle.cpp @@ -1,8 +1,6 @@ #include "graphicsItem/itemControlHandle.h" #include -#define HNDLE_SIZE 8 - ItemControlHandle::ItemControlHandle(QGraphicsItem *parent) : QGraphicsRectItem(-HNDLE_SIZE / 2, -HNDLE_SIZE / 2, @@ -11,6 +9,8 @@ ItemControlHandle::ItemControlHandle(QGraphicsItem *parent) { m_type = T_resize; m_tag = H_none; + m_enable = true; + m_ifShow = true; } ItemControlHandle::~ItemControlHandle() diff --git a/source/graphicsItem/itemPort.cpp b/source/graphicsItem/itemPort.cpp new file mode 100644 index 0000000..a67d4f8 --- /dev/null +++ b/source/graphicsItem/itemPort.cpp @@ -0,0 +1,77 @@ +#include +#include "graphicsItem/itemPort.h" + +ItemPort::ItemPort(QGraphicsItem *parent) + : ItemControlHandle(parent) +{ + _pos = P_top; + _ptr = nullptr; +} + +ItemPort::~ItemPort() +{ +} + +void ItemPort::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget) +{ + Q_UNUSED(option) + Q_UNUSED(widget) + + painter->setPen(Qt::SolidLine); + painter->setRenderHint(QPainter::Antialiasing, true); + + QPolygonF Triangle; + QRectF rec = rect(); + qreal left = rec.left(); + qreal right = rec.right(); + qreal width = rec.width(); + qreal height = rec.height(); + qreal bottom = rec.bottom(); + painter->setBrush(Qt::black); + if((_pos == P_top && m_type == T_lineIn) || (_pos == P_down && m_type == T_lineOut) ) //从上入或者从下出都是向下 + { + Triangle.append(QPointF(left,0)); + Triangle.append(QPointF(right,0)); + Triangle.append(QPointF(left+width*0.5,bottom)); + painter->drawPolygon(Triangle); + } + else if((_pos == P_top && m_type == T_lineOut) || (_pos == P_down && m_type == T_lineIn) ) //从上出或者从下入都是向上 + { + Triangle.append(QPointF(left,bottom)); + Triangle.append(QPointF(right,bottom)); + Triangle.append(QPointF(left+width*0.5,0)); + painter->drawPolygon(Triangle); + } + else if((_pos == P_left && m_type == T_lineIn) || (_pos == P_right && m_type == T_lineOut) ) //从左入或者从右出都是向右 + { + Triangle.append(QPointF(0,0)); + Triangle.append(QPointF(0,bottom)); + Triangle.append(QPointF(right,height*0.5)); + painter->drawPolygon(Triangle); + } + else if((_pos == P_left && m_type == T_lineOut) || (_pos == P_right && m_type == T_lineIn) ) //从左出或者从右入都是向左 + { + Triangle.append(QPointF(right,0)); + Triangle.append(QPointF(right,bottom)); + Triangle.append(QPointF(0,height*0.5)); + painter->drawPolygon(Triangle); + } + else if(m_type == T_lineInOut) + { + painter->drawEllipse(rect().center(), HNDLE_SIZE / 4, HNDLE_SIZE / 4); + } + + /*if(m_type==T_lineIn) + { + painter->setPen(Qt::NoPen); + painter->setBrush(Qt::green); + painter->drawEllipse(rect().center(), HNDLE_SIZE / 2, HNDLE_SIZE / 2); + } + else if(m_type==T_lineOut) + { + painter->setPen(Qt::NoPen); + painter->setBrush(Qt::red); + painter->drawEllipse(rect().center(), HNDLE_SIZE / 2, HNDLE_SIZE / 2); + }*/ + //ItemControlHandle::paint(painter,option,widget); +} diff --git a/source/statusBar.cpp b/source/statusBar.cpp new file mode 100644 index 0000000..80ad03e --- /dev/null +++ b/source/statusBar.cpp @@ -0,0 +1,21 @@ +#include +#include "statusBar.h" + +StatusBar::StatusBar(QWidget *parent) + : QStatusBar(parent) + ,m_pScaleLevel(nullptr) +{ + m_pScaleLevel = new QLabel("当前级数:10",this); + m_pScaleLevel->setMinimumWidth(250); + addWidget(m_pScaleLevel); +} + +StatusBar::~StatusBar() +{ + +} + +void StatusBar::onScaleLevelChanged(double f) +{ + m_pScaleLevel->setText(QString::fromWCharArray(L"当前级数:")+QString::number(f)); +} diff --git a/source/util/baseSelector.cpp b/source/util/baseSelector.cpp index d3c7387..3630c22 100644 --- a/source/util/baseSelector.cpp +++ b/source/util/baseSelector.cpp @@ -8,6 +8,8 @@ QPointF BaseSelector::ms_ptMouseDown(0.0,0.0); QPointF BaseSelector::ms_ptMouseLast(0.0,0.0); double BaseSelector::ms_dAngleMouseDownToItem = 0.0; int BaseSelector::ms_nDragHandle = 0; +uint BaseSelector::_Id = 0; +ItemMap BaseSelector::m_graphicsItem; BaseSelector::BaseSelector(QObject *parent) : QObject(parent) @@ -70,7 +72,8 @@ void BaseSelector::mousePressEvent(QGraphicsSceneMouseEvent* event, DesignerScen else if(ms_nDragHandle >= H_connect ) //连接控制点 { m_opMode = OM_connect; - setCursor(scene, Qt::ClosedHandCursor); + //setCursor(scene, Qt::ClosedHandCursor); + setCursor(scene, Qt::ArrowCursor); emit setWorkingSelector(ST_connecting); } else diff --git a/source/util/connectingSelector.cpp b/source/util/connectingSelector.cpp index 558bf55..980abfe 100644 --- a/source/util/connectingSelector.cpp +++ b/source/util/connectingSelector.cpp @@ -1,12 +1,18 @@ #include "util/connectingSelector.h" +#include "graphicsItem/itemControlHandle.h" +#include "graphicsItem/itemPort.h" +#include "graphicsItem/electricConnectLineItem.h" #include #include #include ConnectingSelector::ConnectingSelector(QObject *parent) - : BaseSelector(parent),m_pConnectingItem(nullptr) + : BaseSelector(parent) + ,m_pConnectingItem(nullptr) + ,m_pTouchedItem(nullptr) { m_type = ST_connecting; + m_bReadyConnect = false; } ConnectingSelector::~ConnectingSelector() { @@ -19,6 +25,112 @@ void ConnectingSelector::mousePressEvent(QGraphicsSceneMouseEvent* event, Design } +bool ConnectingSelector::targetCouldConnect(GraphicsBaseItem* p,QPointF pos) +{ + GraphicsItemType iType = p->getItemType(); + if(iType == GIT_bus) + { + setTargetHighLight(true); + return true; + } + else + { + int nHandle = p->collidesWithHandle(pos); + if(nHandle >= H_connect ) //连接控制点 + { + setTargetHighLight(false); + p->setLastPort(nHandle); + ItemPort* pt = p->getPortPtr(nHandle); + if(pt) + { + HandleType targetDir = pt->getType(); + bool bCon = pt->connected(); + + if(m_pConnectingItem) + { + ItemPort* ptSrc = m_pConnectingItem->getPortPtr(ms_nDragHandle); + HandleType sourceDir = ptSrc->getType(); + + if((targetDir != sourceDir) && !bCon) + { + setTargetHighLight(true); + return true; + } + } + } + } + else //超出了触碰范围 + { + setTargetHighLight(false); + p->setLastPort(-1); + } + } + return false; +} + +void ConnectingSelector::setTargetHighLight(bool val) +{ + if(m_pTouchedItem) + { + GraphicsItemType iType = m_pTouchedItem->getItemType(); + if(iType == GIT_bus) + { + m_pTouchedItem->setTouched(val); + } + else + { + int n = m_pTouchedItem->getLastPort(); + if(n != -1) + m_pTouchedItem->setHandleVisible(n,val); + } + } +} + +void ConnectingSelector::createConnectLline(GraphicsBaseItem* connectingItem,GraphicsBaseItem* touchedItem,DesignerScene* scene) +{ + ElectricConnectLineItem* pItem = new ElectricConnectLineItem(); + pItem->setItemId(++_Id); + pItem->setItemType(GIT_connectLine); + scene->addItem(pItem); + + ItemPort* ptSrc = connectingItem->getPortPtr(ms_nDragHandle); + int srcId = connectingItem->itemId(); + int srcPort = ptSrc->getTag(); + HandleType srcType = ptSrc->getType(); + pItem->setStartPoint(ptSrc->scenePos()); + ptSrc->setConnect(pItem); + + ItemPort* ptDest = nullptr; + if(touchedItem->getItemType() == GIT_bus) //母线动态创建port + { + int nId = touchedItem->addPort(p_movable,touchedItem->mapFromScene(ms_ptMouseLast)); + if(nId != -1) + { + ptDest = touchedItem->getPortPtr(nId); + pItem->setEndPoint(ptDest->scenePos()); + } + } + else + { + int nLastPort = touchedItem->getLastPort(); + ptDest = touchedItem->getPortPtr(nLastPort); + pItem->setEndPoint(ptDest->scenePos()); + } + + if(ptDest != nullptr) + { + int destId = touchedItem->itemId(); + int destPort = ptDest->getTag(); + HandleType destType = ptDest->getType(); + + pItem->calculatePath(); + pItem->setConnection(Connection(srcId,srcPort,srcType,destId,destPort,destType)); + ptDest->setConnect(pItem); + + m_graphicsItem[sceneName()].insert(QString::number(pItem->itemId()),pItem); //插入连接线到总表 + } +} + void ConnectingSelector::mouseMoveEvent(QGraphicsSceneMouseEvent* event, DesignerScene* scene) { ms_ptMouseLast = event->scenePos(); @@ -32,7 +144,7 @@ void ConnectingSelector::mouseMoveEvent(QGraphicsSceneMouseEvent* event, Designe { if(ms_nDragHandle != H_none) { - item->setState(S_lineOut); + item->setState(S_prepareConnect); QPointF start = item->mapFromScene(ms_ptMouseDown); QPointF end = item->mapFromScene(ms_ptMouseLast); item->setBeginConnectPos(start); @@ -48,6 +160,33 @@ void ConnectingSelector::mouseMoveEvent(QGraphicsSceneMouseEvent* event, Designe { QPointF end = m_pConnectingItem->mapFromScene(ms_ptMouseLast); m_pConnectingItem->setEndConnectPos(end); + + QList items = scene->items(ms_ptMouseLast); + if (items.count() == 1) + { + GraphicsBaseItem* item = dynamic_cast(items.first()); + if(item) + { + int n1 = item->itemId(); + int n2 = m_pConnectingItem->itemId(); + if(n1 != n2) //判断两个对象是否相同 + { + m_pTouchedItem = item; + m_bReadyConnect = targetCouldConnect(item,ms_ptMouseLast); + } + } + } + if(items.isEmpty()) + { + //todo取消选中 + m_bReadyConnect = false; + setTargetHighLight(false); + if(m_pTouchedItem) + { + m_pTouchedItem->setLastPort(-1); + m_pTouchedItem = nullptr; + } + } } } @@ -55,8 +194,24 @@ void ConnectingSelector::mouseMoveEvent(QGraphicsSceneMouseEvent* event, Designe void ConnectingSelector::mouseReleaseEvent(QGraphicsSceneMouseEvent* event, DesignerScene* scene) { + if(m_bReadyConnect) + { + if(m_pConnectingItem && m_pTouchedItem) + { + createConnectLline(m_pConnectingItem,m_pTouchedItem,scene); + } + } + if(m_pConnectingItem) + { m_pConnectingItem->setState(S_normal); + } + if(m_pTouchedItem) + { + setTargetHighLight(false); + m_pTouchedItem->setLastPort(-1); + m_pTouchedItem = nullptr; + } m_pConnectingItem = nullptr; ms_nDragHandle = H_none; setCursor(scene, Qt::ArrowCursor); diff --git a/source/util/creatingSelector.cpp b/source/util/creatingSelector.cpp index 318ccfa..1efdf9b 100644 --- a/source/util/creatingSelector.cpp +++ b/source/util/creatingSelector.cpp @@ -16,6 +16,7 @@ CreatingSelector::CreatingSelector(QObject *parent) m_creatingMethod = CM_drag; m_pCreatingItem = nullptr; m_scalBasePoint = QPointF(); + _Id = 0; } CreatingSelector::~CreatingSelector() { @@ -58,7 +59,8 @@ void CreatingSelector::mousePressEvent(QGraphicsSceneMouseEvent* event, Designer { m_creatingMethod = CM_click; m_pCreatingItem = new ElectricSvgItemBus(QRect(-100, -3, 200, 6)); - + m_pCreatingItem->setItemId(++_Id); + m_pCreatingItem->setItemType(GIT_bus); m_pCreatingItem->editShape(ms_nDragHandle, ms_ptMouseLast); emit setWorkingSelector(ST_base); } @@ -66,8 +68,9 @@ void CreatingSelector::mousePressEvent(QGraphicsSceneMouseEvent* event, Designer case GIT_itemRect: { m_creatingMethod = CM_click; - m_pCreatingItem = new ElectricSvgItemRect(QRect(-30, -30, 60, 60)); - + m_pCreatingItem = new ElectricSvgItemRect(QRect(-20, -20, 40, 40)); + m_pCreatingItem->setItemId(++_Id); + m_pCreatingItem->setItemType(GIT_itemRect); m_pCreatingItem->editShape(ms_nDragHandle, ms_ptMouseLast); emit setWorkingSelector(ST_base); } @@ -75,8 +78,9 @@ void CreatingSelector::mousePressEvent(QGraphicsSceneMouseEvent* event, Designer case GIT_itemTri: { m_creatingMethod = CM_click; - m_pCreatingItem = new ElectricSvgItemTriangle(QRect(-30, -30, 60, 60)); - + m_pCreatingItem = new ElectricSvgItemTriangle(QRect(-20, -20, 40, 40)); + m_pCreatingItem->setItemId(++_Id); + m_pCreatingItem->setItemType(GIT_itemTri); m_pCreatingItem->editShape(ms_nDragHandle, ms_ptMouseLast); emit setWorkingSelector(ST_base); } @@ -106,6 +110,7 @@ void CreatingSelector::mousePressEvent(QGraphicsSceneMouseEvent* event, Designer //创建时添加了第一个点,紧接着再次添加第二点,然后从第二个点开始进行移动绘制 m_pCreatingItem->addPoint(ms_ptMouseDown); ms_nDragHandle = m_pCreatingItem->handleCount(); + m_graphicsItem[sceneName()].insert(QString::number(m_pCreatingItem->itemId()),m_pCreatingItem); //插入数据到总表 m_pCreatingItem = nullptr; //先舍弃多次点击创建对象241124 by } } diff --git a/source/util/movingSelector.cpp b/source/util/movingSelector.cpp index 5b546b1..bc4c16d 100644 --- a/source/util/movingSelector.cpp +++ b/source/util/movingSelector.cpp @@ -1,7 +1,9 @@ #include "util/movingSelector.h" +#include "graphicsItem/itemPort.h" #include #include #include +#include "graphicsItem/electricConnectLineItem.h" MovingSelector::MovingSelector(QObject *parent) : BaseSelector(parent) @@ -15,7 +17,10 @@ MovingSelector::~MovingSelector() void MovingSelector::mousePressEvent(QGraphicsSceneMouseEvent* event, DesignerScene* scene) { + ms_ptMouseLast = event->scenePos(); + QList items = scene->selectedItems(); + updateConnectLine(items); } void MovingSelector::mouseMoveEvent(QGraphicsSceneMouseEvent* event, DesignerScene* scene) @@ -40,9 +45,33 @@ void MovingSelector::mouseReleaseEvent(QGraphicsSceneMouseEvent* event, Designer if(item) item->removeOperationCopy(); } + updateConnectLine(items); setCursor(scene, Qt::ArrowCursor); scene->callParentEvent(event); emit setWorkingSelector(ST_base); } +void MovingSelector::updateConnectLine(QList lst) +{ + for(auto iter:lst) //更新连接线 + { + auto item = dynamic_cast(iter); + if(item) + { + if(item->getItemType() != GIT_connectLine) + { + int nId = item->itemId(); + for(auto pPort:item->getPorts()) + { + if(pPort->connected()) + { + auto pConnect = pPort->getConnectPtr(); + pConnect->updateConnection(nId,pPort->scenePos()); + } + } + } + } + } +} + diff --git a/source/util/selectorManager.cpp b/source/util/selectorManager.cpp index e78e0a6..fcd6299 100644 --- a/source/util/selectorManager.cpp +++ b/source/util/selectorManager.cpp @@ -69,6 +69,14 @@ void SelectorManager::setDrawGraphicsItem(GraphicsItemType item) } } +void SelectorManager::setName(const QString& str) +{ + for(auto iter:m_vecSelectors) + { + iter->setSceneName(str); + } +} + void SelectorManager::onSignal_setWorkingSelector(SelectorType s) { setWorkingSelector(s);