DiagramDesigner/diagramCavas/include/graphicsItem/graphicsBaseItem.h

522 lines
18 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#ifndef GRAPHICSBASEITEM_H
#define GRAPHICSBASEITEM_H
#include "itemControlHandle.h"
#include "global.h"
#include <QObject>
#include <QGraphicsItem>
#include <QGraphicsSceneMouseEvent>
#include <QPen>
#include <QGraphicsSvgItem>
#include <QUuid>
#include <QJsonObject>
//#include "graphicsItem/itemPort.h"
enum ShapeType
{
T_undefined,
T_item,
T_group
};
enum ItemState
{
S_normal = 0,
S_prepareConnect,
};
//基类采用模板形式QGraphicsItem是默认值,也可以是别的类型比如QGraphicsItemGroup这样不同的基类继承可以共用一些高层的行为定义
template <typename BaseType = QGraphicsItem>
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 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<QGraphicsItem> AbstractShape;
class GraphicsNonStandardItem:public QObject, public AbstractShapeType<QGraphicsItem> //非标准图元,如间隔
{
Q_OBJECT
public:
GraphicsNonStandardItem(QGraphicsItem *parent = 0)
:AbstractShapeType<QGraphicsItem>(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<QGraphicsItem>
{
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<QString,ItemPort*> getPorts() {return m_mapPort;}
//virtual GraphicsBaseItem*
virtual void initialPortsByDatabase(); //从数据库初始化port信息
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<QString,ItemPort*> m_mapPort; //单独存放port
QMap<int,ItemControlHandle*> 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();
protected:
virtual QVariant itemChange(QGraphicsItem::GraphicsItemChange, const QVariant&);
};
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~10~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