#ifndef GRAPHICSBASEITEM_H #define GRAPHICSBASEITEM_H #include "itemControlHandle.h" #include "global.h" #include #include #include #include #include #include #include //#include "graphicsItem/itemPort.h" enum ShapeType { T_undefined, T_item, T_group }; enum ItemState { S_normal = 0, S_prepareConnect, }; //基类采用模板形式,QGraphicsItem是默认值,也可以是别的类型,比如QGraphicsItemGroup,这样不同的基类继承可以共用一些高层的行为定义 template class AbstractShapeType : public BaseType { public: explicit AbstractShapeType(QGraphicsItem *parent = 0) : BaseType(parent) { m_type = T_undefined; m_pen = QPen(Qt::NoPen); m_brush = QBrush(QColor(rand() % 32 * 8, rand() % 32 * 8, rand() % 32 * 8)); m_dWidth = m_dHeight = 0; m_pOperationCopy = nullptr; m_dSyncRotationByParent = 0.0; } virtual ~AbstractShapeType() { } public: virtual ShapeType getType() {return m_type;} virtual QUuid itemId() const {return m_itemId;} virtual void setItemId(QUuid n){m_itemId = n;} QPen pen() { return m_pen; } void setPen(const QPen &pen) { m_pen = pen; } QColor penColor() { return m_pen.color(); } void setPenColor(const QColor &color) { m_pen.setColor(color); } QBrush brush() { return m_brush; } void setBrush(const QBrush &brush) { m_brush = brush; } QColor brushColor() { return m_brush.color(); } void setBrushColor(const QColor &color) { m_brush.setColor(color); } double width() { return m_dWidth; } void setWidth(double width) { m_dWidth = width; updateCoordinate(); } double height() { return m_dHeight; } void setHeight(double height) { m_dHeight = height; updateCoordinate(); } //操作副本相关 virtual void createOperationCopy() {} virtual void removeOperationCopy() {} virtual void moveOperationCopy(const QPointF&) {} virtual void rotateOperationCopy(const double&) {} virtual void resize(int,double, double, const QPointF&) {} virtual void move(const QPointF&) {} virtual void editShape(int, const QPointF&) {} virtual void updateCoordinate() {} virtual void setBoundingRect(QRectF rec){m_boundingRect = rec;} virtual QRectF boundingRect() const { return m_boundingRect; } virtual QPainterPath shape() { QPainterPath path; return path; } virtual void syncRotationDataFromParent(const double&) {} virtual double getSyncRotationDataFromParent() {return m_dSyncRotationByParent;} virtual void setItemType(GraphicsItemType type){m_Itemtype = type;} virtual GraphicsItemType getItemType() const {return m_Itemtype;} protected: QUuid m_itemId; ShapeType m_type; QPen m_pen; QBrush m_brush; double m_dWidth; double m_dHeight; QRectF m_boundingRect; GraphicsItemType m_Itemtype; //显示类型 double m_dSyncRotationByParent; //父项(被加入到某一组)的旋转数据,因为加入某一组后,对该组进行旋转,自身的旋转数据不会同步更新 QGraphicsPathItem* m_pOperationCopy; //图元移动和旋转时的操作副本 QPointF m_movingIniPos; //移动副本开始移动初始 }; class ItemPort; class ModelProperty; class PowerEntity; class AbstractProperty; typedef AbstractShapeType AbstractShape; class GraphicsNonStandardItem:public QObject, public AbstractShapeType //非标准图元,如间隔 { Q_OBJECT public: GraphicsNonStandardItem(QGraphicsItem *parent = 0) :AbstractShapeType(parent) { setFlag(QGraphicsItem::ItemIsSelectable, true); } virtual ~GraphicsNonStandardItem(){}; virtual void setProperty(AbstractProperty* p){_property = p;} virtual AbstractProperty* getProperty() {return _property;} bool containsPoint(const QPointF& pos) { QPointF localPos = mapFromScene(pos); QPainterPath path = shape(); // 或更精确的计算 return path.contains(localPos); } protected: AbstractProperty* _property; }; class GraphicsBaseItem :public QObject, public AbstractShapeType { Q_OBJECT public: GraphicsBaseItem(QGraphicsItem *parent); virtual ~GraphicsBaseItem(); public: virtual int addPort(PortState typ,QPointF vec,QString id = "",HandleType hType = T_lineInOut,PortPos pos = P_top); //新建,返回-1失败 virtual void setEntity(PowerEntity*); //设置当前图元的拓扑数据 virtual PowerEntity* entity(); virtual void setProperty(ModelProperty* p); virtual ModelProperty* getProperty() {return _property;} virtual void updateByProperty(){}; //使用data对象更新自己 virtual void setItemChanged(bool b){_itemChanged = b;} virtual bool itemChanged() const {return _itemChanged;} virtual void renderSelectBackground(QPainter*); virtual ItemPort* getPortById(QString) const; virtual ItemPort* getPortPtr(int) const; virtual ItemControlHandle* getHandlePtr(int) const; virtual QMap getPorts() {return m_mapPort;} //virtual GraphicsBaseItem* virtual void initialPortsByDatabase(int nComponentTypeId); //从数据库初始化port信息,component_type中的id virtual void setLastPoint(QPointF p) {m_lastPoint = p;} virtual void setTouched(bool b){m_touched = b;} int collidesWithHandle(const QPointF& point) { foreach (int key, m_vecHanle.keys()) { ItemControlHandle* pHandle = m_vecHanle.value(key); if (pHandle) { QPointF pt = pHandle->mapFromScene(point); if(pHandle->contains(pt)) { if(pHandle->enable()) return pHandle->getTag(); } } } return HandleTag::H_none; } //handle相关 virtual int handleCount() { return m_vecHanle.count(); } virtual ItemControlHandle* getHandle(int nHandle) { ItemControlHandle* handle = nullptr; foreach (int key, m_vecHanle.keys()) { ItemControlHandle* pHandle = m_vecHanle.value(key); if (pHandle) { if(pHandle->getTag() == nHandle) { handle = pHandle; return handle; } } } return handle; } virtual void setHandleVisible(bool bVisible) { foreach (int key, m_vecHanle.keys()) { ItemControlHandle* pHandle = m_vecHanle.value(key); if(pHandle) { 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 setHandleIfShow(int tag,bool bVisible) //是否参与显示判断 { foreach (int key, m_vecHanle.keys()) { ItemControlHandle* pHandle = m_vecHanle.value(key); if(pHandle) { if(pHandle->getTag() == tag) { pHandle->setIfShow(bVisible); 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; } } } } virtual QPointF getSymmetricPointPos(int nHandle) //获取对称点的坐标位置,缩放的时候需要以对称点为锚点 { QPointF pt; //handle的位置相对boundingRect会有一个向外的错位,因此直接采用bounddingRect的相应位置会更精准 switch (nHandle) { case H_leftTop: //pt = m_vecHanle.at(H_rightBottom - 1)->pos(); pt = m_boundingRect.bottomRight(); break; case H_top: //pt = m_vecHanle.at(H_bottom - 1)->pos(); pt = QPointF(m_boundingRect.width() * 0.5, m_boundingRect.bottom()); break; case H_rightTop: //pt = m_vecHanle.at(H_leftBottom - 1)->pos(); pt = m_boundingRect.bottomLeft(); break; case H_right: //pt = m_vecHanle.at(H_left - 1)->pos(); pt = QPointF(m_boundingRect.left(), m_boundingRect.height() * 0.5); break; case H_rightBottom: //pt = m_vecHanle.at(H_leftTop - 1)->pos(); pt = m_boundingRect.topLeft(); break; case H_bottom: //pt = m_vecHanle.at(H_top - 1)->pos(); pt = QPointF(m_boundingRect.width() * 0.5, m_boundingRect.top()); break; case H_leftBottom: //pt = m_vecHanle.at(H_rightTop - 1)->pos(); pt = m_boundingRect.topRight(); break; case H_left: //pt = m_vecHanle.at(H_right - 1)->pos(); pt = QPointF(m_boundingRect.right(), m_boundingRect.height() * 0.5); break; default: break; } return pt; } virtual void updateHandles() { int nMargin = 5; const QRectF& boundRect = this->boundingRect(); foreach (int key, m_vecHanle.keys()) { ItemControlHandle* pHandle = m_vecHanle.value(key); if(pHandle) { switch (pHandle->getTag()) { case H_leftTop: pHandle->move(boundRect.x() - nMargin, boundRect.y() - nMargin); break; case H_top: pHandle->move(boundRect.x() + boundRect.width() * 0.5, boundRect.y() - nMargin); break; case H_rightTop: pHandle->move(boundRect.x() + boundRect.width() + nMargin, boundRect.y() - nMargin); break; case H_right: pHandle->move(boundRect.x() + boundRect.width() + nMargin, boundRect.y() + boundRect.height() * 0.5 + nMargin); break; case H_rightBottom: pHandle->move(boundRect.x() + boundRect.width() + nMargin, boundRect.y() + boundRect.height() + nMargin); break; case H_bottom: pHandle->move(boundRect.x() + boundRect.width() * 0.5, boundRect.y() + boundRect.height()+ nMargin); break; case H_leftBottom: pHandle->move(boundRect.x() - nMargin, boundRect.y() + boundRect.height() + nMargin); break; case H_left: pHandle->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(); pHandle->move(pt.x() - nSize - 1, pt.y() - nSize - 1); } else pHandle->setVisible(false); break; } case H_rotate_rightTop: { ItemControlHandle* handle = getHandle(H_rightTop); if(handle) { int nSize = handle->getSize(); QPointF pt = handle->pos(); pHandle->move(pt.x() + nSize + 1, pt.y() - nSize - 1); } else pHandle->setVisible(false); break; } case H_rotate_rightBottom: { ItemControlHandle* handle = getHandle(H_rightBottom); if(handle) { int nSize = handle->getSize(); QPointF pt = handle->pos(); pHandle->move(pt.x() + nSize + 1, pt.y() + nSize + 1); } else pHandle->setVisible(false); break; } case H_rotate_leftBottom: { ItemControlHandle* handle = getHandle(H_leftBottom); if(handle) { int nSize = handle->getSize(); QPointF pt = handle->pos(); pHandle->move(pt.x() - nSize - 1, pt.y() + nSize + 1); } else pHandle->setVisible(false); break; } default: break; } } } double dWidth = boundRect.width(); double dHeight = boundRect.height(); double dDiagonal = sqrt((dWidth* 0.5)*(dWidth * 0.5)+(dHeight*0.5)*(dHeight*0.5)); double dParam = dWidth > dHeight ? (dDiagonal-dWidth*0.5):(dDiagonal-dHeight*0.5); m_boundingRect_selected = boundRect.adjusted(-dParam-nMargin, -dParam-nMargin, dParam+nMargin, dParam+nMargin); } public slots: void onUpdateData(); //data发送的更新通知 protected: ModelProperty* _property; PowerEntity* _pEntity; //图元拓扑 bool _itemChanged; //图元变化标志,判断是否需要保存 QMap m_mapPort; //单独存放port QMap m_vecHanle; QPointF m_lastPoint; //鼠标上次点击位置 bool m_touched; //被触碰状态 QRectF m_boundingRect_selected; //选中矩形框 }; class GraphicsBaseModelItem : public GraphicsBaseItem //基模item { Q_OBJECT public: GraphicsBaseModelItem(QGraphicsItem *parent); virtual ~GraphicsBaseModelItem(); virtual void paint(QPainter*, const QStyleOptionGraphicsItem*, QWidget*) override; protected: virtual QVariant itemChange(QGraphicsItem::GraphicsItemChange, const QVariant&) override; }; class GraphicsProjectModelItem : public GraphicsBaseItem //工程模item { Q_OBJECT public: GraphicsProjectModelItem(QGraphicsItem *parent); virtual ~GraphicsProjectModelItem(); virtual void createOperationCopy(); virtual void removeOperationCopy(); virtual void moveOperationCopy(const QPointF&); virtual void rotateOperationCopy(const double&); virtual void syncRotationDataFromParent(const double&); //多边形、线段等点选创建的对象需要的函数 virtual void addPoint(const QPointF&) {} virtual bool endDrawing() { return true; } virtual void setLabelTag(const QString& name); //设置名字牌 virtual QString getLabelTag() const; virtual void setLabelCurrent(const QString& str); //设置电流标签 virtual QString getLabelCurrent() const; virtual void setLabelVoltage(const QString& str); //设置电压标签 virtual QString getLabelVoltage() const; //virtual void addPort(PortState typ,int ntagId,QPointF vec); //载入 PortState为P_const时,QPointF中为(0~1,0~1)的相对位置;PortState为p_movable时,QPointF为坐标值 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 setLastPort(int n){_lastPort = n;} virtual int getLastPort() const {return _lastPort;} virtual void unbindProperty(); //断开图元与数据的绑定 virtual void updateByProperty(); //使用data对象更新自己 virtual void updateConnectData(); //更新连接关系数据 virtual void setModelName(QString sName){_modelName = sName;} virtual QString getModelName() const {return _modelName;} protected: virtual QVariant itemChange(QGraphicsItem::GraphicsItemChange, const QVariant&); virtual void contextMenuEvent(QGraphicsSceneContextMenuEvent*); signals: void ifExist(QUuid id,const QString&,int type,GraphicsProjectModelItem*); public slots: void onEditNameFinish(const QString&); protected: ItemState m_state; QPointF m_beginConnectPoint; QPointF m_endConnectPoint; int _lastPort; //最后触碰的port QString _modelName; //当前图元使用的模型名,用来在model中检索属性信息 }; #endif