#include "QtNodeGraphicsObject.hpp"#include <iostream>#include <cstdlib>#include <QtWidgets/QtWidgets>#include <QtWidgets/QGraphicsEffect>#include "QtConnectionGraphicsObject.hpp"#include "QtFlowScene.hpp"#include "QtNode.hpp"#include "QtNodeDataModel.hpp"#include "QtInteraction.hpp"#include "QtStyle.hpp"#include "qtextoption.h"#include <QtSvg/QSvgRenderer>namespace Qt{void HotkeyButton::setTransform(QPointF ori, unsigned int x, unsigned int y){this->mSize = QSize(x,y);this->mOrigin = ori;}void HotkeyButton::setSize(unsigned int x, unsigned int y){this->mSize = QSize(x, y);}bool HotkeyButton::isPointInButton(const QPointF& point) {return (point.x() >= mOrigin.x() && point.x() < mOrigin.x() + mSize.width()*scaleX &&point.y() >= mOrigin.y() && point.y() < mOrigin.y() + mSize.height());}bool HotkeyButton::isChecked(){if (mCheckedFunc == nullptr)return mDefaultChecked;return mCheckedFunc();}void HotkeyButton::setState(HotkeyState state){mState = state;if (mState == checkedState)mDefaultChecked = true;else if (mState == defaultState)mDefaultChecked = false;}void HotkeyButton::setUserPolicy(std::function<bool()> policy){mCheckedFunc = policy;}bool HotkeyButton::mouseHover(const QPointF& point){if (mMode == checkedMode && isChecked())return false;bool success = this->isPointInButton(point);if (success){this->setState(hoverState);return true;}else{if (mMode == checkedMode){this->setState(defaultState);}else if (mMode == clickMode){this->setState(defaultState);}}return false;}bool HotkeyButton::mouseClick(const QPointF& point){bool success = this->isPointInButton(point);if (success){this->setState(clickState);return true;}return false;};void HotkeyButton::leaveWidget(){if (mMode == clickMode)this->setState(defaultState);else if (mMode == checkedMode){if(isChecked())this->setState(checkedState);elsethis->setState(defaultState);}}bool HotkeyButton::mouseRelease(const QPointF& point){bool success = this->isPointInButton(point);if (success){if (mMode == checkedMode){if (isChecked())this->setState(defaultState);elsethis->setState(checkedState);}else if (mMode == clickMode){mState = defaultState;}return true;}return false;}const char* HotkeyButton::getIcon(){if(isChecked())return mCheckedIcon.c_str();switch (mState){case Qt::HotkeyButton::hoverState:return mHoverIcon.c_str();break;case Qt::HotkeyButton::clickState:return mClickIcon.c_str();break;default:return mDefaultIcon.c_str();break;}return nullptr;}void HotkeyButton::setIconsPath(const char* defaultIcon, const char* checkedIcon, const char* hoverIcon, const char* clickIcon){mDefaultIcon = defaultIcon;mCheckedIcon = checkedIcon;mHoverIcon = hoverIcon;mClickIcon = clickIcon;}voidQtNodePainter::paint(QPainter* painter,QtNode & node,QtFlowScene const& scene){NodeGeometry const& geom = node.nodeGeometry();NodeState const& state = node.nodeState();QtNodeGraphicsObject const & graphicsObject = node.nodeGraphicsObject();geom.recalculateSize(painter->font());//--------------------------------------------QtNodeDataModel const * model = node.nodeDataModel();drawNodeRect(painter, geom, model, graphicsObject);drawHotKeys(painter, geom, model, graphicsObject);drawConnectionPoints(painter, geom, state, model, scene);//drawFilledConnectionPoints(painter, geom, state, model);drawModelName(painter, geom, state, model);drawEntryLabels(painter, geom, state, model);drawResizeRect(painter, geom, model);drawValidationRect(painter, geom, model, graphicsObject);/// call custom painterif (auto painterDelegate = model->painterDelegate()){painterDelegate->paint(painter, geom, model);}}voidQtNodePainter::drawNodeRect(QPainter* painter,NodeGeometry const& geom,QtNodeDataModel const* model,QtNodeGraphicsObject const & graphicsObject){NodeStyle const& nodeStyle = model->nodeStyle();auto color = graphicsObject.isSelected()? nodeStyle.SelectedBoundaryColor: nodeStyle.NormalBoundaryColor;if (geom.hovered()){QPen p(color, nodeStyle.HoveredPenWidth);painter->setPen(p);}else{QPen p(color, nodeStyle.PenWidth);painter->setPen(p);}float diam = nodeStyle.ConnectionPointDiameter;double const radius = 6.0;QRectF boundary = model->captionVisible() ? QRectF(-diam, -diam, 2.0 * diam + geom.width(), 2.0 * diam + geom.height()): QRectF(-diam, 0.0f, 2.0 * diam + geom.width(), diam + geom.height());if (model->captionVisible()){QLinearGradient gradient(QPointF(0.0, 0.0),QPointF(0.0, geom.height()));unsigned int captionHeight = geom.captionHeight();qreal captionRatio = (qreal)captionHeight / geom.height();gradient.setColorAt(0.0, nodeStyle.GradientColor0);gradient.setColorAt(captionRatio, nodeStyle.GradientColor0);gradient.setColorAt(captionRatio + 0.001, nodeStyle.GradientColor1);gradient.setColorAt(0.98, nodeStyle.GradientColor2);gradient.setColorAt(1.0, nodeStyle.GradientColor3);painter->setBrush(gradient);painter->drawRoundedRect(boundary, radius, radius);painter->setPen(QPen(color, nodeStyle.PenWidth));painter->drawLine(QPointF(-diam, geom.captionHeight()), QPointF(diam + geom.width(), geom.captionHeight()));}else{QLinearGradient gradient(QPointF(0.0, 0.0),QPointF(2.0, geom.height()));gradient.setColorAt(0.0, nodeStyle.GradientColor0);gradient.setColorAt(0.03, nodeStyle.GradientColor1);gradient.setColorAt(0.97, nodeStyle.GradientColor2);gradient.setColorAt(1.0, nodeStyle.GradientColor3);painter->setBrush(gradient);painter->drawRoundedRect(boundary, radius, radius);}}void QtNodePainter::drawHotKeys(QPainter* painter,NodeGeometry const& geom,QtNodeDataModel const* model,QtNodeGraphicsObject const & graphicsObject){NodeStyle const& nodeStyle = model->nodeStyle();auto color = graphicsObject.isSelected()? nodeStyle.SelectedBoundaryColor: nodeStyle.NormalBoundaryColor;const QPen& pen = painter->pen();if (model->captionVisible() && model->hotkeyEnabled()) {float diam = nodeStyle.ConnectionPointDiameter;unsigned int captionHeight = geom.captionHeight();painter->setPen(QPen(color, nodeStyle.PenWidth));{unsigned int buttonSize = captionHeight + diam;unsigned int iconSize = 0.8 * buttonSize;QPointF barLine[2];unsigned int barYCoord = geom.height() - captionHeight;barLine[0] = QPointF(-diam, barYCoord);barLine[1] = QPointF(geom.width() + diam, barYCoord);painter->drawPolyline(barLine, 2);auto& buttons = geom.constHotkeyButtons();for (size_t i = 0; i < buttons.size(); i++){auto buttonOrigin = buttons[i]->getOrigin();QPointF p2 = QPointF(buttonOrigin.x(), buttonOrigin.y() + buttons[i]->getSize().height());barLine[0] = buttonOrigin;barLine[1] = p2;painter->drawPolyline(barLine, 2);unsigned int iconOffset = (buttonSize - iconSize)/2;QPointF imageCoord = QPointF(buttonOrigin.x() + iconOffset, barYCoord + iconOffset);QSvgRenderer renderer(QString(buttons[i]->getIcon()));QPixmap pixmap(iconSize, iconSize);pixmap.fill(Qt::transparent);QPainter iconPainter(&pixmap);iconPainter.setRenderHints(QPainter::Antialiasing);renderer.render(&iconPainter);painter->drawPixmap(imageCoord, pixmap);}}}}voidQtNodePainter::drawConnectionPoints(QPainter* painter,NodeGeometry const& geom,NodeState const& state,QtNodeDataModel const * model,QtFlowScene const & scene){NodeStyle const& nodeStyle = model->nodeStyle();auto const &connectionStyle = StyleCollection::connectionStyle();float diameter = nodeStyle.ConnectionPointDiameter;auto reducedDiameter = diameter * 0.6;for (PortType portType : {PortType::Out, PortType::In}){size_t n = state.getEntries(portType).size();for (unsigned int i = 0; i < n; ++i){QPointF p = geom.portScenePosition(i, portType);auto const & dataType = model->dataType(portType, i);bool canConnect = (state.getEntries(portType)[i].empty() ||(portType == PortType::Out &&model->portOutConnectionPolicy(i) == QtNodeDataModel::ConnectionPolicy::Many));double r = 1.0;if (state.isReacting() &&canConnect &&portType == state.reactingPortType()){auto diff = geom.draggingPos() - p;double dist = std::sqrt(QPointF::dotProduct(diff, diff));bool typeConvertable = false;{if (portType == PortType::In){typeConvertable = scene.registry().getTypeConverter(state.reactingDataType(), dataType) != nullptr;}else{typeConvertable = scene.registry().getTypeConverter(dataType, state.reactingDataType()) != nullptr;}}if (state.reactingDataType().id == dataType.id || typeConvertable){double const thres = 40.0;r = (dist < thres) ?(2.0 - dist / thres) :1.0;}else{double const thres = 80.0;r = (dist < thres) ?(dist / thres) :1.0;}}//TODO: change the ports appearance according to the connection statesif (connectionStyle.useDataDefinedColors()){painter->setBrush(connectionStyle.normalColor(dataType.id));}else{painter->setBrush(nodeStyle.ConnectionPointColor);}// if (connectionStyle.useDataDefinedColors())// {// painter->setPen(QPen(connectionStyle.normalColor(dataType.id), 1, Qt::SolidLine));// }// else// {// painter->setPen(QPen(nodeStyle.ConnectionPointColor, 1, Qt::SolidLine));// }qreal w = diameter * 0.4 * r;qreal h = diameter * 0.8 * r;QPointF vert[5];vert[0] = p + QPointF(-w, -h);vert[1] = p + QPointF(-w, h);vert[2] = p + QPointF(w, h);vert[3] = p + QPointF(2.5*w, 0.0);vert[4] = p + QPointF(w, -h);qreal dr = diameter * 1 * r;QPointF arrow[3];arrow[0] = p + QPointF(0, dr);arrow[1] = p + QPointF(dr, 0);arrow[2] = p + QPointF(0, -dr);qreal odr = diameter * 1.1 * r;qreal idr = diameter * 0.3 * r;QPointF diamond_out[4];diamond_out[0] = p + QPointF(0, odr);diamond_out[1] = p + QPointF(odr, 0);diamond_out[2] = p + QPointF(0, -odr);diamond_out[3] = p + QPointF(-odr, 0);QPointF diamond_inner[4];diamond_inner[0] = p + QPointF(0, idr);diamond_inner[1] = p + QPointF(idr, 0);diamond_inner[2] = p + QPointF(0, -idr);diamond_inner[3] = p + QPointF(-idr, 0);switch (dataType.shape){case PortShape::Point:painter->drawEllipse(p,reducedDiameter * r,reducedDiameter * r);break;case PortShape::Diamond:painter->drawConvexPolygon(diamond_out, 4);painter->setBrush(Qt:: black);painter->drawConvexPolygon(diamond_inner, 4);break;case PortShape::Arrow:painter->drawConvexPolygon(arrow, 3);break;default:break;}}};}voidQtNodePainter::drawFilledConnectionPoints(QPainter * painter,NodeGeometry const & geom,NodeState const & state,QtNodeDataModel const * model){NodeStyle const& nodeStyle = model->nodeStyle();auto const & connectionStyle = StyleCollection::connectionStyle();auto diameter = nodeStyle.ConnectionPointDiameter;for (PortType portType : {PortType::Out, PortType::In}){size_t n = state.getEntries(portType).size();for (size_t i = 0; i < n; ++i){QPointF p = geom.portScenePosition((PortIndex)i, portType);if (!state.getEntries(portType)[i].empty()){auto const & dataType = model->dataType(portType, (PortIndex)i);if (connectionStyle.useDataDefinedColors()){QColor const c = connectionStyle.normalColor(dataType.id);painter->setPen(c);painter->setBrush(c);}else{painter->setPen(nodeStyle.FilledConnectionPointColor);painter->setBrush(nodeStyle.FilledConnectionPointColor);}painter->drawEllipse(p,diameter * 0.4,diameter * 0.4);}}}}voidQtNodePainter::drawModelName(QPainter * painter,NodeGeometry const & geom,NodeState const & state,QtNodeDataModel const * model){NodeStyle const& nodeStyle = model->nodeStyle();Q_UNUSED(state);if (!model->captionVisible())return;QString const &name = model->caption();QFont f = painter->font();f.setBold(true);QFontMetrics metrics(f);auto rect = metrics.boundingRect(name);// QPointF position((geom.width() - rect.width()) / 2.0,// (geom.spacing() + geom.entryHeight()) / 3.0);QPointF position(geom.captionHeight() / 2,(geom.spacing() + geom.entryHeight()) / 3.0);painter->setFont(f);painter->setPen(nodeStyle.FontColor);painter->drawText(position, name);f.setBold(false);painter->setFont(f);}voidQtNodePainter::drawEntryLabels(QPainter * painter,NodeGeometry const & geom,NodeState const & state,QtNodeDataModel const * model){QFontMetrics const & metrics =painter->fontMetrics();for (PortType portType : {PortType::Out, PortType::In}){auto const &nodeStyle = model->nodeStyle();auto& entries = state.getEntries(portType);size_t n = entries.size();for (size_t i = 0; i < n; ++i){QPointF p = geom.portScenePosition((PortIndex)i, portType);if (entries[i].empty())painter->setPen(nodeStyle.FontColorFaded);elsepainter->setPen(nodeStyle.FontColor);QString s;if (model->portCaptionVisible(portType, (PortIndex)i)){s = model->portCaption(portType, (PortIndex)i);}else{s = model->dataType(portType, (PortIndex)i).name;}auto rect = metrics.boundingRect(s);p.setY(p.y() + rect.height() / 4.0);switch (portType){case PortType::In:p.setX(5.0);break;case PortType::Out:p.setX(geom.width() - 5.0 - rect.width());break;default:break;}painter->drawText(p, s);}}}voidQtNodePainter::drawResizeRect(QPainter * painter,NodeGeometry const & geom,QtNodeDataModel const * model){if (model->resizable()){painter->setBrush(Qt::gray);painter->drawEllipse(geom.resizeRect());}}voidQtNodePainter::drawValidationRect(QPainter * painter,NodeGeometry const & geom,QtNodeDataModel const * model,QtNodeGraphicsObject const & graphicsObject){auto modelValidationState = model->validationState();if (modelValidationState != NodeValidationState::Valid){NodeStyle const& nodeStyle = model->nodeStyle();auto color = graphicsObject.isSelected()? nodeStyle.SelectedBoundaryColor: nodeStyle.NormalBoundaryColor;if (geom.hovered()){QPen p(color, nodeStyle.HoveredPenWidth);painter->setPen(p);}else{QPen p(color, nodeStyle.PenWidth);painter->setPen(p);}//Drawing the validation message backgroundif (modelValidationState == NodeValidationState::Error){painter->setBrush(nodeStyle.ErrorColor);}else{painter->setBrush(nodeStyle.WarningColor);}double const radius = 3.0;float diam = nodeStyle.ConnectionPointDiameter;QRectF boundary(-diam,-diam + geom.height() - geom.validationHeight(),2.0 * diam + geom.width(),2.0 * diam + geom.validationHeight());painter->drawRoundedRect(boundary, radius, radius);painter->setBrush(Qt::gray);//Drawing the validation message itselfQString const &errorMsg = model->validationMessage();QFont f = painter->font();QFontMetrics metrics(f);auto rect = metrics.boundingRect(errorMsg);QPointF position((geom.width() - rect.width()) / 2.0,geom.height() - (geom.validationHeight() - diam) / 2.0);painter->setFont(f);painter->setPen(nodeStyle.FontColor);painter->drawText(position, errorMsg);}}QtNodeGraphicsObject::QtNodeGraphicsObject(QtFlowScene &scene,QtNode& node): _scene(scene), _node(node), _locked(false), _proxyWidget(nullptr){_scene.addItem(this);setFlag(QGraphicsItem::ItemDoesntPropagateOpacityToChildren, true);setFlag(QGraphicsItem::ItemIsMovable, true);setFlag(QGraphicsItem::ItemIsFocusable, true);setFlag(QGraphicsItem::ItemIsSelectable, true);setFlag(QGraphicsItem::ItemSendsScenePositionChanges, true);setCacheMode(QGraphicsItem::DeviceCoordinateCache);auto const &nodeStyle = node.nodeDataModel()->nodeStyle();{auto effect = new QGraphicsDropShadowEffect;effect->setOffset(4, 4);effect->setBlurRadius(20);effect->setColor(nodeStyle.ShadowColor);setGraphicsEffect(effect);}setOpacity(nodeStyle.Opacity);setAcceptHoverEvents(true);setZValue(0);embedQWidget();// connect to the move signals to emit the move signals in FlowSceneauto onMoveSlot = [this] {_scene.nodeMoved(_node, pos());};connect(this, &QGraphicsObject::xChanged, this, onMoveSlot);connect(this, &QGraphicsObject::yChanged, this, onMoveSlot);}QtNodeGraphicsObject::~QtNodeGraphicsObject(){_scene.removeItem(this);}QtNode&QtNodeGraphicsObject::node(){return _node;}QtNode const&QtNodeGraphicsObject::node() const{return _node;}voidQtNodeGraphicsObject::embedQWidget(){NodeGeometry & geom = _node.nodeGeometry();if (auto w = _node.nodeDataModel()->embeddedWidget()){_proxyWidget = new QGraphicsProxyWidget(this);_proxyWidget->setWidget(w);_proxyWidget->setPreferredWidth(5);geom.recalculateSize();if (w->sizePolicy().verticalPolicy() & QSizePolicy::ExpandFlag){// If the widget wants to use as much vertical space as possible, set it to have the geom's equivalentWidgetHeight._proxyWidget->setMinimumHeight(geom.equivalentWidgetHeight());}_proxyWidget->setPos(geom.widgetPosition());update();_proxyWidget->setOpacity(1.0);_proxyWidget->setFlag(QGraphicsItem::ItemIgnoresParentOpacity);}}QRectFQtNodeGraphicsObject::boundingRect() const{return _node.nodeGeometry().boundingRect();}voidQtNodeGraphicsObject::setGeometryChanged(){prepareGeometryChange();}voidQtNodeGraphicsObject::moveConnections() const{NodeState const & nodeState = _node.nodeState();for (PortType portType : {PortType::In, PortType::Out}){auto const & connectionEntries =nodeState.getEntries(portType);for (auto const & connections : connectionEntries){for (auto & con : connections)con.second->getConnectionGraphicsObject().move();}}}voidQtNodeGraphicsObject::lock(bool locked){_locked = locked;setFlag(QGraphicsItem::ItemIsMovable, !locked);setFlag(QGraphicsItem::ItemIsFocusable, !locked);setFlag(QGraphicsItem::ItemIsSelectable, !locked);}voidQtNodeGraphicsObject::paint(QPainter * painter,QStyleOptionGraphicsItem const* option,QWidget*){painter->setClipRect(option->exposedRect);_defaultPainter = painter;QtNodePainter::paint(painter, _node, _scene);}QVariantQtNodeGraphicsObject::itemChange(GraphicsItemChange change, const QVariant &value){if (change == ItemPositionChange && scene()){moveConnections();}return QGraphicsItem::itemChange(change, value);}voidQtNodeGraphicsObject::mousePressEvent(QGraphicsSceneMouseEvent * event){auto model = _node.nodeDataModel();if (model->captionVisible() && event->button() == Qt::LeftButton){_node.nodeGeometry().updateMousePress(event->pos());}if (_locked)return;// deselect all other items after this one is selectedif (!isSelected() &&!(event->modifiers() & Qt::ControlModifier)){_scene.clearSelection();}for (PortType portToCheck : {PortType::In, PortType::Out}){NodeGeometry const & nodeGeometry = _node.nodeGeometry();// TODO do not pass sceneTransformint const portIndex = nodeGeometry.checkHitScenePoint(portToCheck,event->scenePos(),sceneTransform());if (portIndex != INVALID_PORT){NodeState const & nodeState = _node.nodeState();std::unordered_map<QUuid, QtConnection*> connections =nodeState.connections(portToCheck, portIndex);// start dragging existing connectionif (!connections.empty() && portToCheck == PortType::In){auto con = connections.begin()->second;QtInteraction interaction(_node, *con, _scene);interaction.disconnect(portToCheck);}else // initialize new QtConnection{if (portToCheck == PortType::Out){auto const outPolicy = _node.nodeDataModel()->portOutConnectionPolicy(portIndex);if (!connections.empty() &&outPolicy == QtNodeDataModel::ConnectionPolicy::One){_scene.deleteConnection(*connections.begin()->second);}}// todo add to FlowSceneauto connection = _scene.createConnection(portToCheck,_node,portIndex);_node.nodeState().setConnection(portToCheck,portIndex,*connection);connection->getConnectionGraphicsObject().grabMouse();}}}auto pos = event->pos();auto & geom = _node.nodeGeometry();auto & state = _node.nodeState();if (_node.nodeDataModel()->resizable() &&geom.resizeRect().contains(QPoint(pos.x(),pos.y()))){state.setResizing(true);}hideTipsAndTimer();}voidQtNodeGraphicsObject::mouseMoveEvent(QGraphicsSceneMouseEvent * event){auto & geom = _node.nodeGeometry();auto & state = _node.nodeState();if (state.resizing()){auto diff = event->pos() - event->lastPos();if (auto w = _node.nodeDataModel()->embeddedWidget()){prepareGeometryChange();auto oldSize = w->size();oldSize += QSize(diff.x(), diff.y());w->setFixedSize(oldSize);_proxyWidget->setMinimumSize(oldSize);_proxyWidget->setMaximumSize(oldSize);_proxyWidget->setPos(geom.widgetPosition());geom.recalculateSize();update();moveConnections();event->accept();}}else{QGraphicsObject::mouseMoveEvent(event);if (event->lastPos() != event->pos())moveConnections();event->ignore();}QRectF r = scene()->sceneRect();r = r.united(mapToScene(boundingRect()).boundingRect());scene()->setSceneRect(r);}voidQtNodeGraphicsObject::mouseReleaseEvent(QGraphicsSceneMouseEvent* event){/** First check whether any of the hot key was hit */auto model = _node.nodeDataModel();bool hotKeyHit = false;//The hot keys can only be triggered by the left mouse buttonif (model->captionVisible() && event->button() == Qt::LeftButton){int id = _node.nodeGeometry().updateMouseRelease(event->pos());if (id>=0){_scene.nodeHotKeyClicked(node(), !_node.nodeGeometry().isHotkeyChecked(id), id);hotKeyHit = true;}}auto& state = _node.nodeState();state.setResizing(false);QGraphicsObject::mouseReleaseEvent(event);// position connections precisely after fast node movemoveConnections();/** Emit a signal to notify the node is selected */if (isSelected() && !hotKeyHit){_pressCounter++;if (_pressCounter == 1) {QTimer::singleShot(300, this, SLOT(nodeSelection()));}}update();}voidQtNodeGraphicsObject::hoverEnterEvent(QGraphicsSceneHoverEvent * event){// bring all the colliding nodes to backgroundQList<QGraphicsItem *> overlapItems = collidingItems();for (QGraphicsItem *item : overlapItems){if (item->zValue() > 0.0){item->setZValue(0.0);}}// bring this node forwardsetZValue(1.0);_node.nodeGeometry().setHovered(true);update();_scene.nodeHovered(node(), event->screenPos());event->accept();//HelpTimerID = startTimer(2000);}voidQtNodeGraphicsObject::hoverLeaveEvent(QGraphicsSceneHoverEvent * event){_node.nodeGeometry().setHovered(false);update();_scene.nodeHoverLeft(node());event->accept();_node.nodeGeometry().leaveHoverButton();_node.nodeGeometry().HideTips();_node.nodeGeometry().HidePortTips();//std::cout << "++++++++++killid:" << HelpTimerID << std::endl;if(HelpTimerID != -1)killTimer(HelpTimerID);HelpTimerID = -1;if (PortTimerID != -1)killTimer(PortTimerID);PortTimerID = -1;}voidQtNodeGraphicsObject::hoverMoveEvent(QGraphicsSceneHoverEvent * event){auto pos = event->pos();auto & geom = _node.nodeGeometry();auto model = _node.nodeDataModel();if (_node.nodeDataModel()->resizable() &&geom.resizeRect().contains(QPoint(pos.x(), pos.y()))){setCursor(QCursor(Qt::SizeFDiagCursor));}else{setCursor(QCursor());}if (model->captionVisible() && model->hotkeyEnabled()){_node.nodeGeometry().updateHotkeyHover(event->pos());}hideTipsAndTimer();//Active timer for NodeTipsif (HelpTimerID == -1 ) HelpTimerID = startTimer(1500);//use ports tipsfor (PortType portToCheck : {PortType::In, PortType::Out})//{auto porttype = portToCheck;NodeGeometry const& nodeGeometry = _node.nodeGeometry();// TODO do not pass sceneTransformint const portIndex = nodeGeometry.findHitPort(portToCheck,event->scenePos(),sceneTransform(), geom , model);if (portIndex != INVALID_PORT){NodeState const& nodeState = _node.nodeState();_node.nodeGeometry().hoverport_type = portToCheck ;_node.nodeGeometry().hoverport_id = portIndex ;if (PortTimerID == -1){PortTimerID = startTimer(1000);_node.nodeGeometry().HideTips();if (HelpTimerID != -1)killTimer(HelpTimerID); HelpTimerID = -1;}if (porttype == PortType::In){break;}}else{if (PortTimerID != -1){killTimer(PortTimerID); PortTimerID = -1;}}}_node.nodeGeometry().HidePortTips();update();event->accept();}// void// QtNodeGraphicsObject::// mouseDoubleClickEvent(QGraphicsSceneMouseEvent* event)// {// QGraphicsItem::mouseDoubleClickEvent(event);//// _scene.nodeDoubleClicked(node());// }void QtNodeGraphicsObject::contextMenuEvent(QGraphicsSceneContextMenuEvent* event){_scene.nodeContextMenu(node(), mapToScene(event->pos()));}void QtNodeGraphicsObject::nodeSelection(){if (_pressCounter == 1)_scene.nodeSelected(node());else_scene.nodeDoubleClicked(node());_pressCounter = 0;}//此部分为生成注释的定时器void QtNodeGraphicsObject::timerEvent(QTimerEvent* event) {//std::cout << "有定时器事件" << event->timerId() << std::endl;//std::cout << "++++++++++定时器启动++++++++id:" << HelpTimerID << std::endl;//此部分为NodeTips的生成与全部注释的定时器销毁。if (event->timerId() == HelpTimerID){if (!_node.nodeGeometry().getPortTipsState())_node.nodeGeometry().ShowTips();//std::cout << "++++++++++killid:" << event->timerId() << std::endl;if (HelpTimerID != -1)killTimer(event->timerId()); HelpTimerID = -1;if (PortTimerID != -1)killTimer(PortTimerID); PortTimerID = -1;}//此部分为PortTips的生成与全部注释的定时器销毁。if (event->timerId() == PortTimerID){_node.nodeGeometry().ShowPortTips();//std::cout << "显示portTips" << std::endl;if (PortTimerID != -1)killTimer(event->timerId()); PortTimerID = -1;if (HelpTimerID != -1)killTimer(HelpTimerID); HelpTimerID = -1;}else;}void QtNodeGraphicsObject::hideTipsAndTimer(){if (PortTimerID != -1) {_node.nodeGeometry().HidePortTips();killTimer(PortTimerID); PortTimerID = -1;}if (HelpTimerID != -1) {_node.nodeGeometry().HideTips();killTimer(HelpTimerID); HelpTimerID = -1;}}}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。