1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035 |
- #include "WindowAppPouScene.h"
- #include "WindowAppPouFrame.h"
- #include "ToolDepository.h"
- #include "WindowAppBlockPort.h"
- #include "WindowAppBlockStandard.h"
- #include "WindowAppBlockGoto.h"
- #include "WindowAppItemLink.h"
- #include "PouManager.h"
- #include "WindowAppItemInterface.h"
- #include "WindowAppBlockComment.h"
- #include "WindowAppBlockParallel.h"
- #include "WindowAppBlockForloop.h"
- #include "WindowAppBlockWait.h"
- #include "WindowAppTaskView.h"
- #include "TaskManager.h"
- extern ToolDepository toolDepository;
- WindowAppPouScene::WindowAppPouScene(
- const QString& strTitle,
- QObject* parent,
- QWidget* parentparent
- )
- : QGraphicsScene(parent)
- // 2022-1-8 保存PouFrame的指针
- , m_pPouFrame((WindowAppPouFrame*)parentparent)
- {
- m_sceneMode = SCENE_MODE::NORMAL_MODE;
- m_tmpLinkLine = nullptr;
- m_strPouName = strTitle;
- // 完成Pou的初始化动作
- m_Pou.init(strTitle, this);
- // 如果本Group是硬件Group的话,则绑定硬件的Pou
- if (strTitle == GROUP_NAME_HARDWARE)
- {
- g_pPouManager->registerHdwPou(&m_Pou);
- }
- //else
- //{
- // 在全局信息数据中注册本Pou
- g_pPouManager->registerPou(&m_Pou);
- // }
- //// 保存当前的Pou数据结构信息
- //Pou.insert(m_strTitle, &m_Pou);
- // 初始化步长值为 1
- m_nMoveBlockSleep = 1;
- }
- /// <summary>
- /// 生成新的运行时工具信息,并添加到界面中
- /// </summary>
- /// <param name="pNewTool"></param>
- /// <param name="pos"></param>
- WindowAppBlockBase* WindowAppPouScene::addToolItem(const STATIC_TOOL* pNewTool, QPointF pos)
- {
- //// 2022-3-13 增加,如果是注释工具的话,则专门进行注释工具的添加流程
- //if (pNewTool->Type == TOOL_TYPE::TOOL_TYPE_COMMENT)
- //{
- // this->addNewCommentItem(pNewTool, pos);
- // return;
- //}
- WindowAppBlockBase* pNewBlock = nullptr;
- // 如果不是注释工具的话,则需要执行如下判断
- if (pNewTool->Type != TOOL_TYPE::TOOL_TYPE_COMMENT)
- {
- // 2021-8-14 增加,如果本Pou正在Task的执行过程中,则不允许添加
- if (m_Pou.isRunningInTask())
- {
- Utility::VPCriticalMessageBox(
- "Can not add Tool[" + pNewTool->strName + "], Reason: this pou is running in Task[" + m_Pou.m_pParentTask->strName + "].");
- return nullptr;
- }
- // 2021-8-19 增加,如果本页面是硬件页面,那么只允许硬件的工具拖进来
- if (this->m_strPouName == GROUP_NAME_HARDWARE
- && pNewTool->strCategory != CATEGORY_TOOL_HARDWARE)
- {
- Utility::VPCriticalMessageBox("Only hardware tools could be added in this page!");
- return nullptr;
- }
- }
-
- // 检查通过后开始建立工具
- TOOL* toolRunning = new TOOL(pNewTool);
- // 2021-7-4增加,保存组名
- toolRunning->strPouName = m_strPouName;
- // 生成新的运行时工具信息
- // 标准工具
- if (pNewTool->isStandardTool())
- {
- pNewBlock = this->addStandardItem(toolRunning, pos);
- }
- // Port工具
- else if (pNewTool->isPortTool())
- {
- pNewBlock = this->addPortItem(toolRunning, pos);
- }
- // Goto工具
- else if (pNewTool->isGotoTool())
- {
- pNewBlock = this->addGotoItem(toolRunning, pos);
- }
- // Comment工具
- else if (pNewTool->isCommentTool())
- {
- pNewBlock = this->addCommentItem(toolRunning, pos);
- }
- // Parallel工具
- else if (pNewTool->isParallelTool())
- {
- pNewBlock = this->addParallelItem(toolRunning, pos);
- }
- // ForLoop工具
- else if (pNewTool->isForloopTool())
- {
- pNewBlock = this->addForloopItem(toolRunning, pos);
- }
- // Wait工具
- else if (pNewTool->isWaitTool())
- {
- pNewBlock = this->addWaitItem(toolRunning, pos);
- }
- else
- {
- // Error Here
- qDebug() << "[ERROR] WindowAppPouScene::addNewItem - Unknown tool type :" << (int)pNewTool->Type;
- return nullptr;
- }
- vDebug() << "Add Tool[" << toolRunning->strInstanceName << "] in Pou[" << m_strPouName << "].";
- return pNewBlock;
- }
- /// <summary>
- /// 生成新的运行时工具信息(反序列化方式)
- /// </summary>
- /// <param name="pNewTool"></param>
- /// <param name="pos"></param>
- /// <param name="bFromDoc">此参数的含义是是否通过反序列化添加,如果是反序列化进来的,需要跳过一些变量设置</param>
- WindowAppBlockBase* WindowAppPouScene::addToolItem(TOOL* pNewTool, QPointF pos, bool bFromDoc)
- {
- //// 2022-3-13 增加,如果是注释工具的话,则专门进行注释工具的添加流程
- //if (pNewTool->Type == TOOL_TYPE::TOOL_TYPE_COMMENT)
- //{
- // this->addNewCommentItem(pos);
- // return;
- //}
- // 标准工具信息
- if (pNewTool->isStandardTool())
- {
- return this->addStandardItem(pNewTool, pos, bFromDoc);
- }
- // Port工具
- else if (pNewTool->isPortTool())
- {
- return this->addPortItem(pNewTool, pos, bFromDoc);
- }
- // Goto工具
- else if (pNewTool->isGotoTool())
- {
- return this->addGotoItem(pNewTool, pos, bFromDoc);
- }
- // 注释工具
- else if (pNewTool->isCommentTool())
- {
- return this->addCommentItem(pNewTool, pos, bFromDoc);
- }
- // Parallel工具
- else if (pNewTool->isParallelTool())
- {
- return this->addParallelItem(pNewTool, pos, bFromDoc);
- }
- // ForLoop工具
- else if (pNewTool->isForloopTool())
- {
- return this->addForloopItem(pNewTool, pos, bFromDoc);
- }
- // Wait工具
- else if (pNewTool->isWaitTool())
- {
- return this->addWaitItem(pNewTool, pos, bFromDoc);
- }
- else
- {
- // Error Here
- qDebug() << "[ERROR] WindowAppPouScene::addNewItem - Unknown tool type :" << (int)pNewTool->Type;
- return nullptr;
- }
- }
- /// <summary>
- /// 移除一个ToolItem
- /// </summary>
- /// <param name="pBlock"></param>
- void WindowAppPouScene::delToolItem(WindowAppBlockBase* pBlock)
- {
- // 确保指针有效
- if (pBlock == nullptr)
- {
- vDebug() << "[Error] BlockBase is nullptr.";
- return;
- }
- // 检查是否可以被删除
- if (!pBlock->couldBeDeleted())
- {
- return;
- }
- // 2022-10-2,这里只处理去Task和Pou处处理标准工具,跳过其他工具
- // NOTICE:之所以这里会出现这个问题,是因为之前只有StandardBase工具会走这里删除,
- // MEMORY
- if (pBlock->m_toolInfo->isIndexedTool())
- {
- // 2022-3-5增加,如果此工具的Pou被Task选中,需要通知Task删除此工具
- if (m_Pou.isSelByTask())
- {
- WindowAppTaskView* pTaskView = g_pTaskManager->getTaskViewByName(m_Pou.m_pParentTask->strName);
- pTaskView->onDelPouTool(&m_Pou, pBlock->m_toolInfo);
- }
- }
- // 2022-10-2,除了Comment工具,其他的工具都需要到Pou中删除本工具的数据信息
- // 逻辑数据删除
- m_Pou.ToolDelete(pBlock);
- // 从界面中移除此功能块
- this->removeItem(pBlock);
- }
- /// <summary>
- /// 添加一个标准工具
- /// </summary>
- /// <param name="pNewTool"></param>
- /// <param name="pos"></param>
- WindowAppBlockStandard* WindowAppPouScene::addStandardItem(TOOL* pNewTool, QPointF pos, bool bFromDoc)
- {
- // 2022-3-31 如果从序列化中恢复,则不需要重新设置索引和实例名称了
- if (!bFromDoc)
- {
- // 初始化本功能块
- this->initBlockItem(pNewTool, true, true, true);
- // TODO:2022-9-19,如果此处工具从序列化中恢复,要检查工具Event类型的接口是否正常初始化了?一般都会绑定到Task中
- }
- // 加载dll,取得指针
- pNewTool->pDllPtr = toolDepository.GetToolPtr(pNewTool->strName);
- if (pNewTool->pDllPtr == nullptr)
- {
- vDebug() << "[Error] [" << pNewTool->strName << "], but pDllPtr is nullptr ";
- return nullptr;
- }
- // 2022-10-4,保存一下本Dll的全路径信息,供后续查询需要
- pNewTool->pDllPtr->m_strFullPath = toolDepository.GetDllPathByName(pNewTool->strName);
- try
- {
- // 工具初始化(带值初始化 withValue )
- pNewTool->pDllPtr->InitTool(
- (WindowAppPouFrame*)this->parent(),
- m_Pou.pouName(),
- pNewTool->strInstanceName,
- (QObject*)g_pTaskManager
- );
- //QFuture<int> future = QtConcurrent::run(
- // pNewTool->pDllPtr,
- // &DllTool::InitTool,
- // (WindowAppPouFrame*)this->parent(),
- // m_Pou.pouName(),
- // pNewTool->strInstanceName,
- // (QObject*)g_pTaskManager
- // );
- //future.waitForFinished();
- }
- catch (...)
- {
- qWarning() << "[Error] WindowAppPouScene::addStandardItem - " << m_Pou.pouName()
- << " init Tool" << pNewTool->strInstanceName << " failed.";
- }
-
-
- //// 2021-8-5 设置,为dll设置event的传递目标(TaskManager)
- //pNewTool->pDllPtr->setEventTarget((QObject*)g_pTaskManager);
- // 2022-3-3增加,设置GvlManager指针,用于和DB类型的全局变量做交互
- pNewTool->pDllPtr->setGvlTarget((QObject*)g_pGvlManager);
- // 2022-3-10 增加,设置WindowAppPouScene指针,用于同步dll侧发来的动态端口同步消息
- pNewTool->pDllPtr->setPouTarget(this);
- //// 2021-8-3 增加,此处从dll获取刚生成的变量值
- //// (仅限于Hardware类型的Event接口,但是其实也可以不保存在exe中,每次都从dll中拿,两种方案都可以)
- //for (int i = 0; i < pNewTool->Interfaces.size(); i++)
- //{
- // pNewTool->Interfaces[i]->value.Ptr = pNewTool->pDllPtr->Interface(i).value.Ptr;
- //}
- // 根据对应的工具信息绘制对应的功能块
- WindowAppBlockStandard* pNewBlock =
- qgraphicsitem_cast<WindowAppBlockStandard*>(this->createBlock(pNewTool, pos, TOOL_TYPE::TOOL_TYPE_STANDARD));
- return pNewBlock;
- }
- /// <summary>
- /// 添加一个Port工具
- /// </summary>
- /// <param name="pNewTool"></param>
- /// <param name="pos"></param>
- WindowAppBlockPort* WindowAppPouScene::addPortItem(TOOL* pNewPort, QPointF pos, bool bFromDoc)
- {
- // 2022-3-31 如果从序列化中恢复,则不需要重新设置实例名称和接口名称了
- if (!bFromDoc)
- {
- //// 需要根据现有工具情况生成新的实例名字
- //pNewPort->strInstanceName = m_Pou.genToolInstanceName(pNewPort->strName);
- // 初始化本功能块
- this->initBlockItem(pNewPort, false, true, false);
- // 2022-3-23,需要为接口补充上全名,用于在Pou中建立对应关系
- if (pNewPort->Type == TOOL_TYPE::TOOL_TYPE_PORT_INPUT)
- {
- pNewPort->Interfaces[0]->strFullName = pNewPort->strPouName + "."
- + pNewPort->strInstanceName + "."
- + DEFAULT_INPUT_PORT_NAME;
- }
- else if (pNewPort->Type == TOOL_TYPE::TOOL_TYPE_PORT_OUTPUT)
- {
- pNewPort->Interfaces[0]->strFullName = pNewPort->strPouName + "."
- + pNewPort->strInstanceName + "."
- + DEFAULT_OUTPUT_PORT_NAME;
- }
- else
- {
- qDebug() << "WindowAppPouScene::addPortItem - [Error] Invalid toolType of Port[" << pNewPort->strInstanceName << ".";
- }
- }
- // 根据对应的工具信息绘制对应的功能块
- WindowAppBlockPort* pNewBlock =
- qgraphicsitem_cast<WindowAppBlockPort*>(this->createBlock(pNewPort, pos, TOOL_TYPE::TOOL_TYPE_PORT_INPUT));
- return pNewBlock;
- }
- /// <summary>
- /// 添加一个Goto工具
- /// </summary>
- /// <param name="pNewPort"></param>
- /// <param name="pos"></param>
- /// <returns></returns>
- WindowAppBlockGoto* WindowAppPouScene::addGotoItem(TOOL* pNewTool, QPointF pos, bool bFromDoc)
- {
- // 2022-3-31 如果从序列化中恢复,则不需要重新设置索引和实例名称了
- if (!bFromDoc)
- {
- // 初始化本功能块
- this->initBlockItem(pNewTool, true, true, false);
- //// 计算分配的Index
- //pNewTool->nIndex = m_Pou.GetIndexedToolsCount();
- //// 需要根据现有工具情况生成新的实例名字
- //pNewTool->updateInstanceName(m_Pou.genToolInstanceName(pNewTool->strName));
- }
- // 根据对应的工具信息绘制对应的功能块
- WindowAppBlockGoto* pNewBlock =
- qgraphicsitem_cast<WindowAppBlockGoto*>(this->createBlock(pNewTool, pos, TOOL_TYPE::TOOL_TYPE_GOTO));
- return pNewBlock;
- }
- /// <summary>
- /// 添加一个Comment工具
- /// </summary>
- /// <param name="pNewTool"></param>
- /// <param name="pos"></param>
- /// <param name="bFromDoc"></param>
- /// <returns></returns>
- WindowAppBlockComment* WindowAppPouScene::addCommentItem(TOOL* pNewTool, QPointF pos, bool bFromDoc /*= false*/)
- {
- // 2022-3-31 如果从序列化中恢复,则不需要重新设置实例名称了
- if (!bFromDoc)
- {
- // 初始化本功能块
- this->initBlockItem(pNewTool, false, true, false);
- //// 需要根据现有工具情况生成新的实例名字
- //pNewTool->updateInstanceName(m_Pou.genToolInstanceName(pNewTool->strName));
- }
- // 根据对应的工具信息绘制对应的功能块
- WindowAppBlockComment* pNewBlock =
- qgraphicsitem_cast<WindowAppBlockComment*>(this->createBlock(pNewTool, pos, TOOL_TYPE::TOOL_TYPE_COMMENT));
- return pNewBlock;
- }
- /// <summary>
- /// 添加一个Parallel工具
- /// </summary>
- /// <param name="pNewTool"></param>
- /// <param name="pos"></param>
- /// <param name="bFromDoc"></param>
- /// <returns></returns>
- WindowAppBlockParallel* WindowAppPouScene::addParallelItem(TOOL* pNewTool, QPointF pos, bool bFromDoc /*= false*/)
- {
- // 如果从序列化中恢复,则不需要重新设置索引和实例名称了
- if (!bFromDoc)
- {
- // 初始化本功能块
- this->initBlockItem(pNewTool, true, true, true);
- //// 计算分配的Index
- //pNewTool->nIndex = m_Pou.GetIndexedToolsCount();
- //// 需要根据现有工具情况生成新的实例名字
- //pNewTool->updateInstanceName(m_Pou.genToolInstanceName(pNewTool->strName));
- //// 2022-4-27,为Parallel的ToolInterface命名
- //pNewTool->startInterface->strName = pNewTool->strInstanceName;
- //pNewTool->startInterface->strFullName = m_Pou.pouName() + "." + pNewTool->strInstanceName + ".Start";
- //pNewTool->endInterface->strName = pNewTool->strInstanceName;
- //pNewTool->endInterface->strFullName = m_Pou.pouName() + "." + pNewTool->strInstanceName + ".End";
- }
- // 根据对应的工具信息绘制对应的功能块
- WindowAppBlockParallel* pNewBlock =
- qgraphicsitem_cast<WindowAppBlockParallel*>(this->createBlock(pNewTool, pos, TOOL_TYPE::TOOL_TYPE_PARALLEL));
- return pNewBlock;
- }
- /// <summary>
- /// 添加一个ForLoop工具
- /// </summary>
- /// <param name="pNewTool"></param>
- /// <param name="pos"></param>
- /// <param name="bFromDoc"></param>
- /// <returns></returns>
- WindowAppBlockForloop* WindowAppPouScene::addForloopItem(TOOL* pNewTool, QPointF pos, bool bFromDoc /*= false*/)
- {
- // 如果从序列化中恢复,则不需要重新设置索引和实例名称了
- if (!bFromDoc)
- {
- // 初始化本功能块
- this->initBlockItem(pNewTool, true, true, true);
- }
- // 根据对应的工具信息绘制对应的功能块
- WindowAppBlockForloop* pNewBlock =
- qgraphicsitem_cast<WindowAppBlockForloop*>(this->createBlock(pNewTool, pos, TOOL_TYPE::TOOL_TYPE_FORLOOP));
- return pNewBlock;
- }
- /// <summary>
- /// 添加一个Wait工具
- /// </summary>
- /// <param name="pNewTool"></param>
- /// <param name="pos"></param>
- /// <param name="bFromDoc"></param>
- /// <returns></returns>
- WindowAppBlockWait* WindowAppPouScene::addWaitItem(TOOL* pNewTool, QPointF pos, bool bFromDoc /*= false*/)
- {
- // 如果从序列化中恢复,则不需要重新设置索引和实例名称了
- if (!bFromDoc)
- {
- // 初始化本功能块
- this->initBlockItem(pNewTool, true, true, false);
- }
- // 根据对应的工具信息绘制对应的功能块
- WindowAppBlockWait* pNewBlock =
- qgraphicsitem_cast<WindowAppBlockWait*>(this->createBlock(pNewTool, pos, TOOL_TYPE::TOOL_TYPE_WAIT));
- return pNewBlock;
- }
- /// <summary>
- /// 创建功能块
- /// </summary>
- /// <param name="pBlock"></param>
- /// <param name="pTool"></param>
- /// <param name="pos"></param>
- /// <param name="tooType"></param>
- /// <returns></returns>
- WindowAppBlockBase* WindowAppPouScene::createBlock(
- TOOL* pTool,
- const QPointF& pos,
- TOOL_TYPE toolType
- )
- {
- WindowAppBlockBase* newItem = nullptr;
- // 根据种类创建对应的控件
- switch (toolType)
- {
- case TOOL_TYPE::TOOL_TYPE_STANDARD:
- newItem = new WindowAppBlockStandard(pTool, &m_Pou);
- break;
- case TOOL_TYPE::TOOL_TYPE_PORT_INPUT:
- case TOOL_TYPE::TOOL_TYPE_PORT_OUTPUT:
- newItem = new WindowAppBlockPort(pTool, &m_Pou);
- break;
- case TOOL_TYPE::TOOL_TYPE_GOTO:
- newItem = new WindowAppBlockGoto(pTool, &m_Pou);
- break;
- case TOOL_TYPE::TOOL_TYPE_COMMENT:
- newItem = new WindowAppBlockComment(pTool, &m_Pou);
- break;
- case TOOL_TYPE::TOOL_TYPE_PARALLEL:
- newItem = new WindowAppBlockParallel(pTool, &m_Pou);
- break;
- case TOOL_TYPE::TOOL_TYPE_FORLOOP:
- newItem = new WindowAppBlockForloop(pTool, &m_Pou);
- break;
- case TOOL_TYPE::TOOL_TYPE_WAIT:
- newItem = new WindowAppBlockWait(pTool, &m_Pou);
- break;
- default:
- {
- qDebug() << "[Error] WindowAppPouScene::createBlock - Unknown tooltype: " << (short)toolType;
- return nullptr;
- }
- }
- // 根据控件类型的不同绑定不同的消息
- if (toolType != TOOL_TYPE::TOOL_TYPE_COMMENT)
- {
- // 绑定移动信号用于移动功能块时同步移动link连线
- connect(
- newItem,
- &WindowAppBlockBase::blockMoveSignal,
- this,
- &WindowAppPouScene::onBlockMove
- );
- }
- else
- {
- // 绑定信号用于注释控件内容为空时,删除控件
- connect(
- qgraphicsitem_cast<WindowAppBlockComment*>(newItem),
- &WindowAppBlockComment::emptyContent,
- this,
- &WindowAppPouScene::removeEmptyBlockComment
- );
- }
- // 置于最顶层
- newItem->setZValue(Z_ORDER_BLOCK);
- // Scene中添加功能块
- addItem(newItem);
- // 设置位置
- newItem->setPos(pos);
- // 添加功能块接口
- newItem->addItemInterfaces();
- // 将新的工具信息和功能块信息绑定保存
- m_Pou.registerTool(newItem, pTool);
- return newItem;
- }
- /// <summary>
- /// 直接增加一个Port,并且连接
- /// </summary>
- /// <param name="pLinkInf"></param>
- void WindowAppPouScene::addPortAndAutolink(WindowAppItemInterface* pLinkInf, const QLineF infRealLine)
- {
- // 从工具库中获取Port工具原型
- const STATIC_TOOL* portTool = nullptr;
-
- // 根据接口的输入输出获取不同的port工具,并且根据方向计算一下Port应该出现的中心点位置
-
- QPointF posPort;
- posPort.setY(infRealLine.y1() - PBD_BASIC_HEIGHT / 2);
- if (pLinkInf->m_infInfo->Direction == INF_DIRECTION::INF_DIR_OUT)
- {
- portTool = toolDepository.GetInputPort();
- posPort.setX(infRealLine.x2() + PBD_BASIC_WIDTH + AUTOPORT_SPACING + TBD_INF_LINE );
- }
- else
- {
- portTool = toolDepository.GetOutputPort();
- posPort.setX(infRealLine.x1() - PBD_BASIC_WIDTH - AUTOPORT_SPACING - TBD_INF_LINE);
- }
- // 确保工具有效
- if (portTool == nullptr)
- {
- return;
- }
-
- // 确保输入端口没被引用过
- if (pLinkInf->m_infInfo->Direction == INF_DIRECTION::INF_DIR_IN &&
- pLinkInf->m_infInfo->nRefCount > 0 )
- {
- return;
- }
- // 确保输出端口没被引用过 (暂时限制输出多次添加数据端口,以后有必要的时候再放开)
- if (pLinkInf->m_infInfo->Direction == INF_DIRECTION::INF_DIR_OUT &&
- pLinkInf->m_infInfo->nRefCount > 0)
- {
- return;
- }
- // 添加这个port工具
- TOOL* portRunning = new TOOL(portTool);
- // 2021-7-5添加,需要保存所属的Group
- portRunning->strPouName = m_strPouName;
- // 2021-05-26添加,双击添加的Port工具需要根据link的接口指定类型
- portRunning->Interfaces[0]->value.type = pLinkInf->m_infInfo->value.type;
- WindowAppBlockPort* pNewPortItem = this->addPortItem(portRunning, posPort);
- // 并且将两个接口进行连接(输出->输入)
- if (pLinkInf->m_infInfo->Direction == INF_DIRECTION::INF_DIR_OUT)
- {
- addLink(pLinkInf, pNewPortItem->m_itemInterfaces[0]);
- }
- else
- {
- addLink(pNewPortItem->m_itemInterfaces[0], pLinkInf);
- }
- }
- /// <summary>
- /// 鼠标按下时
- /// </summary>
- /// <param name="mouseEvent"></param>
- void WindowAppPouScene::mousePressEvent(QGraphicsSceneMouseEvent* mouseEvent)
- {
- //qDebug() << "WindowAppDiagramScene::mousePressEvent";
- // 如果鼠标按下的位置是接口的话,则切换进入Link模式
- QTransform transform;
-
- // 2022-1-8 测试点击的是接口还是功能块
- WindowAppItemInterface* activeItem = qgraphicsitem_cast<WindowAppItemInterface*>(this->itemAt(mouseEvent->scenePos(), transform));
- WindowAppBlockStandardBase* activeBlock = qgraphicsitem_cast<WindowAppBlockStandardBase*>(this->itemAt(mouseEvent->scenePos(), transform));
-
- // 如果点击的是接口,并且是输出接口的话,那么执行link
- if ( activeItem!=nullptr && activeItem->m_infInfo->Direction== INF_DIRECTION::INF_DIR_OUT )
- {
- // 如果是硬件组态,则不执行Link相关的所有操作(包括批量选中移动后的特殊处理)
- if (m_strPouName == GROUP_NAME_HARDWARE)
- {
- QGraphicsScene::mousePressEvent(mouseEvent);
- return;
- }
- // 开始执行Link动作
- startLink(activeItem, mouseEvent->scenePos());
- // 输出Debug数据
- QString strValue = activeItem->m_infInfo->getValueString();
- DebugData data;
- data.addLog(activeItem->m_infInfo->strName, strValue);
- m_pPouFrame->UpdataDebugData(data);
- }
- // 2022-6-20,增加了对批量功能块移动的处理
- // 只有标准系列的功能块使用
- else if (activeBlock !=nullptr && activeBlock->isStandardBasedBlock())
- {
- // 2022-1-8,如果点击的是标准功能块,则调用UpdataDebugData
- if (activeBlock->type()== ITEM_TYPE_STANDARD)
- {
- // 显示DeBug信息
- try
- {
- DebugData data = m_Pou.GetToolDebugData(activeBlock);
- m_pPouFrame->UpdataDebugData(data);
- }
- catch (...)
- {
- }
- }
- // 如果是硬件组态,则不执行Link相关的所有操作(包括批量选中移动后的特殊处理)
- if (m_strPouName == GROUP_NAME_HARDWARE)
- {
- QGraphicsScene::mousePressEvent(mouseEvent);
- return;
- }
- // 检查是否正在是多选之后的批量移动操作
- this->checkBatchMove();
- }
- QGraphicsScene::mousePressEvent(mouseEvent);
- }
- /// <summary>
- /// 控制功能块的移动以及连线
- /// </summary>
- /// <param name="mouseEvent"></param>
- void WindowAppPouScene::mouseMoveEvent(QGraphicsSceneMouseEvent* mouseEvent)
- {
- // 如果处于Link模式,则实时绘制连线
- if (m_sceneMode == SCENE_MODE::LINK_MODE && m_tmpLinkLine!=nullptr )
- {
- bool blink = false;
- WindowAppItemInterface* startItem = nullptr;
- WindowAppItemInterface* endItem = nullptr;
- // 执行连接预检查 改变鼠标的形态
- int nStrte = preLinkCheck(mouseEvent->scenePos(), startItem, endItem);
- if (nStrte == 0)
- {
- m_pPouFrame->setCursor(Qt::UpArrowCursor);// ok
- // 自定义图标
- //m_pPouView->setCursor(QCursor(QPixmap(":/image/tree_item.png")));
- blink = true;
- }
- else
- {
- m_pPouFrame->setCursor(Qt::ArrowCursor);
- }
- moveLink(mouseEvent->scenePos(), blink);
- }
- // 批量移动模式
- else if(m_sceneMode == SCENE_MODE::BATCHMOVE_MODE)
- {
- // 暂时不需要做什么
- }
- // qDebug() << "WindowAppPouScene::mouseMoveEvent";
- QGraphicsScene::mouseMoveEvent(mouseEvent);
- }
- /// <summary>
- /// 控制功能块的移动以及生成连线
- /// </summary>
- /// <param name="mouseEvent"></param>
- void WindowAppPouScene::mouseReleaseEvent(QGraphicsSceneMouseEvent* mouseEvent)
- {
- //qDebug() << "WindowAppDiagramScene::mouseReleaseEvent";
- // 如果正处于Link模式
- if (m_sceneMode == SCENE_MODE::LINK_MODE)
- {
- // 结束link操作
- endLink(mouseEvent->scenePos());
- }
- // 如果正处于批量移动模式
- else if (m_sceneMode == SCENE_MODE::BATCHMOVE_MODE)
- {
- // 取消所有选中Link的Movable状态
- for (auto& linkItem : m_batchMoveLinks)
- {
- linkItem->setMovable(false);
- }
- // 清空链表
- m_batchMoveLinks.clear();
- }
- // 切换回正常模式
- m_sceneMode = SCENE_MODE::NORMAL_MODE;
- // 恢复鼠标
- m_pPouFrame->setCursor(Qt::ArrowCursor);
- QGraphicsScene::mouseReleaseEvent(mouseEvent);
- }
- /// <summary>
- /// 2022-6-20,检查是否正在是多选之后的批量移动操作
- /// </summary>
- bool WindowAppPouScene::checkBatchMove()
- {
- // 获取当前选中的Item
- QList<QGraphicsItem*> selItems = this->selectedItems();
- QList<WindowAppBlockStandardBase*> selBlocks;
- // 如果选中的
- if (selItems.size() <= 1)
- {
- return false;
- }
- // 取出其中所有的Block
- for (const auto& selItem : selItems)
- {
- WindowAppBlockStandardBase* block = qgraphicsitem_cast<WindowAppBlockStandardBase*>(selItem);
- if (block != nullptr && block->isStandardBasedBlock() )
- {
- selBlocks.push_back(block);
- }
- }
- // 如果选中Block的数量大于2,则说明在做批量拖动
- if (selBlocks.size() >= 2)
- {
- m_sceneMode = SCENE_MODE::BATCHMOVE_MODE;
- qDebug() << "WindowAppPouScene::checkBatchMove() - SCENE_MODE::BATCHMOVE_MODE";
- }
- else
- {
- m_sceneMode = SCENE_MODE::NORMAL_MODE;
- return false;
- }
- // 取出其中每一个功能块之间的Link,将Link状态设置为Movable,可随Block随动
- for (const auto& selBlock : selBlocks)
- {
- for (const auto& selBlock2 : selBlocks)
- {
- if (selBlock2 != selBlock)
- {
- // 判断两个Block之间是否存在Link
- QList<WindowAppItemLink*> linkItems = m_Pou.getLinkItemsBetweenBlocks(selBlock, selBlock2);
- qDebug() << "WindowAppPouScene::checkBatchMove() - " << linkItems.size() << " link items between ["
- << selBlock->m_toolInfo->strInstanceName << "] ["
- << selBlock2->m_toolInfo->strInstanceName << "].";
- // 将这些Link都设置为Movable,并且保存下来后续使用
- for (auto& linkItem : linkItems)
- {
- //linkItem->setFlag(QGraphicsItem::ItemIsMovable, true);
- linkItem->setMovable(true);
- // 并且设置为选中
- linkItem->setSelected(true);
- m_batchMoveLinks.push_back(linkItem);
- }
- }
- }
- }
- return true;
- }
- /// <summary>
- /// 2022-8-26,添加完功能块Item后,初始化对应参数(Index、InstanceName、ToolInterface Name等)
- /// </summary>
- /// <param name="newTool">工具引用</param>
- /// <param name="bInitIndex">是否需要初始化功能块Index</param>
- /// <param name="bInitInstName">是否需要初始化功能块实例名称</param>
- /// <param name="bInitToolInfName">是否需要初始化功能块Tool接口名字</param>
- void WindowAppPouScene::initBlockItem(TOOL*& pNewTool, bool bInitIndex, bool bInitInstName, bool bInitToolInfName)
- {
- if (bInitIndex)
- {
- // 计算分配的Index
- pNewTool->nIndex = m_Pou.GetIndexedToolsCount();
- }
- if (bInitInstName)
- {
- // 需要根据现有工具情况生成新的实例名字
- pNewTool->updateInstanceName(m_Pou.genToolInstanceName(pNewTool->strName));
- }
- if (bInitToolInfName)
- {
- // 2022-8-25,为工具的Tool接口命名
- pNewTool->ToolInterfaces[INF_START]->strName = pNewTool->strInstanceName + ".Start";
- pNewTool->ToolInterfaces[INF_START]->strFullName = m_Pou.pouName() + "." + pNewTool->ToolInterfaces[INF_START]->strName;
- pNewTool->ToolInterfaces[INF_END]->strName = pNewTool->strInstanceName + ".End";
- pNewTool->ToolInterfaces[INF_END]->strFullName = m_Pou.pouName() + "." + pNewTool->ToolInterfaces[INF_END]->strName;
- }
- }
- /// <summary>
- /// 功能块序号 减 1
- /// </summary>
- void WindowAppPouScene::BlockMoveUp()
- {
- // 防止功能块被多选
- QList<QGraphicsItem*> selItems = this->selectedItems();
- if (selItems.size() > 1)
- {
- return;
- }
- QGraphicsItem* selItem = this->selectedItems().first();
- if (selItem != nullptr)
- {
- WindowAppBlockStandardBase* block = qgraphicsitem_cast<WindowAppBlockStandardBase*>(selItem);
- if (block != nullptr && block->isStandardBasedBlock())
- {
- block->onBlockMoveUp();
- }
- }
- }
- /// <summary>
- /// 功能块序号 加 1
- /// </summary>
- void WindowAppPouScene::BlockMoveDown()
- {
- // 防止功能块被多选
- QList<QGraphicsItem*> selItems = this->selectedItems();
- if (selItems.size() > 1)
- {
- return;
- }
- QGraphicsItem* selItem = this->selectedItems().first();
- if (selItem != nullptr)
- {
- WindowAppBlockStandardBase* block = qgraphicsitem_cast<WindowAppBlockStandardBase*>(selItem);
-
- if (block != nullptr && block->isStandardBasedBlock())
- {
- block->onBlockMoveDown();
- }
- }
- }
- /// <summary>
- /// 功能块序号 置1
- /// </summary>
- void WindowAppPouScene::BlockMoveFirst()
- {
- // 防止功能块被多选
- QList<QGraphicsItem*> selItems = this->selectedItems();
- if (selItems.size() > 1)
- {
- return;
- }
- QGraphicsItem* selItem = this->selectedItems().first();
- if (selItem != nullptr)
- {
- WindowAppBlockStandardBase* block = qgraphicsitem_cast<WindowAppBlockStandardBase*>(selItem);
-
- if (block != nullptr && block->isStandardBasedBlock())
- {
- block->onBlockMoveFirst();
- }
- }
- }
- /// <summary>
- /// 功能块序号 置底
- /// </summary>
- void WindowAppPouScene::BlockMoveLast()
- {
- // 防止功能块被多选
- QList<QGraphicsItem*> selItems = this->selectedItems();
- if (selItems.size() > 1)
- {
- return;
- }
- QGraphicsItem* selItem = this->selectedItems().first();
- if (selItem != nullptr)
- {
- WindowAppBlockStandardBase* block = qgraphicsitem_cast<WindowAppBlockStandardBase*>(selItem);
- if (block != nullptr && block->isStandardBasedBlock())
- {
- block->onBlockMoveLast();
- }
- }
- }
- /// <summary>
- /// 功能块左对齐
- /// </summary>
- void WindowAppPouScene::BlockAlignLeft()
- {
- // 获取当前选中的Item
- QList<QGraphicsItem*> selItems = this->selectedItems();
- QList<WindowAppBlockStandardBase*> selBlocks;
- // 如果选中的
- if (selItems.size() <= 1)
- {
- return ;
- }
- // 取出其中所有的Block
- for (const auto& selItem : selItems)
- {
- WindowAppBlockStandardBase* block = qgraphicsitem_cast<WindowAppBlockStandardBase*>(selItem);
- if (block != nullptr && block->isStandardBasedBlock())
- {
- selBlocks.push_back(block);
- }
- }
- // 确保选中的功能块数量大于 1
- if (selBlocks.size() <= 1)
- {
- return;
- }
- // 获取最左侧的工具坐标
- int nLeftValue = INT_MAX;
- for (int i = 0; i < selBlocks.size(); i++)
- {
- QPointF point = selBlocks[i]->scenePos();
- QRectF rect = selBlocks[i]->boundingRect();
- int x = point.x() - rect.width() / 2;
- if (nLeftValue > x)
- {
- nLeftValue = x;
- }
- }
- // 设置选中的功能块坐标
- for (int i = 0; i < selBlocks.size(); i++)
- {
- QPointF point = selBlocks[i]->scenePos();
- QRectF rect = selBlocks[i]->boundingRect();
- point.setX(nLeftValue + rect.width()/2 );
- selBlocks[i]->setPos(point);
- }
- }
- /// <summary>
- /// 功能块顶对齐
- /// </summary>
- void WindowAppPouScene::BlockAlignTop()
- {
- // 获取当前选中的Item
- QList<QGraphicsItem*> selItems = this->selectedItems();
- QList<WindowAppBlockStandardBase*> selBlocks;
- // 如果选中的
- if (selItems.size() <= 1)
- {
- return;
- }
- // 取出其中所有的Block
- for (const auto& selItem : selItems)
- {
- WindowAppBlockStandardBase* block = qgraphicsitem_cast<WindowAppBlockStandardBase*>(selItem);
- if (block != nullptr && block->isStandardBasedBlock())
- {
- selBlocks.push_back(block);
- }
- }
- // 确保选中的功能块数量大于 1
- if (selBlocks.size() <= 1)
- {
- return;
- }
- // 获取最顶侧的工具坐标
- int nTopValue = INT_MAX;
- for (int i = 0; i < selBlocks.size(); i++)
- {
- QPointF point = selBlocks[i]->scenePos();
- QRectF rect = selBlocks[i]->boundingRect();
- int y = point.y() - rect.height() / 2;
- if (nTopValue > y)
- {
- nTopValue = y;
- }
- }
- // 设置选中的功能块坐标
- for (int i = 0; i < selBlocks.size(); i++)
- {
- QPointF point = selBlocks[i]->scenePos();
- QRectF rect = selBlocks[i]->boundingRect();
- point.setY(nTopValue + rect.height() / 2);
- selBlocks[i]->setPos(point);
- }
- }
- /// <summary>
- /// 功能块右对齐
- /// </summary>
- void WindowAppPouScene::BlockAlignRight()
- {
- // 获取当前选中的Item
- QList<QGraphicsItem*> selItems = this->selectedItems();
- QList<WindowAppBlockStandardBase*> selBlocks;
- // 如果选中的
- if (selItems.size() <= 1)
- {
- return;
- }
- // 取出其中所有的Block
- for (const auto& selItem : selItems)
- {
- WindowAppBlockStandardBase* block = qgraphicsitem_cast<WindowAppBlockStandardBase*>(selItem);
- if (block != nullptr && block->isStandardBasedBlock())
- {
- selBlocks.push_back(block);
- }
- }
- // 确保选中的功能块数量大于 1
- if (selBlocks.size() <= 1)
- {
- return;
- }
- // 获取最右侧的工具坐标
- int nRightValue = 0;
- for (int i = 0; i < selBlocks.size(); i++)
- {
- QPointF point = selBlocks[i]->scenePos();
- QRectF rect = selBlocks[i]->boundingRect();
- int x = point.x() + rect.width() / 2;
- if (nRightValue < x)
- {
- nRightValue = x;
- }
- }
- // 设置选中的功能块坐标
- for (int i = 0; i < selBlocks.size(); i++)
- {
- QPointF point = selBlocks[i]->scenePos();
- QRectF rect = selBlocks[i]->boundingRect();
-
- point.setX(nRightValue - rect.width() / 2);
- selBlocks[i]->setPos(point);
-
- }
- }
- /// <summary>
- /// 功能块底对齐
- /// </summary>
- void WindowAppPouScene::BlockAlignBottom()
- {
- // 获取当前选中的Item
- QList<QGraphicsItem*> selItems = this->selectedItems();
- QList<WindowAppBlockStandardBase*> selBlocks;
- // 如果选中的
- if (selItems.size() <= 1)
- {
- return;
- }
- // 取出其中所有的Block
- for (const auto& selItem : selItems)
- {
- WindowAppBlockStandardBase* block = qgraphicsitem_cast<WindowAppBlockStandardBase*>(selItem);
- if (block != nullptr && block->isStandardBasedBlock())
- {
- selBlocks.push_back(block);
- }
- }
- // 确保选中的功能块数量大于 1
- if (selBlocks.size() <= 1)
- {
- return;
- }
- // 获取最底侧的工具坐标
- int nBottomValue = 0;
- for (int i = 0; i < selBlocks.size(); i++)
- {
- QPointF point = selBlocks[i]->scenePos();
- QRectF rect = selBlocks[i]->boundingRect();
- int y = point.y() + rect.height() / 2;
- if (nBottomValue < y)
- {
- nBottomValue = y;
- }
- }
- // 设置选中的功能块坐标
- for (int i = 0; i < selBlocks.size(); i++)
- {
- QPointF point = selBlocks[i]->scenePos();
- QRectF rect = selBlocks[i]->boundingRect();
- point.setY(nBottomValue - rect.height() / 2);
- selBlocks[i]->setPos(point);
-
- }
- }
- //=================================================================
- //
- // Link相关
- //
- //=================================================================
- /// <summary>
- /// 开始执行Link动作
- /// </summary>
- void WindowAppPouScene::startLink(WindowAppItemInterface* pStartInf, QPointF ptMouse)
- {
- // 切换模式
- this->m_sceneMode = SCENE_MODE::LINK_MODE;
- // 连线的起点
- QPointF ptStart;
-
- // 2022-4-24,根据起点接口的类型,分别进行处理
- // 普通功能块接口
- if (!pStartInf->m_infInfo->isParallelToolEnd())
- {
- ptStart = pStartInf->mapToScene(pStartInf->line().p2());
- }
- // Parallel输出接口
- else
- {
- ptStart = ptMouse;
- }
- // 建立临时的连接线
- m_tmpLinkLine = new QGraphicsLineItem(QLineF(ptStart, ptMouse));
- m_tmpLinkLine->setPen(QPen(LINK_TMPLINE_COLOR, LINK_LINE_WIDTH));
- this->addItem(m_tmpLinkLine);
- }
- /// <summary>
- /// 移动Link连接
- /// </summary>
- /// <param name="ptMouse"></param>
- void WindowAppPouScene::moveLink(QPointF ptMouse, bool blink)
- {
- QLineF newLine(m_tmpLinkLine->line().p1(), ptMouse);
- m_tmpLinkLine->setLine(newLine);
- if (blink)
- {
- m_tmpLinkLine->setPen(QPen(LINK_LINE_COLOR, LINK_LINE_WIDTH));
- }
- else
- {
- QVector<qreal> dashes;
- dashes << 5 << 5 << 5 << 5;
- QPen pen(QPen(LINK_LINE_COLOR, LINK_LINE_WIDTH));
- pen.setDashPattern(dashes);
- m_tmpLinkLine->setPen(pen);
- }
- // 增加了重绘,防止线条覆盖住接口的情况
- this->update();
- }
- /// <summary>
- /// 结束Link动作
- /// </summary>
- /// <param name="ptMouse"></param>
- void WindowAppPouScene::endLink(QPointF ptMouse)
- {
- WindowAppItemInterface* startItem = nullptr;
- WindowAppItemInterface* endItem = nullptr;
- // 执行连接预检查,如果检查通过了再建立连接
- int nState = preLinkCheck(ptMouse, startItem, endItem);
- if (nState == 0)
- {
- Q_ASSERT(startItem != nullptr);
- Q_ASSERT(endItem != nullptr);
- // 此处判断一下是否是Goto->Tool的连接
- if (startItem->m_infInfo->isGotoToolEnd())
- {
- // 建立Goto到Tool之间的Link
- this->addGotoLink(startItem->m_infInfo, endItem->m_infInfo->parent());
- }
- // 继续判断一下是否是Parallel->Tool的连接
- else if (startItem->m_infInfo->isParallelToolEnd()
- && endItem->m_infInfo->isStandardToolStart())
- {
- // 建立Parallel到Tool之间的Link
- this->addParallelLink(startItem->m_infInfo, endItem->m_infInfo->parent());
- }
- // 建立标准接口间的link
- else
- {
- addLink(startItem, endItem, LINK_MODE::LINK_NORMAL);
- }
- }
- // 无论成功与否都清除掉临时连接线
- removeItem(m_tmpLinkLine);
- RELEASE(m_tmpLinkLine);
- }
- /// <summary>
- /// 进行连接预检查
- /// </summary>
- /// <param name="ptMouse"></param>
- /// <returns></returns>
- int WindowAppPouScene::preLinkCheck(QPointF ptMouse, WindowAppItemInterface*& startItem, WindowAppItemInterface*& endItem)
- {
- // 先把多余的起点和终点区域的Item去掉,只留下接口
- // MENTION:此处稍微偏移一些,为了更准确的选中接口
- QPointF startPoint = QPointF(m_tmpLinkLine->line().p1().x() - 2, m_tmpLinkLine->line().p1().y());
- QList<QGraphicsItem*> startItems = items(startPoint);
- if (startItems.count() && startItems.first() == m_tmpLinkLine)
- {
- startItems.removeFirst();
- }
-
- QList<QGraphicsItem*> endItems = items(ptMouse);
- if (endItems.count() && endItems.first() == m_tmpLinkLine)
- {
- endItems.removeFirst();
- }
- // 去除多余Item后,是否还有有效的接口信息
- if (startItems.count() <= 0 || endItems.count() <= 0)
- {
- // qDebug() << "[Error] WindowAppPouScene::preLinkCheck - startItem or endItem count <=0.";
- return -1;
- }
- // 从集合的第一个Item中取出需要link的item
- startItem = qgraphicsitem_cast<WindowAppItemInterface*>(startItems.first());
- endItem = qgraphicsitem_cast<WindowAppItemInterface*>(endItems.first());
- if (startItem == nullptr || endItem == nullptr)
- {
- // qDebug() << "[Error] WindowAppPouScene::preLinkCheck - startItem or endItem is nullptr.";
- return -2;
- }
- // 取出其中的接口信息
- const _INTERFACE* startInf = startItem->m_infInfo;
- const _INTERFACE* endInf = endItem->m_infInfo;
- // 此处增加一个有效性检查
- if (startItem == nullptr)
- {
- // qDebug() << "[Error] WindowAppPouScene::preLinkCheck - startItem is not a WindowAppItemInterface.";
- return -3;
- }
- if (endItem == nullptr)
- {
- // qDebug() << "[Error] WindowAppPouScene::preLinkCheck - endItem is not a WindowAppItemInterface.";
- return -4;
- }
- // 检查是否是同一个item
- if (startItem == endItem)
- {
- // qDebug() << "[Error] WindowAppPouScene::preLinkCheck - startItem is same as endItem.";
- return -5;
- }
- if (startItem->m_infInfo->parent() == endItem->m_infInfo->parent())
- {
- // qDebug() << "[Error] WindowAppPouScene::preLinkCheck - startItem's parent Tool is same as endItem.";
- return -6;
- }
- // 检查起点是否是有效的接口类型
- if (startItem->type() != WindowAppItemInterface::Type)
- {
- // qDebug() << "[Error] WindowAppPouScene::preLinkCheck - startItem is not interface item.";
- return -7;
- }
- // 检查起点是否是有效的接口类型
- if (endItem->type() != WindowAppItemInterface::Type)
- {
- // qDebug() << "[Error] WindowAppPouScene::preLinkCheck - endItem is not interface item.";
- return -8;
- }
- // 检查终点是否是输入接口
- if (endInf->Direction != INF_DIRECTION::INF_DIR_IN)
- {
- // qDebug() << "[Error] WindowAppPouScene::preLinkCheck - endItem is not input interface.";
- return -9;
- }
- // 检查终点接口是否已经有连接了
- if (endInf->pUpLinkInterface != nullptr)
- {
- // qDebug() << "[Error] WindowAppPouScene::preLinkCheck - endItem is already linked.";
- return -10;
- }
- // 检查起点和终点接口的数值类型是否一致(并且所有基础类型算作是相同类型)
- if (!endInf->isSameTypeTo(startInf, true))
- {
- // qDebug() << "[Error] WindowAppPouScene::preLinkCheck - startItem and endItem is not the same value type.";
- return -11;
- }
- // 2022-6-7,增加检查项,如果是Tool类型接口,还需要额外检查
- // 本接口目前不允许父功能块是同类型的连接,比如Goto->Goto,Tool->Tool,Parallel->Parallel等等
- if (startInf->isToolEnd() && endInf->isParentSameTypeTo(startInf))
- {
- // qDebug() << "[Error] WindowAppPouScene::preLinkCheck - Top output can't link to the same tool type.";
- return -12;
- }
- // 通过所有检查项,执行Link
- qDebug() << "[OK] WindowAppPouScene::preLinkCheck passed. start:" << startItem->m_infInfo->strFullName
- << " | end:" << endItem->m_infInfo->strFullName;
- return 0;
- }
- /// <summary>
- /// 增加一个Link
- /// </summary>
- /// <param name="pStartInf"></param>
- /// <param name="pEndInf"></param>
- /// <param name="linkMode">link的模式(普通/并行)</param>
- /// <param name="linePoints">本次link各线段的坐标(用于反序列化)</param>
- void WindowAppPouScene::addLink(
- WindowAppItemInterface* pStartInf,
- WindowAppItemInterface* pEndInf,
- LINK_MODE linkMode,
- QVector<QLineF> linePoints
- )
- {
- WindowAppItemLink* newLinkItem = new WindowAppItemLink(pStartInf, pEndInf, linkMode, linePoints);
- // 置于最底层
- newLinkItem->setZValue(Z_ORDER_LINK);
- this->addItem(newLinkItem);
- // newLink->updatePosition();
- // 保存Block与Link的关联信息,用于link对Block随动
- ITEM_LINK_INFO newInfo;
- newInfo.bStart = true;
- newInfo.pLink = newLinkItem;
- m_itemBlockLinks.insertMulti(pStartInf->parentItem(), newInfo);
- newInfo.bStart = false;
- m_itemBlockLinks.insertMulti(pEndInf->parentItem(), newInfo);
- // 保存接口与Link的关联信息
- m_itemInfLinks.insertMulti(pStartInf, newLinkItem);
- m_itemInfLinks.insertMulti(pEndInf, newLinkItem);
- // 存储link相关数据结构
- m_Pou.makeLink(pStartInf, pEndInf, newLinkItem, linkMode);
- }
- /// <summary>
- /// 建立Link(根据接口全名)
- /// </summary>
- /// <param name="strStartInf"></param>
- /// <param name="strEndInf"></param>
- /// <param name="linkMode">link的模式(普通/并行)</param>
- /// <param name="linePoints">本次link各线段的坐标(用于反序列化</param>
- void WindowAppPouScene::addLink(
- const QString& strStartInf,
- const QString& strEndInf,
- LINK_MODE linkMode,
- QVector<QLineF> linePoints
- )
- {
- // 获取到对应的接口
- WindowAppItemInterface* startInf = m_Pou.GetInterfaceItemByName(strStartInf);
- WindowAppItemInterface* endInf = m_Pou.GetInterfaceItemByName(strEndInf);
- // Error
- if (startInf == nullptr || endInf == nullptr)
- {
- qDebug() << "[Error] WindowAppPouScene::addLink - startInf is nullptr or endInf is nullptr.";
- return;
- }
- // 建立Link
- this->addLink(startInf, endInf, linkMode, linePoints);
- }
- ///// <summary>
- ///// 建立Link(根据Link结构体)
- ///// </summary>
- ///// <param name="linkInfo"></param>
- //void WindowAppPouScene::addLink(const LINK& linkInfo)
- //{
- // this->addLink(
- // linkInfo.strSrcInf,
- // linkInfo.strDesInf,
- // linkInfo.linkMode,
- // linkInfo.lines
- // );
- //}
- /// <summary>
- /// 删除指定link连线
- /// </summary>
- /// <param name="pLinkItem"></param>
- void WindowAppPouScene::delLink(WindowAppItemLink* pLinkItem)
- {
- WindowAppItemInterface* startInfItem = pLinkItem->startItem();
- WindowAppItemInterface* endInfItem = pLinkItem->endItem();
- // 相关的起点和终点的引用计数 - 1
- //m_PouManager.MinusInterfaceRefCount(startInfItem);
- //m_PouManager.MinusInterfaceRefCount(endInfItem);
- startInfItem->m_infInfo->nRefCount--;
- endInfItem->m_infInfo->nRefCount--;
- // 删除pou中的link信息
- m_Pou.removeLink(endInfItem);
- // 删除itemBlockLinks中的信息
- // 2022-10-19 修正,此处需要精细判断一下具体删除哪个BlockLink,否则一个输出接口连接至多个接口时
- // 此处的多条信息会被一次性删除导致bug
- ITEM_LINK_INFO delInfo;
- delInfo.bStart = true;
- delInfo.pLink = pLinkItem;
- m_itemBlockLinks.remove(startInfItem->parentItem(), delInfo);
- delInfo.bStart = false;
- delInfo.pLink = pLinkItem;
- m_itemBlockLinks.remove(endInfItem->parentItem(), delInfo);
- // 删除itemInfLinks中的信息
- m_itemInfLinks.remove(pLinkItem->startItem(), pLinkItem);
- m_itemInfLinks.remove(pLinkItem->endItem(), pLinkItem);
- // 2022-5-6,如果是
- qDebug() << "[SCENE][LINK] Delete link between [" << startInfItem->m_infInfo->strFullName
- << "]->[" << endInfItem->m_infInfo->strFullName << "].";
- // 最后彻底清空此连线item
- delete pLinkItem;
- pLinkItem = nullptr;
- }
- /// <summary>
- /// 根据接口删除link连线
- /// </summary>
- /// <param name="pInf"></param>
- void WindowAppPouScene::delLink(WindowAppItemInterface* pInf)
- {
- // 首先通过接口快速查询到对应的link连线(有可能会有多个)
- QList<WindowAppItemLink*> pLinkItems = m_itemInfLinks.values(pInf);
- // 如果查询不到,则说明此接口并没有连线
- if ( pLinkItems.size()<=0 )
- {
- qDebug() << "[SCENE][LINK] Delete link error: can not find link of interface[" << pInf->m_infInfo->strFullName << "].";
- return;
- }
- // 然后分别清除每一个对应接口的信息
- for (WindowAppItemLink * pLinkItem : pLinkItems)
- {
- this->delLink(pLinkItem);
- }
- }
- /// <summary>
- /// 根据接口名字删除link连线
- /// </summary>
- /// <param name="strInf"></param>
- void WindowAppPouScene::delLink(const QString& strInf)
- {
- WindowAppItemInterface* infItem = m_Pou.GetInterfaceItemByName(strInf);
- this->delLink(infItem);
- }
- /// <summary>
- /// 执行SmartLink(找离本接口最近的同类型输出端口,序号小于自己的)
- /// </summary>
- /// <param name="pInf"></param>
- void WindowAppPouScene::smartLink(WindowAppItemInterface* pInf)
- {
- // 在pou中找到可以执行smartLink的接口
- WindowAppItemInterface* pLinkInfItem = m_Pou.getSmartLinkInterface(pInf);
- if (pLinkInfItem == nullptr)
- {
- Utility::VPCriticalMessageBox("Not find corresponding smartlink interface!");
- return;
- }
- // 如果成功找到了的话,则连接
- addLink(pLinkInfItem, pInf);
- }
- /// <summary>
- /// 建立Tool间的Link(Goto到Tool的link)
- /// </summary>
- /// <param name="pGotoInf"></param>
- /// <param name="pTool"></param>
- void WindowAppPouScene::addGotoLink(_INTERFACE* pGotoInf, const TOOL* pTool)
- {
- //// 首先检查目标Tool是否已经有连接
- //if (pTool->isTopLinked())
- //{
- // qWarning() << "Tool[" + pTool->strInstanceName + "] is already linked!";
- // return;
- //}
- // 如果本Goto之前绑定过Tool,则首先清除之前的link,准备绑定新Tool
- if (pGotoInf->pBindInterface != nullptr)
- {
- this->delLink(pGotoInf->strFullName);
- }
- // 绑定到目标Tool的ToolStart接口中
- pGotoInf->pBindInterface = pTool->startInterface;
- // 设置接口的名称为目标Tool的实例名字
- pGotoInf->strName = pTool->strInstanceName;
- // 绑定完毕之后,需要把输出接口的显示打开,用于显示绑定目标的名字
- pGotoInf->bShowName = true;
- // 界面增加Link信息
- QString strSrc = pGotoInf->strFullName;
- QString strDst = pTool->startInterface->strFullName;
- this->addLink(strSrc, strDst);
- }
- /// <summary>
- /// 建立Parallel到Tool的Link
- /// </summary>
- /// <param name="pGotoInf"></param>
- /// <param name="pTool"></param>
- void WindowAppPouScene::addParallelLink(_INTERFACE* pParaInf, const TOOL* pTool)
- {
- // 界面增加Link信息
- QString strSrc = pParaInf->strFullName;
- QString strDst = pTool->startInterface->strFullName;
- this->addLink(strSrc, strDst, LINK_MODE::LINK_PARALLEL);
- // Parallel Link建立完毕之后需要立即确认一下并行连线的位置,有可能默认位置已经超出了并行连线的长度
- WindowAppItemInterface* startInf = m_Pou.GetInterfaceItemByName(strSrc);
- startInf->updatePostion();
- }
- /// <summary>
- /// block被移动时,需要同时更新link连线的位置
- /// </summary>
- /// <param name="item"></param>
- void WindowAppPouScene::onBlockMove(QGraphicsItem* item)
- {
- // 更新本Block关联的Link连线
- // qDebug() << "WindowAppDiagramScene::onBlockMove.";
- // TODO:为了修正一个在ShowOnly的情况下多次点击接口右键会崩溃的问题,临时处理
- if (item == nullptr)
- {
- qDebug() << "[POU][Error] WindowAppPouScene::onBlockMove - but item is nullptr.";
- return;
- }
- // 2022-6-15, 如果处于批量拖动模式下,则不需要重绘Link线段,直接平移
- // 2022-7-2 修正,此处不能分开处理,否则Link连线会出现断裂的情况
- //if (sceneMode != SCENE_MODE::BATCHMOVE_MODE)
- //{
- // 查找这个移动的Block是否有对应的link需要重绘
- this->updateLinkItemsByBlock(item);
- // 2022-5-8增加,如果是并行组相关的功能块移动时,还需要检查其所属的并行母线是否需要延长或者缩短
- this->updateParallelLineByBlock(item);
- //}
- }
- /// <summary>
- /// 检查所有的接口连线是否需要刷新
- /// </summary>
- /// <param name="item"></param>
- void WindowAppPouScene::updateLinkItemsByBlock(QGraphicsItem* item)
- {
- QList<ITEM_LINK_INFO> linkInfos = m_itemBlockLinks.values(item);
- if (linkInfos.size() > 0)
- {
- // 自动化方式移动
- //for (WindowAppItemLink* pLink : links)
- //{
- // 更新对应Link的位置
- // pLink->updateLinkLines();
- //}
- // 手动方式移动
- for (auto& linkInfo : linkInfos)
- {
- // 根据移动的功能块调整对应的Link连线
- linkInfo.pLink->updateLinkLinesManual(item, linkInfo.bStart);
- }
- // 重绘界面
- this->update();
- }
- }
- /// <summary>
- /// 检查并行母线是否需要刷新
- /// </summary>
- /// <param name="item"></param>
- void WindowAppPouScene::updateParallelLineByBlock(QGraphicsItem* item)
- {
- WindowAppBlockStandard* pStardardBlock = qgraphicsitem_cast<WindowAppBlockStandard*>(item);
- if (pStardardBlock == nullptr || !pStardardBlock->m_toolInfo->isParallelSubTool())
- {
- return;
- }
- // 找到本工具所属的并行工具组
- TOOL* pParaTool = pStardardBlock->m_toolInfo->toolStartUpTool();
- // 错误,不应该为空
- // Reason:(如果此处不加判断的话,反序列化的时候由于此时工具信息尚未恢复完毕,所以执行到此处的时候会崩溃)
- if (pParaTool == nullptr)
- {
- qDebug() << "[Error] WindowAppPouScene::updateParallelLineByBlock - but ParaTool is nullptr.";
- return;
- }
- // 找到并行工具的功能块
- WindowAppBlockParallel* blockParallel = qgraphicsitem_cast<WindowAppBlockParallel*>(m_Pou.GetToolItem(pParaTool));
- if (blockParallel != nullptr)
- {
- // 更新对应的并行母线(以起始连线线的X坐标为参照)
- blockParallel->updateParallelLine();
- }
- }
- /// <summary>
- /// 用于和注释控件做联动使用,如果注释控件内容为空,则删除此控件
- /// </summary>
- /// <param name="item"></param>
- void WindowAppPouScene::removeEmptyBlockComment(WindowAppBlockComment* item)
- {
- // 如果注释控件为空,则删除此控件
- if (item->content().isEmpty())
- {
- removeItem(item);
- item->deleteLater();
- }
- }
- //=================================================================
- //
- // 动态端口同步相关
- //
- //=================================================================
- /// <summary>
- /// 接收来自Dll端的动态端口同步消息
- /// </summary>
- /// <param name="event"></param>
- void WindowAppPouScene::customEvent(QEvent* event)
- {
- // 如果是动态端口同步消息
- if (event->type() == DLLINF_EVENT_TYPEID)
- {
- SyncInterfaceEvent* pDllInfEvent = dynamic_cast<SyncInterfaceEvent*> (event);
- // 取出参数
- QList<DLL_INF> syncInfs = pDllInfEvent->getSyncInterfaces();
- qDebug() << "WindowAppPouScene::customEvent - DLLINF_EVENT, inf count:" << syncInfs.size()
- << " add/del:" << pDllInfEvent->m_bAdd;
- // 根据名字找到所属的功能块(仅标准功能块支持此功能)
- WindowAppBlockStandard* pBlock =
- dynamic_cast<WindowAppBlockStandard*>(m_Pou.GetToolItem(pDllInfEvent->m_strInstanceName));
- // 执行结果
- bool bRet = false;
- // 如果出错,保存错误原因
- QString strReason;
- // 动态增加
- if (pDllInfEvent->m_bAdd)
- {
- bRet = pBlock->addDynamicInterfacesFromDll(syncInfs, strReason);
- }
- // 动态删除
- else
- {
- bRet = pBlock->deleteDynamicInterfacesFromDll(syncInfs, strReason);
- }
-
- pDllInfEvent->m_bSuccess = bRet;
- pDllInfEvent->m_strReason = strReason;
- //// 刷新整个UI
- //this->update();
- }
- }
- ///// <summary>
- ///// 2022-3-10 为功能块增加动态接口
- ///// </summary>
- ///// <param name="strToolInstName"></param>
- ///// <param name="infList"></param>
- //void WindowAppPouScene::addDynamicInterfaces(const QString& strToolInstName, const QList<DLL_INF>& infList)
- //{
- // WindowAppBlockStandard* pBlock = dynamic_cast<WindowAppBlockStandard*>(m_Pou.GetToolItem(strToolInstName));
- //
- // // 增加动态接口
- // pBlock->addDynamicInterfacesFromDll(infList);
- //
- //}
- //
- //void WindowAppPouScene::delDynamicInterfaces(const QString& strToolInstName, const QList<DLL_INF>& infList)
- //{
- //
- //}
- /// <summary>
- /// 键盘上下键移动功能块 不按 Control 的时候,鼠标上下键为画布移动,按住 Control 的时候,为功能块移动
- /// </summary>
- /// <param name="e"></param>
- void WindowAppPouScene::keyPressEvent(QKeyEvent* event)
- {
- if (QApplication::keyboardModifiers() == Qt::ShiftModifier
- || QApplication::keyboardModifiers() == Qt::ControlModifier
- )
- {
-
- qreal dx = 0, dy = 0;
- switch (event->key())
- {
- case Qt::Key_Up:
- dx = 0;
- dy = -m_nMoveBlockSleep;
- break;
- case Qt::Key_Down:
- dx = 0;
- dy = m_nMoveBlockSleep;
- break;
- case Qt::Key_Left:
- dx = -m_nMoveBlockSleep;
- dy = 0;
- break;
- case Qt::Key_Right:
- dx = m_nMoveBlockSleep;
- dy = 0;
- break;
- }
- // 持续移动的时候,移动步长会持续增加。直到步长值为 50
- if (m_nMoveBlockSleep < 50)
- {
- m_nMoveBlockSleep++;
- }
- QList<QGraphicsItem*> selItems = this->selectedItems();
- QList<WindowAppBlockStandardBase*> selBlocks;
-
- // 取出其中所有的Block
- for (const auto& selItem : selItems)
- {
- WindowAppBlockStandardBase* block = qgraphicsitem_cast<WindowAppBlockStandardBase*>(selItem);
- if (block != nullptr && block->isStandardBasedBlock())
- {
- selBlocks.push_back(block);
- //onBlockMove(selItem);
- block->moveBy(dx, dy);
- }
- }
- // TODO: 还需要移动 Link
-
-
- }
- //else
- {
- QGraphicsScene::keyPressEvent(event);
- }
-
- }
- /// <summary>
- /// 接收键盘释放消息
- /// </summary>
- /// <param name="event"></param>
- void WindowAppPouScene::keyReleaseEvent(QKeyEvent* event)
- {
- //
- if (event->isAutoRepeat())
- {
- event->ignore();
- }
- else
- {
- m_nMoveBlockSleep = 1;
- }
-
- QGraphicsScene::keyReleaseEvent(event);
- }
|