123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585 |
- #include "WindowAppBlockBase.h"
- #include "WindowAppItemInterface.h"
- #include "VPCommand.h"
- #include "Pou.h"
- #include "WindowAppPouScene.h"
- // extern WindowAppPouManager pouManager;
- WindowAppBlockBase::WindowAppBlockBase(
- TOOL* pTool,
- POU* Pou,
- bool bShowOnly,
- QGraphicsObject* parent
- ) :
- QGraphicsObject(parent)
- , m_toolInfo(pTool)
- , m_pPou(Pou)
- , m_bShowOnly(bShowOnly)
- , contextMenu(nullptr)
- , m_oldPos(0, 0)
- {
- // 创建右键菜单
- createContextMenu();
- }
- /// <summary>
- /// 绘制图形
- /// </summary>
- /// <param name="painter"></param>
- /// <param name="option"></param>
- /// <param name="widget"></param>
- void WindowAppBlockBase::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget)
- {
- Q_UNUSED(painter);
- Q_UNUSED(widget);
- Q_UNUSED(option);
- }
- /// <summary>
- /// 返回矩形区域
- /// </summary>
- /// <returns></returns>
- QRectF WindowAppBlockBase::boundingRect() const
- {
- return blockBoundingRect;
- }
- //////////////////////////////////////////////////////////
- // 绘制功能块
- void WindowAppBlockBase::DrawBlock(QPainter* painter)
- {
- // 边框
- if (!this->isSelected())
- {
- painter->setPen(QPen(COLOR_TBD_FRAME1, PEN_LINE_WIDTH));
- }
- else
- {
- painter->setPen(QPen(COLOR_TBD_FRAME1, PEN_LINE_WIDTH_SEL));
- }
- // 填充
- painter->setBrush(COLOR_TBD_BG);
- // 绘制主体
- painter->drawRect(blockRect);
- }
- ///////////////////////////////////////////////////
- // 绘制功能块阴影
- void WindowAppBlockBase::DrawBlockShadow(QPainter* painter)
- {
- // 三重阴影的颜色
- QColor colorShadow[TBD_SHADOW_COUNT];
- colorShadow[0] = COLOR_TBD_SHADOW1;
- colorShadow[1] = COLOR_TBD_SHADOW2;
- colorShadow[2] = COLOR_TBD_SHADOW3;
- for (int i = 1; i <= TBD_SHADOW_COUNT; i++)
- {
- // 偏移
- int offset = i * PEN_LINE_WIDTH;
- painter->setPen(QPen(colorShadow[i - 1], PEN_LINE_WIDTH));
- painter->drawLine(
- QPoint(
- blockRect.right() + offset,
- blockRect.y() + offset
- ),
- QPoint(
- blockRect.right() + offset,
- blockRect.bottom() + offset
- )
- );
- painter->drawLine(
- QPoint(
- blockRect.x() + offset,
- blockRect.bottom() + offset
- ),
- QPoint(
- blockRect.right() + offset,
- blockRect.bottom() + offset
- )
- );
- }
- // 三重阴影的顶点颜色
- QColor colorCorner[TBD_SHADOW_COUNT];
- colorCorner[0] = COLOR_TBD_SHADOW_CORNER1;
- colorCorner[1] = COLOR_TBD_SHADOW_CORNER2;
- colorCorner[2] = COLOR_TBD_SHADOW_CORNER3;
- for (int i = 1; i <= TBD_SHADOW_COUNT; i++)
- {
- // 偏移
- int offset = i * PEN_LINE_WIDTH;
- painter->setPen(QPen(colorCorner[i - 1], PEN_LINE_WIDTH));
- painter->drawPoint(
- QPoint(
- blockRect.right() + offset,
- blockRect.bottom() + offset
- )
- );
- }
- }
- /// <summary>
- /// 更新ItemInterface的位置
- /// </summary>
- /// <param name="blockRect"></param>
- void WindowAppBlockBase::updateInterfacesPostion()
- {
- // (注意此处坐标系需要转换一下)
- QPointF pt = mapToScene(0, 0);
- QRectF rcBlock = blockRect;
- rcBlock.translate(pt);
- // 根据矩形区域计算对应的Interface的位置
- int outCount = 0, inCount = 0;
- for (WindowAppItemInterface* pItemInf : qAsConst(m_itemInterfaces))
- {
- if (!m_bShowOnly && !pItemInf->m_infInfo->bEnable)
- {
- continue;
- }
- // 2022-5-23, 跳过ToolStart接口
- if (pItemInf->m_infInfo->isToolStart()
- || pItemInf->m_infInfo->isToolEnd())
- {
- continue;
- }
- // 为接口更新最新的父功能块区域尺寸
- pItemInf->updateParentRect(rcBlock);
- // 输出接口
- if (pItemInf->m_infInfo->Direction == INF_DIRECTION::INF_DIR_OUT)
- {
- pItemInf->updatePostion(outCount);
- outCount++;
- }
- else if (pItemInf->m_infInfo->Direction == INF_DIRECTION::INF_DIR_IN)
- {
- pItemInf->updatePostion(inCount);
- inCount++;
- }
- }
- }
- ///// <summary>
- ///// 更新单个Interface的位置
- ///// </summary>
- ///// <param name="pInfItem"></param>
- //void WindowAppBlockBase::updateInterfacePostion(WindowAppItemInterface* pInfItem)
- //{
- //
- //}
- /// <summary>
- /// 重绘所有的Interface
- /// </summary>
- void WindowAppBlockBase::redrawAllInterface()
- {
- for (WindowAppItemInterface* pItemInf : qAsConst(m_itemInterfaces))
- {
- pItemInf->update();
- }
- }
- /// <summary>
- /// 显示右键菜单
- /// </summary>
- /// <param name="event"></param>
- void WindowAppBlockBase::contextMenuEvent(QGraphicsSceneContextMenuEvent* event)
- {
- if (!isSelected())
- {
- scene()->clearSelection();
- setSelected(true);
- }
- // 如果不是仅供展示用时,才弹出右键菜单
- if (!m_bShowOnly)
- {
- if (contextMenu != nullptr)
- {
- contextMenu->exec(event->screenPos());
- }
- }
- }
- /// <summary>
- /// 功能块有变动时
- /// </summary>
- /// <param name="change"></param>
- /// <param name="value"></param>
- /// <returns></returns>
- QVariant WindowAppBlockBase::itemChange(GraphicsItemChange change, const QVariant& value)
- {
- if (change == QGraphicsItem::ItemPositionChange && scene())
- {
- // 更新Interface的位置(此处Qt自动处理了,不需要额外处理)
- // WindowAppBlockBase::updateAllInterfacesPostion(blockRect);
- // qDebug() << "WindowAppBlockTool::itemChange";
- //// 功能块移动时,通知对应的Interface以及Interface的link同步移动
- //emit blockMoveSignal(this);
- }
- // 移动完毕之后,执行位置检测
- else if (change == QGraphicsItem::ItemPositionHasChanged && scene())
- {
- // 功能块移动完毕后,通知对应的Interface以及Interface的link同步移动
- emit blockMoveSignal(this);
- // 位置检测
- WindowAppBlockBase::checkPosition(value);
- }
- else if (change == QGraphicsItem::ItemSelectedChange)
- {
- // 如果选中状态变更的话,就重绘所有的Interface
- WindowAppBlockBase::redrawAllInterface();
- }
- return QGraphicsItem::itemChange(change, value);
- }
- /// <summary>
- /// 初始化功能块的右键菜单Action
- /// </summary>
- void WindowAppBlockBase::createContextMenu()
- {
- // 硬件组态不显示右键菜单
- if (m_pPou->pouName() != GROUP_NAME_HARDWARE)
- {
- executeAction = new QAction(QIcon(":/image/Execute.png"), ("&Execute"), this);
- executeAction->setShortcut(QStringLiteral("Ctrl+F5"));
- executeAction->setStatusTip(("Execute this tool"));
- executeSubAction = new QAction(("&Execute Subsequent"), this);
- executeSubAction->setStatusTip(("Execute from this tool"));
- executeAllAction = new QAction(("&Execute All"), this);
- executeAllAction->setStatusTip(("Execute all tools"));
- executeBreakPoint = new QAction(("&BreakPoint"), this);
- executeBreakPoint->setStatusTip(("BreakPoint"));
- moveUpAction = new QAction(QIcon(":/image/MoveUp.png"), ("Move Up"), this);
- moveUpAction->setStatusTip(("Move up tool from diagram"));
- moveDownAction = new QAction(QIcon(":/image/MoveDown.png"), ("Move Down"), this);
- moveDownAction->setStatusTip(("Move down tool from diagram"));
- moveFirstAction = new QAction(QIcon(":/image/MoveFirst.png"), ("Move First"), this);
- moveFirstAction->setStatusTip(("Move first tool from diagram"));
- moveLastAction = new QAction(QIcon(":/image/MoveLast.png"), ("MoveLast"), this);
- moveLastAction->setStatusTip(("Move last tool from diagram"));
- }
- deleteAction = new QAction(QIcon(":/image/Delete.png"), ("&Delete"), this);
- deleteAction->setStatusTip(("Delete item from diagram"));
- propertyAction = new QAction(("&Property"), this);
- propertyAction->setStatusTip(("Property of this item"));
- copyBlockAction = new QAction(("Copy block"), this);
- copyDataAction = new QAction(("Copy data"), this);
- pasteAction = new QAction(("Paste"), this);
- }
- /// <summary>
- /// 返回本功能块的引用计数(所有接口引用计数之和)
- /// </summary>
- /// <returns></returns>
- int WindowAppBlockBase::getRefCount()
- {
- int nRefCount = 0;
- for (WindowAppItemInterface* pItemInf : qAsConst(m_itemInterfaces))
- {
- nRefCount += pItemInf->m_infInfo->nRefCount;
- }
- return nRefCount;
- }
- /// <summary>
- /// // 是否可以被删除(引用计数=0,且没有被Task使用)
- /// </summary>
- /// <returns></returns>
- bool WindowAppBlockBase::couldBeDeleted()
- {
- // 首先需要查询一下引用计数
- int nRefCount = this->getRefCount();
- if (nRefCount > 0)
- {
- Utility::VPCriticalMessageBox("Can't delete this block for reference count is " + QString::number(nRefCount));
- return false;
- }
- // 2021-8-12增加,还需要检查本Pou是否被Task选用,如果选用则不允许删除
- if (this->m_pPou->isRunningInTask())
- {
- Utility::VPCriticalMessageBox("Can't delete this block : this block is running in task[" + m_pPou->m_pParentTask->strName + "]");
- return false;
- }
- return true;
- }
- /// <summary>
- /// 2021-8-17 检查功能块位置(碰撞检测,限制移动范围)
- /// </summary>
- /// <param name="value"></param>
- /// <returns></returns>
- QVariant WindowAppBlockBase::checkPosition(const QVariant& value)
- {
- // 最新中心点位置
- QPointF curPos = value.toPointF();
- // 碰撞检测
- bool bFix = checkCollision();
- bFix = false; //暂时屏蔽碰撞
- if (bFix)
- {
- // 恢复上次的位置
- this->setPos(m_fixPos);
- return value;
- }
- // 碰撞检测如果没有变更功能块位置,然后继续做边界检测
- bFix = restrictBlockPos(curPos);
- bFix = false; // 暂时屏蔽边界检测
- if (bFix)
- {
- // 恢复上次的位置
- this->setPos(m_fixPos);
- }
- else
- {
- // 如果不需要调整,则保存最新的位置
- m_fixPos = value.toPointF();
- }
- return value;
- }
- /// <summary>
- /// 2021-8-17 处理碰撞判断
- /// </summary>
- /// <param name="value"></param>
- /// <returns>返回是否做出了变更</returns>
- bool WindowAppBlockBase::checkCollision()
- {
- // 整个场景区域
- QRectF rcScene = scene()->sceneRect();
- // 获取界面中和本功能块产生碰撞的物体
- QList<QGraphicsItem*> listCollision = scene()->collidingItems(this);
- // 需要排除自身的interface,因为Interface和功能块本身存在碰撞
- for (QGraphicsItem* pItem : listCollision)
- {
- if (pItem->type() != ITEM_TYPE_STANDARD
- && pItem->type() != ITEM_TYPE_PORT)
- {
- listCollision.removeOne(pItem);
- }
- }
- // 判断是否还有碰撞
- if (!listCollision.isEmpty())
- {
- return true;
- }
- return false;
- }
- /// <summary>
- /// 2021-8-17 限制功能块在场景内
- /// </summary>
- /// <param name="value"></param>
- /// <returns>返回是否做出了变更</returns>
- bool WindowAppBlockBase::restrictBlockPos(QPointF curPos)
- {
- // 整个场景区域
- QRectF rcScene = scene()->sceneRect();
- // 重新计算最新的功能块矩形区域(含Interface)
- QRectF blockTotalRect;
- if (this->type() == ITEM_TYPE_STANDARD)
- {
- blockTotalRect.setRect(
- (double)curPos.x() - (double)(blockRect.width() / 2.0) - (double)TBD_INF_LINE - 8.0,
- (double)curPos.y() - (double)(blockRect.height() / 2.0) - (double)TBD_INDEX_HEIGHT,
- (double)blockRect.width() + (double)(TBD_INF_LINE * 3.0) + 5.0,
- (double)blockRect.height() + (double)TBD_INDEX_HEIGHT + (double)(TBD_SHADOW_COUNT * PEN_LINE_WIDTH) + 15.0
- );
- }
- else if (this->type() == ITEM_TYPE_PORT)
- {
- blockTotalRect.setRect(
- (double)curPos.x() - (double)(blockRect.width() / 2.0) - TBD_INF_LINE - 8,
- (double)curPos.y() - (double)blockRect.height() - 5.0,
- (double)blockRect.width() + (double)(TBD_INF_LINE * 3.0),
- (double)blockRect.height() + (double)TBD_INDEX_HEIGHT
- );
- }
- else
- {
- return false;
- }
- // 判断场景是否包含此矩形区域
- if (rcScene.contains(blockTotalRect))
- {
- //// 如果不需要调整,则保存最新的位置
- //m_fixPos = value.toPointF();
- // qDebug() << blockTotalRect << " pass last:" << m_fixPos;;
- return false;
- }
- else
- {
- // qDebug() << blockTotalRect << " restrict resotre to " << m_fixPos;
- //if (m_fixPos == QPointF(0.0, 0.0))
- //{
- // return false;
- //}
- //// 恢复上次的位置
- //this->setPos(m_fixPos);
- return true;
- }
- }
- /// <summary>
- /// 2022-10-4,删除当前功能块(统一功能块的删除入口)
- /// </summary>
- void WindowAppBlockBase::onDeleteItem()
- {
- //// 2022-10-2,为了整合进Undo架构,改为由Scene统一删除
- //m_pPou->parentScene()->delToolItem(this);
- // 生成删除指令,调用Undo体系进行删除
- PouToolDelCommand* toolDelCommand = new PouToolDelCommand(
- (WindowAppPouScene*)this->scene(),
- this->m_toolInfo,
- this->scenePos()
- );
- ((WindowAppPouScene*)scene())->m_CommandManager.executeCommand(toolDelCommand);
- }
- /// <summary>
- /// 鼠标左键按下
- /// </summary>
- /// <param name="event"></param>
- void WindowAppBlockBase::mousePressEvent(QGraphicsSceneMouseEvent* event)
- {
- //设置鼠标形状
- // TODO: 2022-4-22为了方便功能块调试,临时屏蔽
- // setCursor(Qt::ClosedHandCursor);
- // 图元多选 系统默认Ctrl + 鼠标左键可实现多选
- if (event->button() == Qt::LeftButton)
- {
- // 2022-10-2,按下时记录功能块当前位置,用于比较鼠标抬起后是否移动
- m_oldPos = event->scenePos();
- //设置shift+鼠标左键单选
- if (event->modifiers() == Qt::ShiftModifier)
- {
- setSelected(true);
- }
- else
- {
- QGraphicsItem::mousePressEvent(event);
- }
- }
- }
- /// <summary>
- /// 鼠标右键抬起
- /// </summary>
- /// <param name="event"></param>
- void WindowAppBlockBase::mouseReleaseEvent(QGraphicsSceneMouseEvent* event)
- {
- if (event->button() == Qt::LeftButton)
- {
- // 2022-10-2,抬起时记录功能块当前位置,用于比较鼠标抬起后是否移动
- QPointF curPos = event->scenePos();
- // 如果移动了,则记录这次动作,用于执行Redo
- if (curPos != m_oldPos)
- {
- PouToolMoveCommand* toolMoveCommand = new PouToolMoveCommand(
- this->m_pPou,
- this->m_toolInfo->strInstanceName,
- m_oldPos,
- curPos
- );
- ((WindowAppPouScene*)scene())->m_CommandManager.executeCommand(toolMoveCommand, true);
- m_oldPos = curPos;
- }
- }
- QGraphicsItem::mouseReleaseEvent(event);
- }
- /// <summary>
- /// 2022-6-22 查找某个InferfaceItem是否在本Block内
- /// </summary>
- /// <param name="infItem"></param>
- /// <returns></returns>
- bool WindowAppBlockBase::isInBlock(WindowAppItemInterface* infItem)
- {
- int nIndex = m_itemInterfaces.indexOf(infItem);
- if (nIndex >= 0)
- {
- return true;
- }
- else
- {
- return false;
- }
- }
|