DiagramDesigner/diagramCavas/source/graphicsItem/graphicsBaseItem.cpp

802 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.

#include "graphicsItem/graphicsBaseItem.h"
#include "graphicsItem/handleRect.h"
#include "graphicsItem/handleText.h"
#include "graphicsItem/itemPort.h"
#include "baseProperty.h"
#include "dataBase.h"
#include <QGraphicsScene>
#include <QJsonArray>
#include <QPainter>
GraphicsBaseItem::GraphicsBaseItem(QGraphicsItem *parent)
: AbstractShapeType<QGraphicsItem>(parent)
,_property(nullptr)
,_pEntity(nullptr)
{
m_type = T_item;
_itemChanged = false;
m_touched = false;
setFlag(QGraphicsItem::ItemIsSelectable, true);
setFlag(QGraphicsItem::ItemSendsGeometryChanges, true);
setAcceptHoverEvents(true);
m_layoutRadius = 80;
}
GraphicsBaseItem::GraphicsBaseItem(const GraphicsBaseItem& obj)
:AbstractShapeType<QGraphicsItem>(obj)
,_property(nullptr)
,_pEntity(nullptr)
{
m_type = T_item;
_itemChanged = false;
m_touched = false;
setFlag(QGraphicsItem::ItemIsSelectable, true);
setFlag(QGraphicsItem::ItemSendsGeometryChanges, true);
setAcceptHoverEvents(true);
m_layoutRadius = 80;
m_lastPoint = obj.m_lastPoint;
m_touched = obj.m_touched;
m_boundingRect_selected = obj.m_boundingRect_selected;
PortState tpe;
if(m_Itemtype == GIT_baseNode || m_Itemtype == GIT_baseBus || m_Itemtype == GIT_node || m_Itemtype == GIT_bus){
tpe = p_movable;
}
else{
tpe = P_const;
}
for(auto& port:obj.m_mapPort){
addPort(tpe,port->pos(),port->getId(),port->getType(),port->portPos(),port->getXPercent(),port->getYPercent());
}
}
GraphicsBaseItem::~GraphicsBaseItem()
{
foreach (int key, m_vecHanle.keys())
{
ItemControlHandle* pHandle = m_vecHanle.value(key);
if (pHandle)
{
delete pHandle;
pHandle = nullptr;
}
}
}
int GraphicsBaseItem::addPort(PortState typ,QPointF vec,QString id,HandleType hType,PortPos pos,double dXPercent,double dYPercent)
{
int ntagId = -1;
for(ntagId = H_connect;ntagId < 999;++ntagId) //添加到未占用位置
{
if(!m_vecHanle.contains(ntagId))
break;
}
ItemPort* pPort = new ItemPort(this);
if(id.isEmpty())
{
pPort->setId(QUuid::createUuid().toString());
}
else
{
pPort->setId(id);
}
if(typ == p_movable)
{
pPort->setType(T_lineInOut);
}
else
{
pPort->setType(hType);
pPort->setPortPos(pos);
pPort->setXPercent(dXPercent);
pPort->setYPercent(dYPercent);
}
pPort->setTag(ntagId);
m_vecHanle.insert(ntagId,pPort);
pPort->setParent(this);
pPort->setPos(vec);
m_mapPort.insert(pPort->getId(),pPort);
return ntagId;
}
void GraphicsBaseItem::movePort(QString id,QPointF vec)
{
if(m_mapPort.contains(id)){
auto pPort = m_mapPort.value(id);
pPort->setPos(vec);
}
}
void GraphicsBaseItem::setEntity(PowerEntity* pEntity)
{
_pEntity = pEntity;
}
PowerEntity* GraphicsBaseItem::entity()
{
return _pEntity;
}
void GraphicsBaseItem::setProperty(ModelProperty* p)
{
if(_property) //已经有对象
{
disconnect(_property,&ModelProperty::updateData,this,&GraphicsBaseItem::onUpdateData); //断开老数据
}
connect(p,&ModelProperty::updateData,this,&GraphicsBaseItem::onUpdateData);
_property = p;
}
void GraphicsBaseItem::renderSelectBackground(QPainter* painter)
{
int nPenWidth = 1;
painter->setPen(QPen(QColor(135,206,235,180))); //蓝色的外框
painter->setBrush(QBrush(QColor(135,206,235,180)));
double dx = m_boundingRect_selected.x();
double dy = m_boundingRect_selected.y();
double dWidth = m_boundingRect_selected.width();
double dHeight = m_boundingRect_selected.height();
//画弧线0度是3点钟方向
if(dWidth > dHeight)
{
painter->drawRect(m_boundingRect_selected);
painter->drawChord(dx-dHeight*0.5,dy,dHeight,dHeight,90*16,180*16);
painter->drawChord(dx+dWidth-dHeight*0.5,dy,dHeight,dHeight,(-90)*16,180*16);
}
else if(dWidth < dHeight)
{
painter->drawRect(m_boundingRect_selected);
painter->drawChord(dx,dy-dWidth*0.5,dWidth,dWidth,0*16,180*16);
painter->drawChord(dx,dy+dHeight-dWidth*0.5,dWidth,dWidth,180*16,180*16);
//painter->drawChord(dx+dWidth-dHeight*0.5,dy,dHeight,dHeight,(-90)*16,180*16);
}
else
{
painter->drawEllipse(QPointF(dx+dWidth*0.5,dy+dHeight*0.5),dHeight*0.5,dHeight*0.5);
}
}
ItemPort* GraphicsBaseItem::getPortById(QString id) const
{
for(auto iter:m_mapPort)
{
QString portId = iter->getId();
if(portId == id)
return iter;
}
return nullptr;
}
ItemPort* GraphicsBaseItem::getPortPtr(int n) const
{
for(auto iter:m_mapPort)
{
int tag = iter->getTag();
if(tag == n)
return iter;
}
return nullptr;
}
ItemControlHandle* GraphicsBaseItem::getHandlePtr(int n) const
{
for(auto iter:m_vecHanle)
{
int tag = iter->getTag();
if(tag == n)
return iter;
}
return nullptr;
}
void GraphicsBaseItem::onUpdateData()
{
updateByProperty();
}
void GraphicsBaseItem::initialPortsByDatabase(int nComponentTypeId)
{
QMap<int,componentTypeInfo> mapType = DataBase::GetInstance()->getAllComponentType();
if(mapType.contains(nComponentTypeId))
{
QJsonArray nodesJsonArray = mapType[nComponentTypeId].config["port"].toArray();
for (QJsonValueRef nodeJson : nodesJsonArray)
{
QJsonObject node = nodeJson.toObject();
double dX = node["xRatio"].toDouble();
double dY = node["yRatio"].toDouble();
int movable = node["movable"].toInt();
int portType = node["portType"].toInt();
int portLocate = node["portLocate"].toInt();
addPort(PortState(movable),QPointF(boundingRect().left() + boundingRect().width() * dX, boundingRect().top()+boundingRect().height() *dY),QUuid::createUuid().toString(),HandleType(portType),PortPos(portLocate),dX,dY);
}
}
}
void GraphicsBaseItem::addDynamicText(QString tag,QString para)
{
int ntagId = -1;
for(ntagId = H_textCaption+1;ntagId < H_connect;++ntagId) //添加到未占用位置
{
if(!m_vecHanle.contains(ntagId))
break;
}
HandleText* pText = new HandleText(this);
pText->setEditable(false);
pText->setIndex(ntagId);
pText->setTagName(tag);
pText->setType(1);
m_vecHanle.insert(ntagId,pText);
m_mapDynamicText.insert(tag,pText);
rearrangeDynamicText();
}
void GraphicsBaseItem::removeDynamicText(QString tag)
{
for(auto& pText:m_mapDynamicText){
if(pText->getTagName() == tag){
int nIndex = pText->getIndex();
m_vecHanle.remove(nIndex);
auto p = m_mapDynamicText.take(tag);
delete p;
return;
}
}
rearrangeDynamicText();
}
void GraphicsBaseItem::removeAllDynamicText()
{
for(auto iter = m_mapDynamicText.begin();iter != m_mapDynamicText.end();++iter){
int nIndex = iter.value()->getIndex();
m_vecHanle.remove(nIndex);
//auto p = m_mapDynamicText.take(iter.key());
//delete p;
}
qDeleteAll(m_mapDynamicText);
m_mapDynamicText.clear();
}
bool GraphicsBaseItem::hasDynamicText(const QString& tag)
{
for(auto& pText:m_mapDynamicText){
if(pText->getTagName() == tag){
return true;
}
}
return false;
}
void GraphicsBaseItem::setDynamicLayoutRadius(qreal radius)
{
m_layoutRadius = radius;
rearrangeDynamicText();
}
void GraphicsBaseItem::rearrangeDynamicText()
{
int count = m_mapDynamicText.size();
if (count == 0) return;
// 计算左右两侧的项数
int leftCount = (count + 1) / 2; // 左侧稍多
int rightCount = count - leftCount;
qreal itemHeight = 30;
qreal startY = -((qMax(leftCount, rightCount) - 1) * itemHeight) / 2;
int i = 0;
for (auto& item : m_mapDynamicText) {
qreal x, y;
if (i < leftCount) {
// 左侧排列
x = -m_layoutRadius-20; // 左侧偏移多一点
y = startY + i * itemHeight;
} else {
// 右侧排列
x = m_layoutRadius; // 右侧偏移
y = startY + (i - leftCount) * itemHeight;
}
item->setPos(x, y);
++i;
}
}
/********************************基模****************************************/
GraphicsBaseModelItem::GraphicsBaseModelItem(QGraphicsItem *parent)
:GraphicsBaseItem(parent)
{
}
GraphicsBaseModelItem::GraphicsBaseModelItem(const GraphicsBaseModelItem& obj)
:GraphicsBaseItem(obj)
{
}
GraphicsBaseModelItem::~GraphicsBaseModelItem()
{
}
GraphicsBaseModelItem* GraphicsBaseModelItem::clone() const
{
return new GraphicsBaseModelItem(*this);
}
void GraphicsBaseModelItem::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget)
{
if(_stateMask){
if(getProperty()->modelName().isEmpty())
{
painter->setPen(QColor(255,0,0,80));
painter->setBrush(QColor(255,0,0,80));
painter->drawRoundedRect(m_boundingRect,10,10);
}
}
}
QVariant GraphicsBaseModelItem::itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant& value)
{
if (change == QGraphicsItem::ItemSelectedHasChanged)
{
setHandleVisible(value.toBool());
}
return QGraphicsItem::itemChange(change, value);
}
/********************************基模组*************************************/
GraphicsBaseModelGroup::GraphicsBaseModelGroup(QGraphicsItem *parent)
:GraphicsBaseModelItem(parent)
{
}
GraphicsBaseModelGroup::GraphicsBaseModelGroup(const GraphicsBaseModelGroup& obj)
:GraphicsBaseModelItem(obj)
{
_layout = obj._layout;
}
GraphicsBaseModelGroup::~GraphicsBaseModelGroup()
{
}
GraphicsBaseModelGroup* GraphicsBaseModelGroup::clone() const
{
return new GraphicsBaseModelGroup(*this);
}
void GraphicsBaseModelGroup::addItem(GraphicsBaseModelItem* item)
{
item->setParentItem(this); // 关键:设置父项
m_childItems.append(item);
updateLayout();
}
QRectF GraphicsBaseModelGroup::boundingRect() const
{
QRectF rect;
for (auto* child : childItems()) {
rect |= child->boundingRect().translated(child->pos());
}
return rect;
}
void GraphicsBaseModelGroup::updateLayout()
{
if(_layout == 0){ //横
}
else{ //纵
}
}
/********************************工程模**************************************/
GraphicsProjectModelItem::GraphicsProjectModelItem(QGraphicsItem *parent)
:GraphicsBaseItem(parent)
{
_lastPort = -1;
//初始化缩放操作用的handle
//m_vecHanle.reserve(H_left);
for(int i = H_leftTop; i <= H_left; i++)
{
ItemControlHandle* pHandle = new HandleRect(this);
pHandle->setType(T_resize);
pHandle->setTag(i);
m_vecHanle.insert(i-1,pHandle);
}
for(int i = H_rotate_leftTop; i <= H_rotate_leftBottom; i++)
{
ItemControlHandle* pHandle = new HandleRect(this);
pHandle->setType(T_rotate);
pHandle->setTag(i);
m_vecHanle.insert(i-1,pHandle);
}
HandleText* pHandle = new HandleText(this);
pHandle->setType(T_text);
pHandle->setTag(H_textCaption);
//pHandle->setText(QString("uname"));
pHandle->setPos(30,-30);
pHandle->setParent(this);
m_vecHanle.insert(H_textCaption,pHandle);
connect(pHandle,&HandleText::editFinish,this,&GraphicsProjectModelItem::onEditNameFinish);
/*HandleText* pCurrent = new HandleText(this); //电流
pCurrent->setEditable(false);
pCurrent->setType(T_text);
pCurrent->setTag(H_textCurrent);
pCurrent->setText(QString("I:"));
pCurrent->setPos(-30,-30);
pCurrent->setParent(this);
m_vecHanle.insert(H_textCurrent,pCurrent);
HandleText* pVoltage = new HandleText(this); //电压
pVoltage->setType(T_text);
pVoltage->setTag(h_textVoltage);
pVoltage->setText(QString("V:"));
pVoltage->setPos(-30,30);
pVoltage->setParent(this);
m_vecHanle.insert(h_textVoltage,pVoltage);*/
setFlag(QGraphicsItem::ItemIsMovable, true);
setFlag(QGraphicsItem::ItemIsSelectable, true);
setFlag(QGraphicsItem::ItemSendsGeometryChanges, true);
_curMonitorState = monitorItemState::Normal;
_curMonitorStateEnable = false;
}
GraphicsProjectModelItem::GraphicsProjectModelItem(const GraphicsProjectModelItem& obj)
:GraphicsBaseItem(obj)
{
_lastPort = -1;
//初始化缩放操作用的handle
//m_vecHanle.reserve(H_left);
for(int i = H_leftTop; i <= H_left; i++)
{
ItemControlHandle* pHandle = new HandleRect(this);
pHandle->setType(T_resize);
pHandle->setTag(i);
m_vecHanle.insert(i-1,pHandle);
}
for(int i = H_rotate_leftTop; i <= H_rotate_leftBottom; i++)
{
ItemControlHandle* pHandle = new HandleRect(this);
pHandle->setType(T_rotate);
pHandle->setTag(i);
m_vecHanle.insert(i-1,pHandle);
}
HandleText* pHandle = new HandleText(this);
pHandle->setType(T_text);
pHandle->setTag(H_textCaption);
pHandle->setPos(30,-30);
pHandle->setParent(this);
m_vecHanle.insert(H_textCaption,pHandle);
m_state = obj.m_state;
m_beginConnectPoint = obj.m_beginConnectPoint;
m_endConnectPoint = obj.m_endConnectPoint;
_modelName = obj._modelName;
setFlag(QGraphicsItem::ItemIsMovable, true);
setFlag(QGraphicsItem::ItemIsSelectable, true);
setFlag(QGraphicsItem::ItemSendsGeometryChanges, true);
setPos(obj.pos());
setRotation(obj.rotation());
_curMonitorState = monitorItemState::Normal;
_curMonitorStateEnable = false;
}
GraphicsProjectModelItem::~GraphicsProjectModelItem()
{
}
GraphicsProjectModelItem* GraphicsProjectModelItem::clone() const
{
return new GraphicsProjectModelItem(*this);
}
void GraphicsProjectModelItem::createOperationCopy()
{
m_pOperationCopy = new QGraphicsPathItem(this->shape());
m_pOperationCopy->setPen(Qt::DashLine);
m_pOperationCopy->setPos(this->pos());
m_pOperationCopy->setTransformOriginPoint(this->transformOriginPoint());
m_pOperationCopy->setTransform(this->transform());
m_pOperationCopy->setRotation(this->rotation());
m_pOperationCopy->setScale(this->scale());
m_pOperationCopy->setZValue(this->zValue());
QGraphicsScene* scene = this->scene();
if(scene && m_pOperationCopy)
{
scene->addItem(m_pOperationCopy);
m_movingIniPos = this->pos();
}
}
void GraphicsProjectModelItem::removeOperationCopy()
{
QGraphicsScene* scene = this->scene();
if(scene && m_pOperationCopy)
{
if(this->pos() != m_pOperationCopy->pos())
this->setPos(m_pOperationCopy->pos()); //本体移动到副本的位置
if(this->rotation() != m_pOperationCopy->rotation())
this->setRotation(m_pOperationCopy->rotation()); //本体旋转至副本的角度
scene->removeItem(m_pOperationCopy);
delete m_pOperationCopy;
m_pOperationCopy = nullptr;
}
}
void GraphicsProjectModelItem::moveOperationCopy(const QPointF& distance)
{
if(m_pOperationCopy)
m_pOperationCopy->setPos(m_movingIniPos + distance);
}
void GraphicsProjectModelItem::rotateOperationCopy(const double& dAngle)
{
if(m_pOperationCopy)
m_pOperationCopy->setRotation(dAngle);
}
void GraphicsProjectModelItem::syncRotationDataFromParent(const double& data)
{
//m_dSyncRotationByParent = rotation() + data;
m_dSyncRotationByParent += data;
//让角度保持在正负180的区间也就是上下两个半圈这样易于象限判断
if (m_dSyncRotationByParent > 180)
m_dSyncRotationByParent -= 360;
if (m_dSyncRotationByParent < -180)
m_dSyncRotationByParent += 360;
}
QVariant GraphicsProjectModelItem::itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant& value)
{
if (change == QGraphicsItem::ItemSelectedHasChanged)
{
QGraphicsItemGroup *group = dynamic_cast<QGraphicsItemGroup *>(parentItem());
if(!group)
setHandleVisible(value.toBool());
//setFunctionHandleVisible(false);
else //在某一组群中,由组群展示是否选中,自身不做展示
{
setSelected(false);
return QVariant::fromValue<bool>(false);
}
}
return QGraphicsItem::itemChange(change, value);
}
void GraphicsProjectModelItem::contextMenuEvent(QGraphicsSceneContextMenuEvent* event)
{
Q_UNUSED(event);
}
void GraphicsProjectModelItem::paint(QPainter *painter,const QStyleOptionGraphicsItem *option, QWidget *widget)
{
Q_UNUSED(painter);
Q_UNUSED(option);
Q_UNUSED(widget);
}
void GraphicsProjectModelItem::setLabelTag(const QString& name)
{
m_vecHanle[H_textCaption]->setText(name);
}
QString GraphicsProjectModelItem::getLabelTag() const
{
return m_vecHanle[H_textCaption]->getText();
}
void GraphicsProjectModelItem::setLabelCurrent(const QString& str)
{
m_vecHanle[H_textCurrent]->setText(str);
}
QString GraphicsProjectModelItem::getLabelCurrent() const
{
return m_vecHanle[H_textCurrent]->getText();
}
void GraphicsProjectModelItem::setLabelVoltage(const QString& str)
{
m_vecHanle[h_textVoltage]->setText(str);
}
QString GraphicsProjectModelItem::getLabelVoltage() const
{
return m_vecHanle[h_textVoltage]->getText();
}
void GraphicsProjectModelItem::updateByProperty()
{
if(_property)
{
setLabelTag(_property->tag());
}
}
void GraphicsProjectModelItem::unbindProperty()
{
_property = nullptr;
}
void GraphicsProjectModelItem::updateConnectData()
{
QJsonObject obj;
QJsonArray arr;
if(_property)
{
for(auto &ptr:m_mapPort)
{
//if(ptr->connected())
{
QJsonObject port;
port["portId"] = ptr->getId();
//auto pLine = ptr->getConnectPtr();
port["x"] = ptr->pos().x();
port["y"] = ptr->pos().y();
port["locate"] = ptr->portPos();
port["portType"] = ptr->getType();
port["xRatio"] = ptr->getXPercent();
port["yRatio"] = ptr->getYPercent();
arr.push_back(port);
}
}
obj["port"] = arr;
obj["metaModel"] = _property->metaModelName();
obj["subList"] = _property->saveSubToJsonArr();
_property->setContext(obj);
}
}
void GraphicsProjectModelItem::onEditNameFinish(const QString& str)
{
emit ifExist(m_itemId,str,m_Itemtype,this);
}
void GraphicsProjectModelItem::updateTerPos()
{
for(auto &pPort:m_mapPort){
double dX = pPort->getXPercent();
double dY = pPort->getYPercent();
QPointF pos(boundingRect().left() + boundingRect().width() * dX, boundingRect().top()+boundingRect().height() *dY);
pPort->setPos(pos);
}
}
/********************************工程模组*************************************/
GraphicsProjectModelGroup::GraphicsProjectModelGroup(QGraphicsItem *parent)
:GraphicsProjectModelItem(parent)
{
}
GraphicsProjectModelGroup::GraphicsProjectModelGroup(const GraphicsProjectModelGroup& obj)
:GraphicsProjectModelItem(obj)
{
m_direction = obj.m_direction;
m_spacing = obj.m_spacing;
_groupType = obj.m_spacing;
for(auto &pItem:obj.m_childItems){
auto newItem = pItem->clone();
m_childItems.append(newItem);
}
}
GraphicsProjectModelGroup::~GraphicsProjectModelGroup()
{
}
GraphicsProjectModelGroup* GraphicsProjectModelGroup::clone() const
{
return new GraphicsProjectModelGroup(*this);
}
void GraphicsProjectModelGroup::addItem(GraphicsProjectModelItem* item)
{
item->setParentItem(this); // 关键:设置父项
m_childItems.append(item);
updateLayout();
}
/*QRectF GraphicsProjectModelGroup::boundingRect() const
{
}*/
QRectF GraphicsProjectModelGroup::updateBoundRect()
{
QRectF rect;
if(m_childItems.size()){
for (auto* child : m_childItems) {
rect |= child->boundingRect().translated(child->pos());
}
m_boundingRect = rect;
}
else
{
return m_boundingRect;
}
updateHandles();
//qDebug()<<rect;
return rect;
}
void GraphicsProjectModelGroup::updateLayout()
{
if (m_childItems.isEmpty()) return;
// 计算所有子项的总尺寸
qreal totalSize = 0;
QList<qreal> childSizes;
for (GraphicsBaseItem *child : m_childItems) {
QRectF childRect = child->boundingRect();
qreal size = (m_direction == 0) ? childRect.width() : childRect.height();
childSizes.append(size);
totalSize += size;
}
// 计算总间距
qreal totalSpacing = m_spacing * (m_childItems.size() - 1);
// 计算起始位置(相对于父项中心)
qreal startPos = -(totalSize + totalSpacing) / 2;
// 定位每个子项
qreal currentPos = startPos;
for (int i = 0; i < m_childItems.size(); ++i) {
GraphicsBaseItem *child = m_childItems[i];
QRectF childRect = child->boundingRect();
if (m_direction == 0) {
// 水平布局x坐标变化y坐标保持中心对齐
child->setPos(currentPos, -childRect.height() / 2);
currentPos += childSizes[i] + m_spacing;
} else {
// 垂直布局y坐标变化x坐标保持中心对齐
child->setPos(-childRect.width() / 2, currentPos);
currentPos += childSizes[i] + m_spacing;
}
}
updateBoundRect();
}