DiagramDesigner/diagramCavas/include/graphicsItem/graphicsBaseItem.h

596 lines
21 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;
m_touched = false;
}
virtual ~AbstractShapeType()
{
/*for (size_t i = 0; i < m_vecHanle.size(); i++)
{
ItemControlHandle* pHandle = m_vecHanle[i];
if (pHandle)
{
delete pHandle;
pHandle = nullptr;
}
}*/
foreach (int key, m_vecHanle.keys())
{
ItemControlHandle* pHandle = m_vecHanle.value(key);
if (pHandle)
{
delete pHandle;
pHandle = nullptr;
}
}
}
public:
virtual ShapeType getType() {return m_type;}
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();
}
int collidesWithHandle(const QPointF& point)
{
/*for(auto it = m_vecHanle.begin(); it != m_vecHanle.end(); it++)
{
QPointF pt = (*it)->mapFromScene(point);
if((*it)->contains(pt))
return (*it)->getTag();
}*/
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;
}
//操作副本相关
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() {}
//handle相关
virtual int handleCount() { return m_vecHanle.count(); }
virtual ItemControlHandle* getHandle(int nHandle)
{
ItemControlHandle* handle = nullptr;
/*for(auto it = m_vecHanle.begin(); it != m_vecHanle.end(); it++)
{
if((*it)->getTag() == nHandle)
{
handle = (*it);
return handle;
}
}*/
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)
{
/*for(auto it = m_vecHanle.begin(); it != m_vecHanle.end(); it++)
{
if(bVisible)
(*it)->show();
else
(*it)->hide();
}*/
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);
}
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 setTouched(bool b){m_touched = b;}
virtual void setLastPoint(QPointF p) {m_lastPoint = p;}
protected:
ShapeType m_type;
QPen m_pen;
QBrush m_brush;
double m_dWidth;
double m_dHeight;
QRectF m_boundingRect;
QRectF m_boundingRect_selected; //选中矩形框
bool m_touched; //被触碰状态
double m_dSyncRotationByParent; //父项(被加入到某一组)的旋转数据,因为加入某一组后,对该组进行旋转,自身的旋转数据不会同步更新
QGraphicsPathItem* m_pOperationCopy; //图元移动和旋转时的操作副本
QPointF m_movingIniPos; //移动副本开始移动初始
QPointF m_lastPoint; //鼠标上次点击位置
QMap<int,ItemControlHandle*> m_vecHanle;
};
class ItemPort;
class BaseProperty;
typedef AbstractShapeType<QGraphicsItem> AbstractShape;
class GraphicsBaseItem : public QObject, public AbstractShapeType<QGraphicsItem>
{
Q_OBJECT
public:
GraphicsBaseItem(QGraphicsItem *parent);
virtual ~GraphicsBaseItem();
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 int addPort(PortState typ,QPointF vec); //新建,返回-1失败
virtual void addPort(PortState typ,int ntagId,QPointF vec); //载入 PortState为P_const时QPointF中为(0~10~1)的相对位置;PortState为p_movable时QPointF为坐标值
virtual QUuid itemId() const {return m_itemId;}
virtual void setItemId(QUuid 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 ItemControlHandle* getHandlePtr(int) const;
virtual QMap<QString,ItemPort*>& getPorts() {return m_mapPort;}
virtual void setProperty(BaseProperty* p);
virtual BaseProperty* getProperty() {return _property;}
virtual void unbindProperty(); //断开图元与数据的绑定
virtual void updateByProperty(); //使用data对象更新自己
virtual void showPropertyDlg(QWidget* p); //显示属性对话框,参数为父对象
virtual void updateConnectData(); //更新连接关系数据
virtual void setItemChanged(bool b){_itemChanged = b;}
virtual bool itemChanged() const {return _itemChanged;}
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,GraphicsBaseItem*);
public slots:
void onEditNameFinish(const QString&);
void onUpdateData(); //data发送的更新通知
protected:
QUuid m_itemId;
GraphicsItemType m_Itemtype;
ItemState m_state;
QMap<QString,ItemPort*> m_mapPort; //单独存放port
QPointF m_beginConnectPoint;
QPointF m_endConnectPoint;
uint _portId; //port编号
int _lastPort; //最后触碰的port
BaseProperty* _property;
bool _itemChanged; //图元变化标志,判断是否需要保存
QString _modelName; //当前图元使用的模型名用来在model中检索属性信息
};
class BaseProperty:public QObject //属性类,存放电路元件属性
{
Q_OBJECT
public:
BaseProperty(QObject* parent);
virtual ~BaseProperty();
void setUuid(QUuid id) {uUid = id;}
QUuid uuid() const {return uUid;}
void setModelName(QString sName) {sModelName = sName;}
QString modelName() const {return sModelName;}
void setType(int n) {nType = n;}
int type() const {return nType;}
void setPage(int n){nPageId = n;}
int page() const {return nPageId;}
void setTag(QString s){sTag = s;}
QString tag() const {return sTag;}
void setName(QString s){sName = s;}
QString name() const {return sName;}
void setPath(QString s){sPath = s;}
QString path() const {return sPath;}
void setDescription(QString s) {sDescription = s;}
QString description() const {return sDescription;}
void setInService(bool b) {bInService = b;}
bool inService() {return bInService;}
void setState(int n) {nState = n;}
int state() const {return nState;}
void setConnectedBus(QJsonObject j) {jConnectedBus = j;}
QJsonObject connectedBus() const {return jConnectedBus;}
void setLabel(QJsonObject j){jLabel = j;}
QJsonObject label() const {return jLabel;}
void setContext(QJsonObject j){jContext = j;}
QJsonObject context() const {return jContext;}
void setGrid(const QString& s) {sGrid = s;}
QString grid() const {return sGrid;}
void setZone(const QString& s) {sZone = s;}
QString zone() const {return sZone;}
void setStation(const QString& s) {sStation = s;}
QString station() const {return sStation;}
void setPrepareDelete(bool b) {_prepareDelete = b;}
bool prepareDelete() const {return _prepareDelete;}
void setDataChanged(bool b) {_dataChanged = b;} //数据变换标签
bool dataChanged() const {return _dataChanged;}
void notifyUpdate(){emit updateData();}
signals:
void updateData(); //通知数据拥有者更新
protected:
QUuid uUid;
QString sModelName; //模型名
int nType; //设备类型
int nPageId; //暂定为创建本数据的图Id(待定)
QString sTag;
QString sName;
QString sPath;
QString sDescription;
QString sGrid;
QString sZone;
QString sStation;
bool bInService;
int nState;
QJsonObject jConnectedBus;
QJsonObject jLabel;
QJsonObject jContext; //存放port信息
bool _dataChanged; //数据状态,为真则写入库
bool _prepareDelete; //状态,为真准备删除
};
typedef QMap<QString,QVariant> VariableMap; //属性名,值
class VariableProperty:public BaseProperty //收到的变量数据
{
Q_OBJECT
public:
VariableProperty(QObject* parent);
~VariableProperty();
QMap<QString,VariableMap>& getMapGroup() {return _MapGroup;}
private:
QMap<QString,VariableMap> _MapGroup; //<属性组,属性集>
};
#endif