From 4f7d31eb798129a3d3d12c4e3ad4570b6ad7c6c8 Mon Sep 17 00:00:00 2001 From: Eberhard Graether Date: Mon, 23 Feb 2015 12:11:01 +0100 Subject: [PATCH] ui: graph transitions This change adds animated transitions to the QtGraphView using sequential and parallel animations. First vanishing nodes and all edges get faded out, then the remaining nodes are moved and resized, lastly new nodes and all edges are faded in. fortune cookie message = Sorge dich nicht! Du wirst bekommen, was du brauchst. --- .../qt/graphics/QtGraphicsRoundedRectItem.cpp | 8 + .../qt/graphics/QtGraphicsRoundedRectItem.h | 1 + src/app/qt/utility/QtGraphPostprocessor.cpp | 7 +- src/app/qt/utility/QtGraphPostprocessor.h | 1 + src/app/qt/view/QtGraphView.cpp | 326 +++++++++++++++--- src/app/qt/view/QtGraphView.h | 31 +- src/app/qt/view/graphElements/QtGraphEdge.h | 6 +- src/app/qt/view/graphElements/QtGraphNode.cpp | 48 ++- src/app/qt/view/graphElements/QtGraphNode.h | 21 +- .../view/graphElements/QtGraphNodeAccess.cpp | 16 +- .../qt/view/graphElements/QtGraphNodeAccess.h | 8 +- .../QtGraphNodeComponentMoveable.cpp | 15 + .../QtGraphNodeComponentMoveable.h | 1 + .../component/view/graphElements/GraphNode.h | 2 + 14 files changed, 426 insertions(+), 65 deletions(-) diff --git a/src/app/qt/graphics/QtGraphicsRoundedRectItem.cpp b/src/app/qt/graphics/QtGraphicsRoundedRectItem.cpp index d093e501..40abbbe4 100644 --- a/src/app/qt/graphics/QtGraphicsRoundedRectItem.cpp +++ b/src/app/qt/graphics/QtGraphicsRoundedRectItem.cpp @@ -33,6 +33,14 @@ void QtGraphicsRoundedRectItem::setShadow(QColor color, int blurRadius) this->setGraphicsEffect(effect); } +void QtGraphicsRoundedRectItem::setShadowEnabled(bool enabled) +{ + if (this->graphicsEffect()) + { + this->graphicsEffect()->setEnabled(enabled); + } +} + void QtGraphicsRoundedRectItem::setRadius(qreal radius) { m_radius = radius; diff --git a/src/app/qt/graphics/QtGraphicsRoundedRectItem.h b/src/app/qt/graphics/QtGraphicsRoundedRectItem.h index 764274b1..2526c20f 100644 --- a/src/app/qt/graphics/QtGraphicsRoundedRectItem.h +++ b/src/app/qt/graphics/QtGraphicsRoundedRectItem.h @@ -13,6 +13,7 @@ public: virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem* options, QWidget* widget); void setShadow(QColor color, int blurRadius); + void setShadowEnabled(bool enabled); void setRadius(qreal radius); private: diff --git a/src/app/qt/utility/QtGraphPostprocessor.cpp b/src/app/qt/utility/QtGraphPostprocessor.cpp index 9228b786..6aa7a7fa 100644 --- a/src/app/qt/utility/QtGraphPostprocessor.cpp +++ b/src/app/qt/utility/QtGraphPostprocessor.cpp @@ -66,8 +66,11 @@ void QtGraphPostprocessor::doPostprocessing(std::listgetPosition(); + node->setPosition(alignOnRaster(node->getPosition())); +} +Vec2i QtGraphPostprocessor::alignOnRaster(Vec2i position) +{ int rasterPosDivisor = s_cellSize + s_cellPadding; if(position.x % rasterPosDivisor != 0) @@ -110,7 +113,7 @@ void QtGraphPostprocessor::allignNodeOnRaster(QtGraphNode* node) position.y = t * rasterPosDivisor; } - node->setPosition(position); + return position; } void QtGraphPostprocessor::resolveOutliers(std::list>& nodes, const Vec2i& centerPoint) diff --git a/src/app/qt/utility/QtGraphPostprocessor.h b/src/app/qt/utility/QtGraphPostprocessor.h index 583d9a3a..cc68660d 100644 --- a/src/app/qt/utility/QtGraphPostprocessor.h +++ b/src/app/qt/utility/QtGraphPostprocessor.h @@ -14,6 +14,7 @@ public: static void doPostprocessing(std::list>& nodes); static void allignNodeOnRaster(QtGraphNode* node); + static Vec2i alignOnRaster(Vec2i position); private: static unsigned int s_cellSize; diff --git a/src/app/qt/view/QtGraphView.cpp b/src/app/qt/view/QtGraphView.cpp index 81d4b207..d4bdf9c7 100644 --- a/src/app/qt/view/QtGraphView.cpp +++ b/src/app/qt/view/QtGraphView.cpp @@ -4,6 +4,9 @@ #include #include #include +#include +#include +#include #include "qt/utility/QtGraphPostprocessor.h" #include "qt/utility/utilityQt.h" @@ -69,12 +72,7 @@ void QtGraphView::clear() GraphView::Metrics QtGraphView::getViewMetrics() const { GraphView::Metrics metrics; - QGraphicsView* view = getView(); - if (view == NULL) - { - return metrics; - } metrics.width = view->width(); metrics.height = view->height(); @@ -86,61 +84,35 @@ GraphView::Metrics QtGraphView::getViewMetrics() const return metrics; } -QGraphicsView* QtGraphView::getView() const +void QtGraphView::finishedTransition() { - QWidget* widget = QtViewWidgetWrapper::getWidgetOfView(this); + for (const std::shared_ptr& node : m_nodes) + { + node->setShadowEnabledRecursive(true); + } - return widget->findChild(""); + QGraphicsView* view = getView(); + view->setInteractive(true); + + switchToNewGraphData(); } -void QtGraphView::doRebuildGraph( - std::shared_ptr graph, - const std::vector& nodes, - const std::vector& edges -){ +void QtGraphView::switchToNewGraphData() +{ + m_oldGraph = m_graph; + + m_oldNodes = m_nodes; + m_oldEdges = m_edges; + + m_nodes.clear(); + m_edges.clear(); + QGraphicsView* view = getView(); - if (view == NULL) - { - LOG_WARNING("Failed to get QGraphicsView"); - return; - } + int margin = 25; + view->setSceneRect(itemsBoundingRect(m_oldNodes).adjusted(-margin, -margin, margin, margin).translated(m_sceneRectOffset)); - // Temporary stores all nodes (existing and newly created) needed in the new graph - // this is a relatively easy and cheap way to save existing nodes that are still needed - std::list> newNodes; - - // create nodes (or find existing nodes for re-use) - for (unsigned int i = 0; i < nodes.size(); i++) - { - std::shared_ptr node = createNodeRecursive(view, NULL, nodes[i]); - if (node) - { - newNodes.push_back(node); - } - } - - doClear(); - m_nodes = newNodes; - - for (unsigned int i = 0; i < edges.size(); i++) - { - std::shared_ptr edge = createEdge(view, edges[i]); - if (edge != NULL) - { - m_edges.push_back(edge); - } - } - - if (graph) - { - m_graph = graph; - } - - QtGraphPostprocessor::doPostprocessing(m_nodes); - - // Manually hover the items below the mouse cursor. - view->scene()->setSceneRect(view->scene()->itemsBoundingRect()); + // Manually hover the item below the mouse cursor. QPointF point = view->mapToScene(view->mapFromGlobal(QCursor::pos())); QGraphicsItem* item = view->scene()->itemAt(point, QTransform()); if (item) @@ -153,10 +125,77 @@ void QtGraphView::doRebuildGraph( } } +QGraphicsView* QtGraphView::getView() const +{ + QWidget* widget = QtViewWidgetWrapper::getWidgetOfView(this); + + QGraphicsView* view = widget->findChild(""); + + if (!view) + { + LOG_ERROR("Failed to get QGraphicsView"); + } + + return view; +} + +void QtGraphView::doRebuildGraph( + std::shared_ptr graph, + const std::vector& nodes, + const std::vector& edges +){ + QGraphicsView* view = getView(); + + m_nodes.clear(); + for (unsigned int i = 0; i < nodes.size(); i++) + { + std::shared_ptr node = createNodeRecursive(view, NULL, nodes[i]); + if (node) + { + m_nodes.push_back(node); + } + } + + QtGraphPostprocessor::doPostprocessing(m_nodes); + + QPointF center = itemsBoundingRect(m_nodes).center(); + Vec2i o = QtGraphPostprocessor::alignOnRaster(Vec2i(center.x(), center.y())); + QPointF offset = QPointF(o.x, o.y); + m_sceneRectOffset = offset - center; + + for (const std::shared_ptr& node : m_nodes) + { + node->setPos(node->pos() - offset); + } + + m_edges.clear(); + for (unsigned int i = 0; i < edges.size(); i++) + { + std::shared_ptr edge = createEdge(view, edges[i]); + if (edge) + { + m_edges.push_back(edge); + } + } + + if (graph) + { + m_graph = graph; + } + + createTransition(); +} + void QtGraphView::doClear() { m_nodes.clear(); m_edges.clear(); + + m_oldNodes.clear(); + m_oldEdges.clear(); + + m_graph.reset(); + m_oldGraph.reset(); } std::shared_ptr QtGraphView::findNodeRecursive(const std::list>& nodes, Id tokenId) @@ -258,3 +297,184 @@ std::shared_ptr QtGraphView::createEdge(QGraphicsView* view, const return NULL; } } + +template +QRectF QtGraphView::itemsBoundingRect(const std::list>& items) const +{ + QRectF boundingRect; + for (const std::shared_ptr& item : items) + { + boundingRect |= item->sceneBoundingRect(); + } + return boundingRect; +} + +void QtGraphView::compareNodesRecursive( + std::list> newSubNodes, + std::list> oldSubNodes, + std::list* appearingNodes, + std::list* vanishingNodes, + std::vector>* remainingNodes +){ + for (std::list>::iterator it = newSubNodes.begin(); it != newSubNodes.end(); it++) + { + bool remains = false; + + for (std::list>::iterator it2 = oldSubNodes.begin(); it2 != oldSubNodes.end(); it2++) + { + if (((*it)->getTokenId() && (*it)->getTokenId() == (*it2)->getTokenId()) || + ((*it)->isAccessNode() && (*it2)->isAccessNode() && + dynamic_cast((*it).get())->getAccessType() == + dynamic_cast((*it2).get())->getAccessType())) + { + remainingNodes->push_back(std::pair((*it).get(), (*it2).get())); + compareNodesRecursive((*it)->getSubNodes(), (*it2)->getSubNodes(), appearingNodes, vanishingNodes, remainingNodes); + + oldSubNodes.erase(it2); + remains = true; + break; + } + } + + if (!remains) + { + appearingNodes->push_back((*it).get()); + } + } + + for (std::shared_ptr& node : oldSubNodes) + { + vanishingNodes->push_back(node.get()); + } +} + +void QtGraphView::createTransition() +{ + std::list appearingNodes; + std::list vanishingNodes; + std::vector> remainingNodes; + + compareNodesRecursive(m_nodes, m_oldNodes, &appearingNodes, &vanishingNodes, &remainingNodes); + + if (!vanishingNodes.size() && !appearingNodes.size()) + { + switchToNewGraphData(); + return; + } + + for (const std::shared_ptr& node : m_nodes) + { + node->setShadowEnabledRecursive(false); + } + + for (const std::shared_ptr& node : m_oldNodes) + { + node->setShadowEnabledRecursive(false); + } + + QGraphicsView* view = getView(); + view->setInteractive(false); + + QSequentialAnimationGroup* group = new QSequentialAnimationGroup(); + + // fade out + if (vanishingNodes.size() || m_oldEdges.size()) + { + QParallelAnimationGroup* vanish = new QParallelAnimationGroup(); + + for (QtGraphNode* node : vanishingNodes) + { + QPropertyAnimation* anim = new QPropertyAnimation(node, "opacity"); + anim->setDuration(300); + anim->setStartValue(1.0f); + anim->setEndValue(0.0f); + + vanish->addAnimation(anim); + } + + for (std::shared_ptr edge : m_oldEdges) + { + QPropertyAnimation* anim = new QPropertyAnimation(edge.get(), "opacity"); + anim->setDuration(150); + anim->setStartValue(1.0f); + anim->setEndValue(0.0f); + + vanish->addAnimation(anim); + } + + group->addAnimation(vanish); + } + + // move and scale + if (remainingNodes.size()) + { + QParallelAnimationGroup* remain = new QParallelAnimationGroup(); + + for (std::pair p : remainingNodes) + { + QtGraphNode* newNode = p.first; + QtGraphNode* oldNode = p.second; + + QPropertyAnimation* anim = new QPropertyAnimation(oldNode, "pos"); + anim->setDuration(300); + anim->setStartValue(oldNode->pos()); + anim->setEndValue(newNode->pos()); + + remain->addAnimation(anim); + + connect(anim, SIGNAL(finished()), newNode, SLOT(showNode())); + connect(anim, SIGNAL(finished()), oldNode, SLOT(hideNode())); + newNode->hide(); + + anim = new QPropertyAnimation(oldNode, "size"); + anim->setDuration(300); + anim->setStartValue(oldNode->size()); + anim->setEndValue(newNode->size()); + + remain->addAnimation(anim); + + if (newNode->isAccessNode() && newNode->getSubNodes().size() == 0 && oldNode->getSubNodes().size() > 0) + { + dynamic_cast(oldNode)->hideLabel(); + } + } + + group->addAnimation(remain); + } + + // fade in + if (appearingNodes.size() || m_edges.size()) + { + QParallelAnimationGroup* appear = new QParallelAnimationGroup(); + + for (QtGraphNode* node : appearingNodes) + { + QPropertyAnimation* anim = new QPropertyAnimation(node, "opacity"); + anim->setDuration(300); + anim->setStartValue(0.0f); + anim->setEndValue(1.0f); + + appear->addAnimation(anim); + + connect(anim, SIGNAL(finished()), node, SLOT(blendIn())); + node->blendOut(); + } + + for (std::shared_ptr edge : m_edges) + { + QPropertyAnimation* anim = new QPropertyAnimation(edge.get(), "opacity"); + anim->setDuration(150); + anim->setStartValue(0.0f); + anim->setEndValue(1.0f); + + appear->addAnimation(anim); + + edge->setOpacity(0.0f); + } + + group->addAnimation(appear); + } + + connect(group, SIGNAL(finished()), this, SLOT(finishedTransition())); + group->start(); +} diff --git a/src/app/qt/view/QtGraphView.h b/src/app/qt/view/QtGraphView.h index 6e76d48c..1cf9ce41 100644 --- a/src/app/qt/view/QtGraphView.h +++ b/src/app/qt/view/QtGraphView.h @@ -1,6 +1,8 @@ #ifndef QT_GRAPH_VIEW_H #define QT_GRAPH_VIEW_H +#include + #include "qt/utility/QtThreadedFunctor.h" #include "utility/math/MatrixDynamicBase.h" #include "utility/math/Vector4.h" @@ -14,8 +16,12 @@ class QGraphicsView; class QtGraphEdge; class QtGraphNode; -class QtGraphView: public GraphView +class QtGraphView + : public QObject + , public GraphView { + Q_OBJECT + public: QtGraphView(ViewLayout* viewLayout); virtual ~QtGraphView(); @@ -30,7 +36,12 @@ public: virtual GraphView::Metrics getViewMetrics() const; +private slots: + void finishedTransition(); + private: + void switchToNewGraphData(); + QGraphicsView* getView() const; void doRebuildGraph(std::shared_ptr graph, const std::vector& nodes, const std::vector& edges); @@ -42,13 +53,31 @@ private: QGraphicsView* view, std::shared_ptr parentNode, const DummyNode& node); std::shared_ptr createEdge(QGraphicsView* view, const DummyEdge& edge); + template + QRectF itemsBoundingRect(const std::list>& items) const; + + void compareNodesRecursive( + std::list> newSubNodes, + std::list> oldSubNodes, + std::list* appearingNodes, + std::list* vanishingNodes, + std::vector>* remainingNodes); + + void createTransition(); + QtThreadedFunctor, const std::vector&, const std::vector&> m_rebuildGraphFunctor; QtThreadedFunctor m_clearFunctor; std::shared_ptr m_graph; + std::shared_ptr m_oldGraph; std::list> m_edges; + std::list> m_oldEdges; + std::list> m_nodes; + std::list> m_oldNodes; + + QPointF m_sceneRectOffset; }; #endif // QT_GRAPH_VIEW_H diff --git a/src/app/qt/view/graphElements/QtGraphEdge.h b/src/app/qt/view/graphElements/QtGraphEdge.h index 5abea7da..a6b26b0e 100644 --- a/src/app/qt/view/graphElements/QtGraphEdge.h +++ b/src/app/qt/view/graphElements/QtGraphEdge.h @@ -55,9 +55,13 @@ private: class QtGraphEdge - : public GraphEdge + : public QObject + , public GraphEdge , public QGraphicsItemGroup { + Q_OBJECT + Q_PROPERTY(qreal opacity READ opacity WRITE setOpacity) + public: QtGraphEdge(const std::weak_ptr& owner, const std::weak_ptr& target, const Edge* data); virtual ~QtGraphEdge(); diff --git a/src/app/qt/view/graphElements/QtGraphNode.cpp b/src/app/qt/view/graphElements/QtGraphNode.cpp index e3ea95de..08592bdd 100644 --- a/src/app/qt/view/graphElements/QtGraphNode.cpp +++ b/src/app/qt/view/graphElements/QtGraphNode.cpp @@ -9,10 +9,29 @@ #include "qt/graphics/QtGraphicsRoundedRectItem.h" #include "qt/utility/QtDeviceScaledPixmap.h" -#include "qt/utility/QtGraphPostprocessor.h" #include "qt/view/graphElements/nodeComponents/QtGraphNodeComponent.h" #include "qt/view/graphElements/QtGraphEdge.h" +void QtGraphNode::blendIn() +{ + setOpacity(1.0f); +} + +void QtGraphNode::blendOut() +{ + setOpacity(0.0f); +} + +void QtGraphNode::showNode() +{ + this->show(); +} + +void QtGraphNode::hideNode() +{ + this->hide(); +} + QFont QtGraphNode::getFontForNodeType(Node::NodeType type) { QFont font("Source Code Pro"); @@ -92,6 +111,11 @@ void QtGraphNode::setName(const std::string& name) m_text->setText(QString::fromStdString(name)); } +bool QtGraphNode::isAccessNode() const +{ + return false; +} + Vec2i QtGraphNode::getPosition() const { return Vec2i(this->scenePos().x(), this->scenePos().y()); @@ -205,6 +229,16 @@ unsigned int QtGraphNode::getInEdgeCount() const return m_inEdges.size(); } +QSize QtGraphNode::size() const +{ + return QSize(m_size.x, m_size.y); +} + +void QtGraphNode::setSize(const QSize& size) +{ + setSize(Vec2i(size.width(), size.height())); +} + bool QtGraphNode::getIsActive() const { return m_isActive; @@ -394,6 +428,16 @@ void QtGraphNode::setStyle() m_text->setPos(padding.x, padding.y); } +void QtGraphNode::setShadowEnabledRecursive(bool enabled) +{ + m_rect->setShadowEnabled(enabled); + + for (const std::shared_ptr& node : m_subNodes) + { + node->setShadowEnabledRecursive(enabled); + } +} + void QtGraphNode::onClick() { if (m_data && !m_data->isType(Node::NODE_UNDEFINED | Node::NODE_NAMESPACE)) @@ -468,8 +512,6 @@ void QtGraphNode::mouseReleaseEvent(QGraphicsSceneMouseEvent* event) parent->mouseReleaseEvent(event); } } - - QtGraphPostprocessor::allignNodeOnRaster(this); } void QtGraphNode::hoverEnterEvent(QGraphicsSceneHoverEvent* event) diff --git a/src/app/qt/view/graphElements/QtGraphNode.h b/src/app/qt/view/graphElements/QtGraphNode.h index 864942c5..05346fe6 100644 --- a/src/app/qt/view/graphElements/QtGraphNode.h +++ b/src/app/qt/view/graphElements/QtGraphNode.h @@ -11,9 +11,22 @@ class QtGraphicsRoundedRectItem; class QtGraphNodeComponent; class QtGraphNode - : public GraphNode + : public QObject + , public GraphNode , public QGraphicsRectItem { + Q_OBJECT + Q_PROPERTY(QPointF pos READ pos WRITE setPos) + Q_PROPERTY(qreal opacity READ opacity WRITE setOpacity) + Q_PROPERTY(QSize size READ size WRITE setSize) + +public slots: + void blendIn(); + void blendOut(); + + void showNode(); + void hideNode(); + public: static QFont getFontForNodeType(Node::NodeType type); @@ -24,6 +37,8 @@ public: virtual std::string getName() const; void setName(const std::string& name); + virtual bool isAccessNode() const; + virtual Vec2i getPosition() const; virtual bool setPosition(const Vec2i& position); virtual void moveTo(const Vec2i& position); @@ -40,6 +55,9 @@ public: virtual unsigned int getOutEdgeCount() const; virtual unsigned int getInEdgeCount() const; + QSize size() const; + void setSize(const QSize& size); + bool getIsActive() const; void setIsActive(bool isActive); @@ -52,6 +70,7 @@ public: virtual void addSubNode(const std::shared_ptr& node); void setStyle(); + void setShadowEnabledRecursive(bool enabled); virtual void onClick(); void hoverEnter(); diff --git a/src/app/qt/view/graphElements/QtGraphNodeAccess.cpp b/src/app/qt/view/graphElements/QtGraphNodeAccess.cpp index 705d6bc0..06a64546 100644 --- a/src/app/qt/view/graphElements/QtGraphNodeAccess.cpp +++ b/src/app/qt/view/graphElements/QtGraphNodeAccess.cpp @@ -95,6 +95,16 @@ QtGraphNodeAccess::~QtGraphNodeAccess() { } +bool QtGraphNodeAccess::isAccessNode() const +{ + return true; +} + +TokenComponentAccess::AccessType QtGraphNodeAccess::getAccessType() const +{ + return m_access; +} + void QtGraphNodeAccess::setSize(const Vec2i& size) { QtGraphNode::setSize(size); @@ -105,7 +115,6 @@ void QtGraphNodeAccess::setSize(const Vec2i& size) void QtGraphNodeAccess::addSubNode(const std::shared_ptr& node) { QtGraphNode::addSubNode(node); - m_text->show(); } @@ -118,3 +127,8 @@ void QtGraphNodeAccess::onClick() MessageGraphNodeExpand(parent->getData()->getId(), m_access).dispatch(); } } + +void QtGraphNodeAccess::hideLabel() +{ + m_text->hide(); +} diff --git a/src/app/qt/view/graphElements/QtGraphNodeAccess.h b/src/app/qt/view/graphElements/QtGraphNodeAccess.h index 5acf5dd5..6b4e0da5 100644 --- a/src/app/qt/view/graphElements/QtGraphNodeAccess.h +++ b/src/app/qt/view/graphElements/QtGraphNodeAccess.h @@ -20,16 +20,18 @@ public: QGraphicsSimpleTextItem* m_number; }; - QtGraphNodeAccess(TokenComponentAccess::AccessType accessType, bool expanded, int invisibleSubNodeCount); virtual ~QtGraphNodeAccess(); + virtual bool isAccessNode() const; + TokenComponentAccess::AccessType getAccessType() const; + virtual void setSize(const Vec2i& size); - virtual void addSubNode(const std::shared_ptr& node); - virtual void onClick(); + void hideLabel(); + private: TokenComponentAccess::AccessType m_access; diff --git a/src/app/qt/view/graphElements/nodeComponents/QtGraphNodeComponentMoveable.cpp b/src/app/qt/view/graphElements/nodeComponents/QtGraphNodeComponentMoveable.cpp index c68d8183..f3109da4 100644 --- a/src/app/qt/view/graphElements/nodeComponents/QtGraphNodeComponentMoveable.cpp +++ b/src/app/qt/view/graphElements/nodeComponents/QtGraphNodeComponentMoveable.cpp @@ -2,6 +2,7 @@ #include +#include "qt/utility/QtGraphPostprocessor.h" #include "qt/view/graphElements/QtGraphNode.h" QtGraphNodeComponentMoveable::QtGraphNodeComponentMoveable(const std::weak_ptr& graphNode) @@ -35,3 +36,17 @@ void QtGraphNodeComponentMoveable::nodeMouseMoveEvent(QGraphicsSceneMouseEvent* event->accept(); } } + +void QtGraphNodeComponentMoveable::nodeMouseReleaseEvent(QGraphicsSceneMouseEvent* event) +{ + if (event->isAccepted()) + { + return; + } + + std::shared_ptr node = m_graphNode.lock(); + if (node != NULL) + { + QtGraphPostprocessor::allignNodeOnRaster(node.get()); + } +} diff --git a/src/app/qt/view/graphElements/nodeComponents/QtGraphNodeComponentMoveable.h b/src/app/qt/view/graphElements/nodeComponents/QtGraphNodeComponentMoveable.h index 4ba698c5..67d10322 100644 --- a/src/app/qt/view/graphElements/nodeComponents/QtGraphNodeComponentMoveable.h +++ b/src/app/qt/view/graphElements/nodeComponents/QtGraphNodeComponentMoveable.h @@ -14,6 +14,7 @@ public: virtual void nodeMousePressEvent(QGraphicsSceneMouseEvent* event); virtual void nodeMouseMoveEvent(QGraphicsSceneMouseEvent* event); + virtual void nodeMouseReleaseEvent(QGraphicsSceneMouseEvent* event); private: Vec2i m_mouseOffset; diff --git a/src/lib/component/view/graphElements/GraphNode.h b/src/lib/component/view/graphElements/GraphNode.h index 1fa9d66e..8fac1504 100644 --- a/src/lib/component/view/graphElements/GraphNode.h +++ b/src/lib/component/view/graphElements/GraphNode.h @@ -25,6 +25,8 @@ public: const Node* getData() const; void setData(const Node* data); + virtual bool isAccessNode() const = 0; + virtual Vec2i getPosition() const = 0; virtual bool setPosition(const Vec2i& position) = 0; virtual void moveTo(const Vec2i& position) = 0;