123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998 |
- #include "WindowAppItemInterface.h"
- #include "WindowAppBlockStandard.h"
- #include "WindowAppBlockPort.h"
- #include "WindowAppPouScene.h"
- #include "WindowAppItemLink.h"
- #include "Pou.h"
- #include <qmath.h>
- WindowAppItemInterface::WindowAppItemInterface(
- _INTERFACE* pInf,
- POU* pPou,
- const TOOL* pTool,
- bool bShowOnly,
- QGraphicsItem* parent /*= nullptr*/
- ):
- m_infInfo(pInf)
- , m_pPou(pPou)
- , m_pParentTool(pTool)
- , m_bShowOnly(bShowOnly)
- // , m_nParallelLineLen(PARARREL_LINE_BASE_LEN)
- {
- // 接收悬停事件,显示提示
- setAcceptHoverEvents(true);
- // 设置风格,可选择但不可拖动
- setFlag(QGraphicsItem::ItemIsMovable, false);
- setFlag(QGraphicsItem::ItemIsSelectable, true);
- // 接收Item移动消息
- setFlag(QGraphicsItem::ItemSendsGeometryChanges);
- this->setParentItem(parent);
- }
- /// <summary>
- /// 返回接口的矩形边界
- /// </summary>
- /// <returns></returns>
- QRectF WindowAppItemInterface::boundingRect() const
- {
- QRectF rc;
- // Goto输出接口的矩形区域
- if ( this->m_infInfo->isGotoToolEnd() )
- {
- rc = QRectF(
- m_parentRect.right() + 1,
- -GOTO_OUTPUT_TRIA_SIDE / 2,
- GOTO_OUTPUT_TRIA_SIDE * qSin(60 * 3.14 / 180),
- GOTO_OUTPUT_TRIA_SIDE
- );
- }
- // Parallel输出接口的矩形区域(并行母线)
- else if ( this->m_infInfo->isParallelToolEnd() )
- {
- //rc = QRectF(
- // m_parentRect.x() - PARARREL_LINE_EX_LEN,
- // m_parentRect.bottom() + PARARREL_LINE_SPACE,
- // m_nParallelLineLen,
- // PARARREL_LINE_HEIGHT
- //);
- rc = QRectF(
- line().x1(),
- line().y1(),
- line().length(),
- PARARREL_LINE_HEIGHT
- );
- }
- // 如果是正常接口,则按正常接口区域返回
- else
- {
- qreal extra = (pen().width()) * 4.0;
- rc = QRectF(
- line().p1(),
- QSizeF(line().p2().x() - line().p1().x(),
- line().p2().y() - line().p1().y()
- ))
- .normalized()
- .adjusted(-extra, -extra, extra, extra);
- }
- return rc;
- }
- /// <summary>
- /// 形状边界(为了扩大接口区域的可点击范围)
- /// </summary>
- /// <returns></returns>
- QPainterPath WindowAppItemInterface::shape() const
- {
- QPainterPath path;
- // Goto输出接口的Shape
- if ( this->m_infInfo->isGotoToolEnd())
- {
- path.moveTo(m_parentRect.right() + 1, -GOTO_OUTPUT_TRIA_SIDE / 2);
- path.lineTo(m_parentRect.right() + 1, GOTO_OUTPUT_TRIA_SIDE / 2);
- path.lineTo(m_parentRect.right() + 1 + GOTO_OUTPUT_TRIA_SIDE * qSin(60 * 3.14 / 180), 0);
- }
- // Parallel输出接口的Shape
- else if (this->m_infInfo->isParallelToolEnd())
- {
- //path.addRect(
- // m_parentRect.x() - PARARREL_LINE_EX_LEN,
- // m_parentRect.bottom() + PARARREL_LINE_SPACE,
- // m_nParallelLineLen,
- // PARARREL_LINE_HEIGHT
- //);
- path.addRect(
- line().x1(),
- line().y1(),
- line().length(),
- PARARREL_LINE_HEIGHT
- );
- }
- // 默认的线条Shape
- else
- {
- qreal extra = (pen().width()) * 4.0;
- extra *= 1.414;
- path = QGraphicsLineItem::shape();
- // 通过Stroker设置精确Shape
- QPainterPathStroker stroker;
- stroker.setWidth(extra);
- path = stroker.createStroke(path);
- }
- return path;
- }
- /// <summary>
- /// 接口绘制
- /// </summary>
- /// <param name="painter"></param>
- /// <param name="option"></param>
- /// <param name="widget"></param>
- void WindowAppItemInterface::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget /*= nullptr*/)
- {
- Q_UNUSED(option);
- Q_UNUSED(widget);
- // 如果本接口压根都没启用的话,则不进行绘制
- if (!m_bShowOnly && !this->m_infInfo->bEnable)
- {
- return;
- }
-
- // 排除掉非标准接口,因为非标准接口无法通过连线的方式进行链接
- if (this->m_infInfo->Type == INF_TYPE::INF_TYPE_EVENT
- || this->m_infInfo->Type == INF_TYPE::INF_TYPE_CONTROL
- )
- {
- return;
- }
- painter->setRenderHint(QPainter::Antialiasing, true);
- painter->save();
- // 硬件组态禁止显示端口
- // if ( m_pPou->pouName() == GROUP_NAME_HARDWARE)
- // {
- // painter->restore();
- // return;
- // }
- // 线条颜色
- QColor penColor;
- // 根据接口废弃与否,显示不同的颜色
- // 废弃线条显示黑色
- if (m_infInfo->Discard != INF_DISCARD::INF_DEFAULT)
- {
- penColor = COLOR_INF_DISCARDLINE;
- }
- // 正常线条显示正常颜色
- else
- {
- penColor = COLOR_INF_LINE;
- }
- // 根据接口选中与否,显示不同的颜色
- // 尚未选中,默认线条
- if (!isSelected() && !IsParentSelected())
- {
- painter->setPen(QPen(penColor, PEN_LINE_WIDTH, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
- }
- // 被选中,加粗线条
- else
- {
- painter->setPen(QPen(penColor, PEN_LINE_WIDTH_SEL, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
- }
- // 绘制接口线条
- this->drawInterfaceLine(painter);
- // 绘制接口文字
- this->drawInterfaceText(painter);
- painter->restore();
- }
- /// <summary>
- /// 绘制接口线条
- /// </summary>
- /// <param name="painter"></param>
- void WindowAppItemInterface::drawInterfaceLine(QPainter* painter)
- {
- // 如果是Goto工具的输出接口,则画一个特殊的三角形箭头
- if ( this->m_infInfo->isGotoToolEnd())
- {
- this->drawArrowOutput(painter);
- }
- // 2022-8-28,如果是ForLoop工具的ToolEnd接口,也需要画一个特殊的三角箭头,但是高度有区别
- else if (this->m_infInfo->isForLoopToolEnd())
- {
- // 调整三角形高度之后绘制
- this->drawArrowOutput(painter, -10);
- }
- // 如果是Parallel工具的输出接口,则画一个特殊的并行母线
- else if (this->m_infInfo->isParallelToolEnd())
- {
- this->drawParallelOutput(painter);
- }
- // 否则绘制默认的接口线条效果
- else
- {
- painter->drawLine(line());
- }
- }
- /// <summary>
- /// 绘制接口文字
- /// </summary>
- /// <param name="painter"></param>
- void WindowAppItemInterface::drawInterfaceText(QPainter* painter)
- {
- if ( this->m_infInfo->bShowName )
- {
- painter->setPen(COLOR_TEXT);
- painter->setFont(FONT_INF);
- painter->drawText(m_ptInfTitle, m_infInfo->strName);
- }
- }
- /// <summary>
- /// 绘制Goto输出接口的三角形
- /// </summary>
- /// <param name="painter"></param>
- void WindowAppItemInterface::drawArrowOutput(QPainter* painter, int nFixHeight)
- {
- QPainterPath path;
- // 起点
- QPointF ptStart(m_parentRect.right() + 1, -GOTO_OUTPUT_TRIA_SIDE / 2 + nFixHeight);
- // 终点
- QPointF ptEnd(ptStart.rx() + GOTO_OUTPUT_TRIA_SIDE * qSin(60 * 3.14 / 180), nFixHeight);
- path.moveTo(ptStart.rx(), -GOTO_OUTPUT_TRIA_SIDE / 2 + nFixHeight);
- path.lineTo(ptStart.rx(), GOTO_OUTPUT_TRIA_SIDE / 2 + nFixHeight);
- // 按照正三角形的方式绘制
- path.lineTo(ptEnd);
- // 如果是Goto工具,则需要根据工具的执行状态改变箭头颜色
- if (this->m_pParentTool->isGotoTool())
- {
- if (this->m_pParentTool->execParams.nRetValue != VPEnum::RETURN_VALUE::Goto)
- {
- painter->fillPath(path, QBrush(COLOR_GOTO_OUTPUT_READY));
- }
- else
- {
- painter->fillPath(path, QBrush(COLOR_GOTO_OUTPUT_DONE));
- }
- }
- else
- {
- painter->fillPath(path, QBrush(COLOR_ARROW_OUTPUT));
- }
- }
- /// <summary>
- /// 绘制并行工具的输出接口(并行母线)
- /// </summary>
- /// <param name="painter"></param>
- void WindowAppItemInterface::drawParallelOutput(QPainter* painter)
- {
- //QPointF start(m_parentRect.x() - PARARREL_LINE_EX_LEN, m_parentRect.bottom() + PARARREL_LINE_SPACE);
- //painter->fillRect(
- // start.rx(),
- // start.ry(),
- // m_nParallelLineLen,
- // PARARREL_LINE_HEIGHT,
- // COLOR_FRAME_PARALLEL
- //);
- painter->fillRect(
- line().x1(),
- line().y1(),
- line().length(),
- PARARREL_LINE_HEIGHT,
- COLOR_FRAME_PARALLEL
- );
- }
- /// <summary>
- /// 更新常规接口位置
- /// </summary>
- void WindowAppItemInterface::updateRegularPostion(int nIndex)
- {
- // 计算线条高度
- int lineHeight = 0;
- // 根据Tool类型调整一下起始高度
- //2022-9-20(所有既带ToolInterface又带普通接口的工具都需要按标准工具的布局处理)
- if (m_infInfo->parent()->isStandardTool()
- || m_infInfo->parent()->isForloopTool()
- || m_infInfo->parent()->isWaitTool()
- )
- {
- lineHeight = m_parentRect.top() + TBD_INF_OFFSET + nIndex * (short)TBD_INF_SPACING;
- }
- else
- {
- lineHeight = m_parentRect.top() + PBD_INF_OFFSET;
- }
- // 设置线条和文字位置(需要区分左右)
- QRect textRect = QFontMetrics(FONT_INF).boundingRect(m_infInfo->strName);
- // 输出接口文字位置
- if (m_infInfo->Direction == INF_DIRECTION::INF_DIR_OUT)
- {
- QLineF lineInf(
- QPointF(m_parentRect.right() + 1, lineHeight),
- QPointF(m_parentRect.right() + TBD_INF_LINE + 1, lineHeight)
- );
- setLine(lineInf);
- if (m_pParentTool->Type != TOOL_TYPE::TOOL_TYPE_GOTO)
- {
- int textX = m_parentRect.right() - textRect.width() - 4;
- int textY = lineHeight + textRect.height() / 4;
- m_ptInfTitle = QPointF(textX, textY);
- }
- // 2022-4-4增加,如果是Goto工具,则需要调整一下输出接口的显示未知
- // 因为Goto工具有序号遮挡,需要把文字的位置左移
- else
- {
- int textX = m_parentRect.right() - textRect.width() - TBD_INDEX_WIDTH - 4;
- int textY = lineHeight + textRect.height() / 4;
- m_ptInfTitle = QPointF(textX, textY);
- }
- }
- // 输入接口文字位置
- else
- {
- QLineF lineInf(
- QPointF(m_parentRect.left() - TBD_INF_LINE, lineHeight),
- QPointF(m_parentRect.left(), lineHeight)
- );
- setLine(lineInf);
- int textX = m_parentRect.left() + 4;
- int textY = lineHeight + textRect.height() / 4;
- m_ptInfTitle = QPointF(textX, textY);
- }
- }
- /// <summary>
- /// 更新Goto输出接口位置
- /// </summary>
- void WindowAppItemInterface::updateGotoPosition()
- {
- // 起点
- QPointF ptStart(m_parentRect.right() + 1, -GOTO_OUTPUT_TRIA_SIDE / 2);
- // 终点
- QPointF ptEnd(ptStart.rx() + GOTO_OUTPUT_TRIA_SIDE * qSin(60 * 3.14 / 180), 0);
- // 2022-4-23增加,此处应该把Line也设置一下,因为Link的时候是以Line为坐标来Link的
- this->setLine(ptStart.rx(), 0, ptEnd.rx(), ptEnd.ry());
- }
- /// <summary>
- /// 更新Parallel输出接口位置
- /// </summary>
- void WindowAppItemInterface::updateParallelPosition()
- {
- // 获取本接口连接的下联接口
- QVector<_INTERFACE*> linkInterfaces = this->m_infInfo->pDownLinkInterfaces;
-
- // 如果尚未下联接口,则使用默认位置
- if (linkInterfaces.size() <= 0)
- {
- // 基准起点
- QPointF start(m_parentRect.x() - PARARREL_LINE_EX_LEN, m_parentRect.bottom() + PARARREL_LINE_SPACE);
- // 设置并行母线线条,母线矩形上沿
- this->setLine(
- start.rx(),
- start.ry() + PARARREL_LINE_HEIGHT,
- start.rx() + PARARREL_LINE_BASE_LEN + PARARREL_LINE_EX_LEN, // 基础长度
- start.ry() + PARARREL_LINE_HEIGHT
- );
- }
-
- // 如果有下联接口,则遍历所有下联接口连线的坐标位置,用于并行母线的坐标参考
- else
- {
- // 取出对应的LinkItem连线,这些都是从并行母线到下面各个Block的ToolStart接口连线
- QList<WindowAppItemLink*> linkItems = (qobject_cast<WindowAppPouScene*>(this->scene()))->getLinkItemsByInfItem(this);
- // 遍历所有的接口,取出左边界和右边界的最大值
- QRectF sceneParentRect = this->mapRectToScene(m_parentRect);
- int nBaseLeft = sceneParentRect.x();
- int nBaseRight = nBaseLeft + PARARREL_LINE_BASE_LEN;
- int nMaxLeft = nBaseLeft;
- int nMaxRight = 0;
- // 遍历所有下联接口的Item,找到最左Item和最右Item
- for (auto linkItem : linkItems)
- {
- QLineF linkLine = linkItem->startLine();
- int ptX = linkLine.p1().x();
- // qDebug() << "linkLine.p1().x: " << ptX << " ParallineLeft: " << nBaseLeft << " ParallineRight: " << nBaseRight;
- if (ptX < nMaxLeft)
- {
- nMaxLeft = ptX;
- }
- else if (ptX > nMaxRight)
- {
- nMaxRight = ptX;
- }
- }
- // 根据下联接口线的位置,调整母线的长度
- // 调整母线左侧
- if (nMaxLeft < nBaseLeft)
- {
- QPointF pt = this->mapToScene(this->line().p1());
- pt.setX(nMaxLeft - PARARREL_LINE_EX_LEN);
- pt = this->mapFromScene(pt);
- // qDebug() << "Before linkLine: " << line() << " pt:" << pt;
- this->setLine(QLineF(pt, line().p2()));
- // qDebug() << "Ajusted linkLine: " << line();
- }
- // 调整母线右侧
- if (nMaxRight + PARARREL_LINE_EX_LEN > nBaseRight)
- {
- QPointF pt = this->mapToScene(this->line().p2());
- pt.setX(nMaxRight + PARARREL_LINE_EX_LEN);
- pt = this->mapFromScene(pt);
- // qDebug() << "Before linkLine: " << line() << " pt:" << pt;
- this->setLine(QLineF(line().p1(), pt));
-
- // qDebug() << "Ajusted linkLine: " << line();
- }
- }
- }
- /// <summary>
- /// 鼠标双击时,自动添加port变量并连接
- /// </summary>
- /// <param name="event"></param>
- void WindowAppItemInterface::mouseDoubleClickEvent(QGraphicsSceneMouseEvent* event)
- {
- Q_UNUSED(event);
- // QMessageBox::information(nullptr, "Vision Plus", "mouseDoubleClickEvent");
- //qDebug() << this->scenePos();
- //qDebug() << this->mapToScene(this->line().p1()) << this->mapToScene(this->line().p2());
- // 只有鼠标左键才响应
- // if (event->button() == Qt::LeftButton && !m_bShowOnly)
- // {
- // // 由于Interface本身的图形已经和所属的Block整合到了一起,所以通过Interface的scenePos()获取的是其父block的Pos
- // // 此处需要帮助外部函数提供一个本Interface的真实Pos
- // QLineF realLine = QLineF(
- // this->mapToScene(this->line().p1()),
- // this->mapToScene(this->line().p2())
- // );
- //
- // ((WindowAppPouScene*)scene())->addPortAndAutolink(this, realLine);
- // }
- }
- /// <summary>
- /// 更新最新的父矩形区域
- /// </summary>
- /// <param name="parentRect"></param>
- void WindowAppItemInterface::updateParentRect(QRectF parentRect)
- {
- // 首先转换坐标系
- QPointF ptFix = mapFromScene(0, 0);
- parentRect.translate(ptFix);
- m_parentRect = parentRect;
- }
- /// <summary>
- /// 根据Block的位置和自身的序号更新本接口的位置(标准接口)
- /// </summary>
- /// <param name="parentRect"></param>
- void WindowAppItemInterface::updatePostion(int nIndex)
- {
- // 由于Goto输出接口是一个三角形,所以Goto接口需要专门处理
- if (this->m_infInfo->isGotoToolEnd())
- {
- this->updateGotoPosition();
- }
- // 由于Parallel输出接口是并行母线的形式,所以Parallel输出接口需要专门处理
- else if (this->m_infInfo->isParallelToolEnd())
- {
- this->updateParallelPosition();
- }
- // 如果是正常的ToolInterface接口,直接走Tool类型的接口位置更新
- else if (this->m_infInfo->isToolInterface())
- {
- this->updateToolInterfacePostion();
- }
- // 剩下的都按常规接口更新
- else
- {
- this->updateRegularPostion(nIndex);
- }
- }
- /// <summary>
- /// 根据Block的位置计算ToolStart、ToolEnd接口的位置(标准工具、并行工具、For工具都会调用到此处)
- /// </summary>
- /// <param name="parentRect"></param>
- void WindowAppItemInterface::updateToolInterfacePostion()
- {
-
- // 输入接口
- if (m_infInfo->Direction == INF_DIRECTION::INF_DIR_IN)
- {
- // 线条高度
- int lineHeight = m_parentRect.top() + TBD_TOPINF_SPACING;
- // 设置线条位置
- QRect textRect = QFontMetrics(FONT_INF).boundingRect(m_infInfo->strName);
- QLineF lineTop(
- QPointF(m_parentRect.left() - TBD_TOPINF_LINE, lineHeight),
- QPointF(m_parentRect.left(), lineHeight)
- );
- setLine(lineTop);
- //// 设置文字位置(目前ToolStart接口暂时不显示名字,为了以后需要,先计算出来)
- //int textX = m_parentRect.left() + 4;
- //int textY = lineHeight + textRect.height() / 4;
- //m_ptInfTitle = QPointF(textX, textY);
- }
- // 输出接口
- else
- {
- // 线条高度
- int lineHeight = m_parentRect.top() + TBD_TOPINF_SPACING;
- // 设置线条位置
- QRect textRect = QFontMetrics(FONT_INF).boundingRect(m_infInfo->strName);
- QLineF lineTop(
- QPointF(m_parentRect.right() + TBD_TOPINF_LINE, lineHeight),
- QPointF(m_parentRect.right(), lineHeight)
- );
- setLine(lineTop);
- //// 设置文字位置(目前ToolStart接口暂时不显示名字,为了以后需要,先计算出来)
- //int textX = m_parentRect.left() + 4;
- //int textY = lineHeight + textRect.height() / 4;
- //m_ptInfTitle = QPointF(textX, textY);
- }
- }
- /// <summary>
- /// 判断父Block是否处于选中状态
- /// </summary>
- /// <returns></returns>
- bool WindowAppItemInterface::IsParentSelected()
- {
- bool bIsParentSel = false;
- WindowAppBlockBase* pParentBlock = qgraphicsitem_cast<WindowAppBlockBase*>(this->parentItem());
- bIsParentSel = pParentBlock->isSelected();
- return bIsParentSel;
- }
- /// <summary>
- /// 显示动态右键菜单
- /// </summary>
- /// <param name="event"></param>
- void WindowAppItemInterface::contextMenuEvent(QGraphicsSceneContextMenuEvent* event)
- {
- Q_UNUSED(event);
- // 设置接口为选中状态
- this->setSelected(true);
-
- // 如果只仅供展示用,则不显示右键菜单
- if (m_bShowOnly)
- {
- return;
- }
- // 动态创建
- createDynamicContextMenu();
- }
- /// <summary>
- /// 新建Interface的右键菜单
- /// </summary>
- void WindowAppItemInterface::createDynamicContextMenu()
- {
- if (m_infInfo->isGotoToolEnd()
- || m_infInfo->isParallelToolStart()
- || m_infInfo->isParallelToolEnd()
- //|| m_infInfo->isToolStart()
- //|| m_infInfo->isToolEnd()
- )
- {
- return;
- }
- // 硬件组态不显示右键菜单
- if (m_pPou->pouName() == GROUP_NAME_HARDWARE)
- {
- return;
- }
- QMenu* contextMenu = new QMenu();
- QMenu* childMenu = new QMenu();
- QAction* unLinkAction = new QAction(("Unlink"), this);
- QAction* smartLinkAction = new QAction(("Smart link"), this);
- QAction* addWatchAction = new QAction(("Add Watch..."), this);
- QAction* addPortAction = new QAction(("Add Port..."), this);
- QAction* disableAction = new QAction(("Disable"), this);
- QAction* linkAction;
-
- // 根据输入输出显示不同的内容
- if (m_infInfo->Direction == INF_DIRECTION::INF_DIR_OUT)
- {
- linkAction = new QAction(("Link To..."), this);
- }
- else
- {
- linkAction = new QAction(("Link From..."), this);
- }
-
- connect(childMenu, SIGNAL(triggered(QAction*)), this, SLOT(onMenuLink(QAction*)));
- connect(unLinkAction, &QAction::triggered, this, &WindowAppItemInterface::onMenuUnlink);
- connect(smartLinkAction, &QAction::triggered, this, &WindowAppItemInterface::onMenuSmartlink);
- connect(addWatchAction, &QAction::triggered, this, &WindowAppItemInterface::onMenuAddWatch);
- connect(addPortAction, &QAction::triggered, this, &WindowAppItemInterface::onMenuAddPort);
- connect(disableAction, &QAction::triggered, this, &WindowAppItemInterface::onMenuDisable);
- // 根据适配的接口创建对应的菜单项
- const QMap<QString, _INTERFACE*> allInfs = m_pPou->GetAllInterfaces();
- QMapIterator<QString, _INTERFACE*> i(allInfs);
- while (i.hasNext())
- {
- const _INTERFACE* pInf = i.next().value();
- // 方向相反、类型相同、不从属于一个工具、并且父工具不是Port类型
- // 目标端口未被引用 , 端口为启用状态
- if (pInf->isRevDirectionTo(this->m_infInfo)
- && pInf->isSameTypeTo(this->m_infInfo)
- && pInf->parent() !=this->m_infInfo->parent()
- && pInf->parent()->isStandardTool()
- && (pInf->nRefCount == 0 || pInf->Direction == INF_DIRECTION::INF_DIR_OUT)
- && pInf->bEnable
- )
- {
- QAction* childAction = new QAction(i.key(), this);
- childMenu->addAction(childAction);
- }
- }
- // 设置菜单结构
- if (childMenu->actions().count() > 0)
- {
- linkAction->setMenu(childMenu);
- }
-
- // 输入端口,且未链接过数据
- if ( m_infInfo->Direction == INF_DIRECTION::INF_DIR_IN
- && m_infInfo->nRefCount == 0
- )
- {
- contextMenu->addAction(linkAction);
- }
-
- // 输出端口,都可以添加
- if (m_infInfo->Direction == INF_DIRECTION::INF_DIR_OUT)
- {
- contextMenu->addAction(linkAction);
- }
- // 如果引用计数不等于 0 ,该端口允许取消链接(因为取消无意义)
- if (m_infInfo->nRefCount != 0)
- {
- contextMenu->addAction(unLinkAction);
- }
-
- contextMenu->addSeparator();
- // 只有输入端口有Smartlink选项
- if (m_infInfo->Direction == INF_DIRECTION::INF_DIR_IN
- && m_infInfo->nRefCount == 0
- )
- {
- contextMenu->addAction(smartLinkAction);
- contextMenu->addSeparator();
- }
- contextMenu->addAction(addWatchAction);
- // 输出端口,和输入端口引用计数为 0 的时候,允许添加 Port
- if (m_infInfo->Direction == INF_DIRECTION::INF_DIR_OUT
- && m_infInfo->nRefCount == 0
- )
- {
- contextMenu->addAction(addPortAction);
- }
-
- contextMenu->addSeparator();
- // 如果引用计数大于 0 ,该端口不添加删除菜单
- if (m_infInfo->nRefCount == 0)
- {
- contextMenu->addAction(disableAction);
- }
-
- contextMenu->exec(QCursor::pos());
- }
- /// <summary>
- /// 菜单 - Link
- /// </summary>
- /// <param name="action"></param>
- void WindowAppItemInterface::onMenuLink(QAction* action)
- {
- QString strInfName = action->text();
- // 从Pou中找到相应的接口
- WindowAppItemInterface* linktoInfItem = m_pPou->GetInterfaceItemByName(strInfName);
- // 此处一定不为nullptr
- if (linktoInfItem != nullptr)
- {
- // 根据输入输出调整link方向
- if (this->m_infInfo->Direction == INF_DIRECTION::INF_DIR_OUT)
- {
- // 建立Link
- ((WindowAppPouScene*)scene())->addLink(this, linktoInfItem);
- }
- else
- {
- // 建立Link
- ((WindowAppPouScene*)scene())->addLink(linktoInfItem, this);
- }
- }
- }
- /// <summary>
- /// 菜单 - Unlink
- /// 无需检查引用计数,而且一个接口如果有多个link连线,一次性全部删除
- /// </summary>
- void WindowAppItemInterface::onMenuUnlink()
- {
- // 直接调用scene来清除连线相关信息
- ((WindowAppPouScene*)scene())->delLink(this);
- }
- /// <summary>
- /// 菜单 - Smartlink (只有输入端口可以执行,找离本接口最近的同类型输出端口,序号小于自己的)
- /// </summary>
- void WindowAppItemInterface::onMenuSmartlink()
- {
- // 如果本身已经处于link状态,则不处理
- if (this->m_infInfo->pUpLinkInterface != nullptr)
- {
- Utility::VPCriticalMessageBox("This interface is alreaday linked!");
- return;
- }
- // 调用scene()执行自动连接
- ((WindowAppPouScene*)scene())->smartLink(this);
- }
- /// <summary>
- /// 菜单 - Add Watch
- /// </summary>
- void WindowAppItemInterface::onMenuAddWatch()
- {
- }
- /// <summary>
- /// 菜单 - Add Port
- /// </summary>
- void WindowAppItemInterface::onMenuAddPort()
- {
- if (!m_bShowOnly)
- {
- // 由于Interface本身的图形已经和所属的Block整合到了一起,所以通过Interface的scenePos()获取的是其父block的Pos
- // 此处需要帮助外部函数提供一个本Interface的真实Pos
- QLineF realLine = QLineF(
- this->mapToScene(this->line().p1()),
- this->mapToScene(this->line().p2())
- );
- ((WindowAppPouScene*)scene())->addPortAndAutolink(this, realLine);
- }
- }
- /// <summary>
- /// 菜单 - Disable
- /// </summary>
- void WindowAppItemInterface::onMenuDisable()
- {
- // 首先检查引用计数
- int nRefCount = this->m_infInfo->nRefCount;
- if (nRefCount > 0)
- {
- Utility::VPCriticalMessageBox("Can't disable this interface for reference count is " + QString::number(nRefCount));
- return;
- }
- // 禁用此接口
- bool bRet = m_pPou->setInterfaceEnable(this->m_infInfo, false);
- if (!bRet)
- {
- Utility::VPCriticalMessageBox(
- "Can't disable this interface for reference count is " + QString::number(this->m_infInfo->nRefCount));
- return;
- }
- // 重新更新父接口
- // 由于只有Standard类型的会有此操作,所以直接通知Standard类型的父功能块重绘
- ((WindowAppBlockStandard*)parentItem())->updatePosition();
- // 重绘
- ((WindowAppPouScene*)scene())->update();
- }
- //void WindowAppItemInterface::mousePressEvent(QGraphicsSceneMouseEvent* mouseEvent)
- //{
- // // 切换scene的操作模式
- // (qobject_cast<WindowAppDiagramScene*>(scene()))->modeScene = MODE::LINK_MODE;
- //
- // qDebug() << "WindowAppItemInterface::mousePressEvent";
- //
- // QGraphicsLineItem::mousePressEvent(mouseEvent);
- //}
- // 悬停事件处理函数,外观效果
- void WindowAppItemInterface::hoverEnterEvent(QGraphicsSceneHoverEvent* event)
- {
- // qDebug("WindowAppItemInterface::hoverEnterEvent");
-
- if (m_infInfo &&
- ( m_infInfo->Type == INF_TYPE::INF_TYPE_STANDARD ||
- m_infInfo->Type == INF_TYPE::INF_TYPE_VALUE )
- )
- {
- // 2022-9-28,如果接口被废弃了,就不要再显示接口的值了,否则会崩溃
- if (m_infInfo->Discard != INF_DISCARD::INF_DEFAULT)
- {
- return;
- }
- QString strValue = m_infInfo->getValueString();
- QString strType = m_infInfo->strNameWithType;
- setToolTip(strType + "\r\nValue: " + strValue);
- }
- else
- {
- // 可以设置鼠标效果以及鼠标提示
- if (m_infInfo != nullptr)
- {
- QString strName = m_infInfo->strFullName;
- QString strType = m_infInfo->strNameWithType;
- setToolTip(strType + "\r\n" + strName);
- }
- }
- // if ((qobject_cast<WindowAppPouScene*>(scene()))->modeScene == MODE::LINK_MODE)
- // {
- // this->setSelected(true);
- // }
- QGraphicsLineItem::hoverEnterEvent(event);
- }
- //void WindowAppItemInterface::hoverMoveEvent(QGraphicsSceneHoverEvent* event)
- //{
- // qDebug("WindowAppItemInterface::hoverMoveEvent");
- //}
- //
- //void WindowAppItemInterface::hoverLeaveEvent(QGraphicsSceneHoverEvent* event)
- //{
- // qDebug("WindowAppItemInterface::hoverLeaveEvent");
- //
- // // setCursor(Qt::ArrowCursor);
- //
- // QGraphicsLineItem::hoverLeaveEvent(event);
- //}
- //void WindowAppItemInterface::mouseReleaseEvent(QGraphicsSceneMouseEvent* mouseEvent)
- //{
- // qDebug() << "WindowAppItemInterface::mouseReleaseEvent...";
- //
- // qDebug("%X", this);
- //
- // QGraphicsLineItem::mouseReleaseEvent(mouseEvent);
- //}
- //
- //bool WindowAppItemInterface::event(QEvent* e) {
- // if (e->type() == QEvent::ToolTip)
- // {
- // qDebug() << "tool tip show";
- // }
- // else if (e->type() == QEvent::Leave)
- // {
- // qDebug() << "tool tip leave";
- // }
- // return QGraphicsItem::event(e);
- //}
|