#include "graphicsItem/graphicsBaseItem.h" #include "graphicsItem/handleRect.h" #include "graphicsItem/handleText.h" #include "graphicsItem/itemPort.h" #include "baseProperty.h" #include "dataBase.h" #include #include #include GraphicsBaseItem::GraphicsBaseItem(QGraphicsItem *parent) : AbstractShapeType(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(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 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(parentItem()); if(!group) setHandleVisible(value.toBool()); //setFunctionHandleVisible(false); else //在某一组群中,由组群展示是否选中,自身不做展示 { setSelected(false); return QVariant::fromValue(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()< 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(); }