#include "graphicsDataModel/fixedPortsModel.h" #include "graphicsItem/graphicsBaseItem.h" #include "graphicsItem/electricSvgItemBus.h" #include "graphicsItem/electricSvgItemRect.h" #include "graphicsItem/electricSvgItemTriangle.h" #include "graphicsItem/electricConnectLineItem.h" #include "graphicsItem/itemPort.h" #include "designerScene.h" #include "dataBase.h" #include "httpInterface.h" #include "drawingPanel.h" #include "itemPropertyDlg.h" #include "dataManager.h" #include "powerEntity.h" #include "topologyManager.h" #include "basePropertyManager.h" #include #include #include "baseProperty.h" bool FixedPortsModel::_dataInitialised = false; FixedPortsModel::FixedPortsModel(PowerEntity* pEntity) :_scene(nullptr) ,_widget(nullptr) ,_Interface(nullptr) ,_pEntity(pEntity) { loadNodeDataFromDataBase(); _Interface = new HttpInterface(this); _timer = new QTimer(this); _modelStateInfo = DataManager::instance().modelState(); _modelDataInfo = DataManager::instance().modelData(); initialPropertyDlg(); connect(_timer,SIGNAL(timeout()),this,SLOT(onTimeOut())); connect(_Interface,&HttpInterface::sendPointData,this,&FixedPortsModel::onSignal_GetPointData); } FixedPortsModel::~FixedPortsModel() { } QMap FixedPortsModel::allNodePos() const { QMap map; for(auto pItem:_nodeItem) { if(pItem->getItemType() != GIT_link) map.insert(pItem->itemId(),pItem->pos()); } return map; } QVector FixedPortsModel::allConnections() { QVector vec; for(auto pItem:_nodeItem) { if(pItem->getItemType() == GIT_link) { auto pLine = dynamic_cast(pItem); if(pLine) { vec.push_back(pLine->getConnection()); } } } return vec; } QMap& FixedPortsModel::allItems() { return _nodeItem; } bool FixedPortsModel::addNodeItem(QUuid uuid,GraphicsBaseItem* pItem) { if(_nodeItem.contains(uuid)) return false; else { _nodeItem.insert(uuid,pItem); connect(pItem,&GraphicsBaseItem::ifExist,this,&FixedPortsModel::onSignal_ifExits); return true; } } void FixedPortsModel::addNodeItem(QUuid id/*,int type*/,QPointF pos) { //todo:load图形时必有拓扑实体,关联到对应的entity BaseProperty* pro = nullptr; GraphicsBaseItem* item = nullptr; QMap mapData = BasePropertyManager::instance().getEntityData(); //加载的图形必定关联component(todo:完善判断条件,如判断拓扑节点) if(mapData.contains(id)) { pro = mapData[id]; if(pro) { int type = pro->type(); if(type == GIT_itemTri) { item = new ElectricSvgItemTriangle(QRect(-15, -15, 30, 30)); item->setItemType(GIT_itemTri); } else if(type == GIT_itemRect) { item = new ElectricSvgItemRect(QRect(-15, -15, 30, 30),false); item->setItemType(GIT_itemRect); QJsonArray portArr = pro->context()["port"].toArray(); for(QJsonValueRef portJson:portArr) { QJsonObject portObj = portJson.toObject(); QString portId = portObj["portId"].toString(); int x = portObj["x"].toInt(); int y = portObj["y"].toInt(); HandleType tye = HandleType(portObj["portType"].toInt()); PortPos locate = PortPos(portObj["locate"].toInt()); item->addPort(P_const,QPointF(x,y),portId,tye,locate); } } else if(type == GIT_bus) { item = new ElectricSvgItemBus(QRect(-100, -3, 200, 6)); item->setItemType(GIT_bus); QJsonArray portArr = pro->context()["port"].toArray(); for(QJsonValueRef portJson:portArr) { QJsonObject portObj = portJson.toObject(); QString portId = portObj["portId"].toString(); int x = portObj["x"].toInt(); int y = portObj["y"].toInt(); item->addPort(p_movable,QPointF(x,y),portId); } } if(item) { item->setItemId(id); item->editShape(0, pos); item->setPos(pos); //item->setSelected(true); _scene->addItem(item); item->addPoint(pos); item->setProperty(pro); //绑定模型 item->updateByProperty(); //使用模型更新自身 item->setModelName(pro->modelName()); _nodeItem.insert(id,item); connect(item,&GraphicsBaseItem::ifExist,this,&FixedPortsModel::onSignal_ifExits); } } } } BaseProperty* FixedPortsModel::addNodeData(QUuid id,int type,QString name,QString modelName) { BaseProperty* pData = BasePropertyManager::instance().findEntityData(id); //已存在不不创建 if(pData != nullptr) return pData; VariableProperty* item = new VariableProperty(this); //todo:关联到对应data if(item) { item->setUuid(id); item->setModelName(modelName); item->setType(type); item->setTag(name); item->setName(name); BasePropertyManager::instance().insertEntityData(id,item); } return item; } void FixedPortsModel::loadNodeDataFromDataBase() { if(!_dataInitialised) { QList lst= DataBase::GetInstance()->getAllComponents(); for(auto &info:lst) { BaseProperty* pData = addNodeData(info.uuid,info.type,info.name,info.modelName); pData->setTag(info.tag); pData->setName(info.name); pData->setPath(info.nspath); pData->setDescription(info.description); pData->setInService(info.inService); pData->setState(info.state); pData->setConnectedBus(info.connected_bus); pData->setLabel(info.label); pData->setContext(info.context); pData->setGrid(info.grid); pData->setZone(info.zone); pData->setStation(info.station); pData->setDataChanged(false); PowerEntity* pEntity = TopologyManager::instance().createEntity(EntityType::Component,info.uuid.toString(),info.name); //首先load所有data和entity,全局唯一 if(pEntity){ createTopoTerminalsByData(pEntity,info.context); } } QList lstTopo = DataBase::GetInstance()->getAllTopologics(); for(auto &info:lstTopo) { TopologyManager::instance().createConnection(QString::number(info.id),info.from_pin.toString(),info.to_pin.toString(),info.uuid_from.toString(),info.uuid_to.toString()); } _dataInitialised = true; } else { //for(auto p:_nodeData) { int a = 1; } } } void FixedPortsModel::addConnectLline(QUuid srcId,QUuid destId,QUuid srcPort,QUuid destPort) { GraphicsBaseItem* src = _nodeItem[srcId]; GraphicsBaseItem* dest = _nodeItem[destId]; if(src && dest) { ElectricConnectLineItem* pItem = new ElectricConnectLineItem(); pItem->setItemId(QUuid::createUuid()); pItem->setItemType(GIT_link); _scene->addItem(pItem); ItemPort* ptSrc = src->getPortById(srcPort.toString()); HandleType srcType = ptSrc->getType(); PortPos srcPos = ptSrc->portPos(); pItem->setStartPoint(ptSrc->scenePos()); ptSrc->setConnect(pItem); ItemPort* ptDest = nullptr; ptDest = dest->getPortById(destPort.toString()); pItem->setEndPoint(ptDest->scenePos()); /*if(dest->getItemType() == GIT_bus) //母线动态创建port { ptDest = dest->getPortById(destPort.toString()); pItem->setEndPoint(ptDest->scenePos()); } else { ptDest = dest->getPortById(destPort.toString()); pItem->setEndPoint(ptDest->scenePos()); }*/ if(ptDest != nullptr) { HandleType destType = ptDest->getType(); PortPos destPos = ptDest->portPos(); pItem->calculatePath(); pItem->setConnection(Connection(srcId,srcPort,srcType,srcPos,destId,destPort,destType,destPos)); ptDest->setConnect(pItem); addNodeItem(pItem->itemId(),pItem); } } } void FixedPortsModel::deleteNodeItem(GraphicsBaseItem* pItem) { if(pItem->getItemType() == GIT_link) { auto pLine = dynamic_cast(pItem); if(pLine) { /*Connection con = pLine->getConnection(); GraphicsBaseItem* srcItem = _nodeItem[con.nSrcNodeId]; if(srcItem) { ItemPort* ptSrc = srcItem->getPortPtr(con.nSrcPort); ptSrc->disConnect(); srcItem->setItemChanged(true); //srcItem->updateConnectData(); } GraphicsBaseItem* destItem = _nodeItem[con.nDestNodeId]; if(destItem) { ItemPort* ptDest = pItem->getPortPtr(con.nDestPort); ptDest->disConnect(); destItem->setItemChanged(true); //destItem->updateConnectData(); } QUuid lineId = pLine->itemId(); _nodeItem.take(lineId); _scene->removeItem(pLine); delete pLine;*/ QUuid conId = pLine->itemId(); TopologyManager::instance().removeConnection(conId.toString()); PowerConnection* pCon = TopologyManager::instance().connection(conId.toString()); if(pCon){ PowerEntity* itemFrom = TopologyManager::instance().getEntityByTerminal(pCon->fromTerminalId()); PowerEntity* itemTo = TopologyManager::instance().getEntityByTerminal(pCon->toTerminalId()); if(itemFrom && itemTo) { _nodeItem.value(QUuid(itemFrom->id()))->setItemChanged(true); _nodeItem.value(QUuid(itemTo->id()))->setItemChanged(true); } } _nodeItem.take(conId); _scene->removeItem(pLine); delete pLine; } } else { /*QMap ports = pItem->getPorts(); for(auto port:ports) { if(port->connected()) { ElectricConnectLineItem* pLine = port->getConnectPtr(); Connection con = pLine->getConnection(); QUuid oppositeId = pLine->getOppositeId(pItem->itemId()); int oppositePort = (con.nSrcNodeId==pItem->itemId())?con.nDestPort:con.nSrcPort; //取另一端点序号 GraphicsBaseItem* oppositeItem = _nodeItem[oppositeId]; if(oppositeItem) { ItemPort* ptOppo = oppositeItem->getPortPtr(oppositePort); ptOppo->disConnect(); oppositeItem->setItemChanged(true); } QUuid lineId = pLine->itemId(); _nodeItem.take(lineId); _scene->removeItem(pLine); delete pLine; port->disConnect(); } }*/ QUuid srcId = pItem->itemId(); QList lstCon = TopologyManager::instance().getConnectionsFor(srcId.toString()); for(auto &con:lstCon) { PowerEntity* pFrom = TopologyManager::instance().getEntityByTerminal(con->fromTerminalId()); PowerEntity* pTo = TopologyManager::instance().getEntityByTerminal(con->toTerminalId()); if(pFrom && pTo) { if(srcId.toString() == pFrom->id()) //对象是srcItem _nodeItem.value(QUuid(pTo->id()))->setItemChanged(true); else //对象是toItem _nodeItem.value(QUuid(pFrom->id()))->setItemChanged(true); } //TopologyManager::instance().removeConnection(con->id()); //删除entity时会同时删除相关连接,无需手动删除 } TopologyManager::instance().deleteEntity(srcId.toString()); pItem->setItemChanged(true); _nodeItem.take(srcId); _scene->removeItem(pItem); delete pItem; } } QVariant FixedPortsModel::nodeData(QUuid nodeId, NodeRole role) const { QVariant result; switch(role) { case NodeRole::Position: result = _nodeItem[nodeId]->pos(); break; } /*auto it = _models.find(nodeId); if (it == _models.end()) return result; auto &model = *it; switch (role) { case NodeRole::Type: result = model->name(); break; case NodeRole::Position: result = _nodeGeometryData[nodeId].pos; break; case NodeRole::Size: result = _nodeGeometryData[nodeId].size; break; case NodeRole::CaptionVisible: result = model->captionVisible(); break; case NodeRole::Caption: result = model->caption(); break; case NodeRole::Style: { //auto style = StyleCollection::nodeStyle(); //result = style.toJson().toVariantMap(); } break; case NodeRole::InternalData: { QJsonObject nodeJson; //nodeJson["internal-data"] = _models[nodeId]->save(); result = nodeJson.toVariantMap(); break; } case NodeRole::InPortCount: result = model->nPorts(PortType::In); break; case NodeRole::OutPortCount: result = model->nPorts(PortType::Out); break; case NodeRole::Widget: { auto w = model->embeddedWidget(); result = QVariant::fromValue(w); } break; }*/ return result; } /*QJsonObject FixedPortsModel::saveNode(QUuid const nodeId) const { QJsonObject nodeJson; nodeJson["id"] = nodeId.toString(); nodeJson["type"] = _nodeItem[nodeId]->getItemType(); { QPointF const pos = nodeData(nodeId, NodeRole::Position).value(); QJsonObject posJson; posJson["x"] = pos.x(); posJson["y"] = pos.y(); nodeJson["position"] = posJson; } return nodeJson; }*/ void FixedPortsModel::saveNode(int nPageId) { QMap mapData = BasePropertyManager::instance().getEntityData(); for(auto &pData:mapData) { if(pData->prepareDelete()) { DataBase::GetInstance()->deleteComponent(pData->uuid().toString()); continue; } if(pData->dataChanged()) { bool exist = DataBase::GetInstance()->componentExist(pData->uuid().toString()); VariableProperty* pVariable = dynamic_cast(pData); if(pVariable) { modelDataInfo dataInfo = pVariable->getPropertyValue(); if(exist) //已存在更新 { DataBase::GetInstance()->updateComponent(pData->uuid(),pData->tag(),pData->name(),pData->context()); for(auto &val:dataInfo.groupInfo) { DataBase::GetInstance()->updateDynamicProperty(pData->uuid(),val); } } else { DataBase::GetInstance()->insertComponent(pData->uuid(),pData->modelName(),pData->path(),pData->tag(),pData->name(),pData->description(),pData->grid(),pData->zone(),pData->station(),pData->type(),true,pData->state(),pData->status(),pData->connectedBus(),pData->label(),pData->context(),1); for(auto &val:dataInfo.groupInfo) { DataBase::GetInstance()->insertDynamicProperty(pData->uuid(),val); } } } } } //todo:增加判断,只在设置模式保存连接关系 QVector vecCon = allConnections(); //保存当前页面中的连接关系 for(auto &con:vecCon) { QString fromPin = con.nSrcPortId.toString(); QString toPin = con.nDestPortId.toString(); PowerConnection* pCon = TopologyManager::instance().connection(fromPin,toPin); if(pCon) { DataState state = pCon->state(); switch (state) { case DataState::unchanged: break; case DataState::prepareDelete: DataBase::GetInstance()->deleteTopologic(con.nSrcPortId,con.nDestPortId); TopologyManager::instance().removeConnection(pCon->id()); break; case DataState::changed: DataBase::GetInstance()->insertTopologic(con.nSrcNodeId,con.nDestNodeId,con.nSrcPortId,con.nDestPortId,0,"",0); break; default: break; } } } } void FixedPortsModel::onSignal_ifExits(QUuid id,const QString& str,int type,GraphicsBaseItem* pitem) { bool exist = false; BaseProperty* pData = nullptr; QMap mapData = BasePropertyManager::instance().getEntityData(); for(auto pro:mapData) { if(pro->tag() == str) { pData = pro; exist = true; break; } } if(exist) //已存在,将发出信号的item绑定到此data { if(_nodeItem.contains(id)) //发出信号对象id与data对象id相同,已绑定,不做响应 return; QMessageBox msgBox; msgBox.setText(QString::fromWCharArray(L"提示")); msgBox.setInformativeText(QString::fromWCharArray(L"此名称对象已存在,是否使用该对象?")); msgBox.setStandardButtons(QMessageBox::Ok | QMessageBox::Cancel); msgBox.setDefaultButton(QMessageBox::Cancel); int ret = msgBox.exec(); switch (ret) { case QMessageBox::Ok: { //todo:断开原来的连接关系 pitem->setProperty(pData); pitem->setItemId(pData->uuid()); PowerEntity* pEntity = TopologyManager::instance().findEntity(pData->uuid().toString()); if(pEntity){ pitem->setEntity(pEntity); //item对象的逻辑接线点无需重复创建 } _nodeItem.take(id); _nodeItem.insert(pData->uuid(),pitem); } break; case QMessageBox::Cancel: // Cancel was clicked break; default: // should never be reached break; } } else //创建新data并绑定 { BaseProperty* pData = addNodeData(id,type,str,pitem->getModelName()); if(pData) { pitem->setProperty(pData); pData->setDataChanged(true); //数据状态改变 } PowerEntity* pEntity = TopologyManager::instance().createEntity(EntityType::Component,id.toString(),str); if(pEntity) pitem->setEntity(pEntity); createTopoTerminalsByItem(pitem); //创建item对象的逻辑接线点 } } void FixedPortsModel::onTimeOut() { _Interface->getPointData("i"); _Interface->getPointData("v"); } void FixedPortsModel::onSignal_GetPointData(QString type,QMap map) { if(map.size() == 1) //实时数据 { double d = map.first(); //for(auto pro:_nodeData) //demo版本只有一个数据 { //int t = pro->type(); //if(t == GIT_itemRect) { //todo:根据id匹配数据 /*auto p = dynamic_cast(pro); if(p) { p->notifyUpdate(); //通知更新 }*/ } } } } void FixedPortsModel::startHttpRequest() { if(_timer) { _timer->setInterval(1000); _timer->start(); } } QWidget* FixedPortsModel::getTopWidget() { return dynamic_cast(_widget); } QPointF FixedPortsModel::getTerminalPos(const QString& sTerminalId) { PowerEntity* pParent = TopologyManager::instance().getEntityByTerminal(sTerminalId); if(pParent) { for(auto &item:_nodeItem) { if(pParent->id() == item->itemId().toString()) //找到terminal父图元 { for(auto &pPort:item->getPorts()) { if(pPort->getId() == sTerminalId) { return pPort->scenePos(); } } } } } return QPointF(0,0); } ElectricConnectLineItem* FixedPortsModel::getLineItemById(const QString& terminalId) { for(auto iter:_nodeItem) //获取id所在的lineitem { auto item = dynamic_cast(iter); if(item) { if(item->getItemType() == GIT_link) { PowerConnection* pCon = TopologyManager::instance().getConnectionContainsTerminal(terminalId); if(pCon) { if(item->itemId().toString() == pCon->id()) return dynamic_cast(item); } } } } return nullptr; } void FixedPortsModel::showModelDlg(const QString& sName,QUuid uuid,GraphicsBaseItem* pItem) { modelStateInfo stateInfo = _modelStateInfo[sName]; ModelDataMap mapData = DataManager::instance().modelData(); ItemPropertyDlg* pDlg = dynamic_cast(stateInfo._PropertyDlg); if(pDlg) { pDlg->showDlg(mapData[sName],uuid,pItem); } else qDebug()<<"showModelDlg err"; } void FixedPortsModel::initialPropertyDlg() { for(auto &modelInfo:_modelStateInfo) { if(modelInfo._PropertyDlg == NULL) { generatePropertyDlg(modelInfo.modelName); } } } void FixedPortsModel::generatePropertyDlg(const QString& sModel) { modelStateInfo info = _modelStateInfo[sModel]; if(info._PropertyDlg == NULL) { ItemPropertyDlg* dlg = new ItemPropertyDlg(_widget); if(dlg) { dlg->loadGroupButton(info.groupInfo); _modelStateInfo[sModel]._PropertyDlg = dlg; } } } ConfigurationDiagram* FixedPortsModel::getTopologyDiagram() { return dynamic_cast(_pEntity); } void FixedPortsModel::createTopoTerminalsByItem(GraphicsBaseItem* pItem) { PowerEntity* pEntity = pItem->entity(); if(pEntity) { QMap mapPorts = pItem->getPorts(); //创建实体port对应的拓扑port for(auto &port:mapPorts) { TerminalType terType; HandleType tpe = port->getType(); switch (tpe) { case T_lineIn: terType = TerminalType::PowerInput; break; case T_lineOut: terType = TerminalType::PowerOutput; break; case T_lineInOut: terType = TerminalType::PowerConnect; break; default: break; } TopologyManager::instance().createTerminal(pEntity->id(),terType,"",port->pos(),port->getId()); } } } void FixedPortsModel::createTopoTerminalsByData(PowerEntity* pParent,QJsonObject componentCon) { QJsonArray portsArray = componentCon["port"].toArray(); for (QJsonValueRef portJson : portsArray) //每个属性的状态信息 { QJsonObject node = portJson.toObject(); QString portId = node["portId"].toString(); int x = node["x"].toInt(); int y = node["y"].toInt(); PortPos locate = PortPos(node["locate"].toInt()); HandleType portType = HandleType(node["portType"].toInt()); TerminalType terType; switch (portType) { case T_lineIn: terType = TerminalType::PowerInput; break; case T_lineOut: terType = TerminalType::PowerOutput; break; case T_lineInOut: terType = TerminalType::PowerConnect; break; default: break; } TopologyManager::instance().createTerminal(pParent->id(),terType,"",QPointF(x,y),portId); } } bool FixedPortsModel::isItemValid(GraphicsBaseItem* pItem) { BaseProperty* pData = pItem->getProperty(); PowerEntity* pEntity = pItem->entity(); return (pData != nullptr && pEntity != nullptr)?true:false; }