diff --git a/src/gui/basegraphgl.cpp b/src/gui/basegraphgl.cpp index 7d5efdb3..84e6eec6 100644 --- a/src/gui/basegraphgl.cpp +++ b/src/gui/basegraphgl.cpp @@ -44,7 +44,8 @@ BaseGraphGL::BaseGraphGL(QWidget* parent) m_cacheStatus(CacheStatus::Ready), m_posEntered(0,0), m_curMode(SelectionMode::Select), - m_fullInspectorVisible(false) + m_fullInspectorVisible(false), + m_attrs(Attributes(0)) { m_ui->setupUi(this); @@ -54,8 +55,10 @@ BaseGraphGL::BaseGraphGL(QWidget* parent) connect(m_ui->bZoomIn, SIGNAL(pressed()), SLOT(zoomIn())); connect(m_ui->bZoomOut, SIGNAL(pressed()), SLOT(zoomOut())); connect(m_ui->bReset, SIGNAL(pressed()), SLOT(resetView())); - //connect(m_ui->edgesList, SIGNAL(itemClicked(QListWidgetItem*)), this, SLOT(edgesListItemClicked(QListWidgetItem*))); connect(m_ui->deleteEdge, SIGNAL(clicked()), this, SLOT(removeEdgeEvent())); + + connect(this, SIGNAL(nodesMoved()), SLOT(slotUpdateSelection())); + m_bCenter = new QtMaterialIconButton(QIcon(":/icons/material/center_white_18"), this); m_bCenter->setToolTip("centralize selection"); m_bCenter->setCheckable(true); @@ -97,6 +100,9 @@ void BaseGraphGL::setup(AbstractGraph* abstractGraph, AttributesScope nodeAttrsS m_nodeAttrsScope = nodeAttrsScope; setupInspector(); updateCache(); + if (m_abstractGraph && !m_abstractGraph->nodes().empty()) { + m_attrs = m_abstractGraph->node(0).attrs(); + } } void BaseGraphGL::paint(QPaintDevice* device, bool paintBackground) const @@ -135,6 +141,47 @@ void BaseGraphGL::slotSelectNode(int nodeid) } } +void BaseGraphGL::slotDeleteSelectedNodes() +{ + for (auto node : m_selectedNodes) { + m_abstractGraph->removeNode(node.second); + } + + clearSelection(); + updateCache(); +} + +void BaseGraphGL::createNode(const QPointF& pos) +{ + QPointF p = nodePoint(pos - m_origin); + m_abstractGraph->addNode(m_attrs, p.x(), p.y()); + updateCache(); +} + +void BaseGraphGL::deleteNode(const QPointF pos) +{ + const Node& node = findNode(pos); + clearSelection(); + m_abstractGraph->removeNode(node); + updateCache(); +} + +void BaseGraphGL::moveSelectedNodes(const Node& node, const QPointF pos) { + QPointF v = nodePoint(pos - m_origin) - QPointF(node.x(), node.y()); + for (Node _node : m_selectedNodes) { + _node.setCoords(_node.x() + v.x(), _node.y() + v.y()); + } + emit(nodesMoved()); + updateCache(); +} + +void BaseGraphGL::moveNode(Node& node, const QPointF pos) { + QPointF p = nodePoint(pos - m_origin); + node.setCoords(p.x(), p.y()); + emit(nodesMoved()); + updateCache(); +} + void BaseGraphGL::setupInspector() { // important! for some reason, changing the layout (add/delete itens) @@ -360,49 +407,72 @@ void BaseGraphGL::mouseReleaseEvent(QMouseEvent *e) return; } - if (m_curMode == SelectionMode::Select) { - if (e->button() == Qt::LeftButton) { - bool fNodeSelected; - const Node& node = findNode(e->localPos()); - Node prevSelection = selectedNode(); - - if (!node.isNull() && inSelectedNodes(node)) { - fNodeSelected = true; - if (e->modifiers().testFlag(Qt::ControlModifier)) { - deselectNode(node); - emit(nodeDeselected(node)); - refreshCache(); - } - } else { - fNodeSelected = false; + const Node _prevNode = findNode(m_posEntered); + Node node = findNode(e->localPos()); + if (e->button() == Qt::LeftButton) { + bool fNodeSelected; + Node prevSelection = selectedNode(); + + if (!node.isNull() && inSelectedNodes(node)) { + fNodeSelected = true; + if (e->modifiers().testFlag(Qt::ControlModifier)) { + deselectNode(node); + emit(nodeDeselected(node)); + refreshCache(); } + } else { + fNodeSelected = false; + } - if (e->pos() == m_posEntered) { - if (!e->modifiers().testFlag(Qt::ControlModifier)) { + if (e->pos() == m_posEntered) { + if (!e->modifiers().testFlag(Qt::ControlModifier)) { + if (m_curMode == SelectionMode::NodeEdit && node.isNull()) { + if (m_selectedNodes.empty()) { + createNode(e->localPos()); + } else { + clearSelection(); + } + } else { clearSelection(); } - if (!node.isNull() && (!fNodeSelected || !e->modifiers().testFlag(Qt::ControlModifier))) { - selectNode(e->localPos(), m_bCenter->isChecked()); - m_selectedNodes.insert(std::make_pair(node.id(), node)); - updateInspector(node); - emit(nodeSelected(node)); - refreshCache(); + } + if (!node.isNull() && (!fNodeSelected || !e->modifiers().testFlag(Qt::ControlModifier))) { + selectNode(e->localPos(), m_bCenter->isChecked()); + m_selectedNodes.insert(std::make_pair(node.id(), node)); + updateInspector(node); + emit(nodeSelected(node)); + refreshCache(); + } + m_bCenter->isChecked() ? updateCache() : update(); + } else { + if (m_curMode == SelectionMode::NodeEdit && !_prevNode.isNull()) { + Node movedNode; + if (inSelectedNodes(_prevNode)) { + moveSelectedNodes(_prevNode, e->localPos()); + } else { + clearSelection(); + movedNode = selectNode(m_posEntered, false); + moveNode(movedNode, e->localPos()); + m_selectedNodes.insert(std::make_pair(movedNode.id(), movedNode)); + updateInspector(movedNode); + emit(nodeSelected(movedNode)); } - m_bCenter->isChecked() ? updateCache() : update(); } else { m_origin += (e->pos() - m_posEntered); updateCache(); } - } else if (e->button() == Qt::RightButton && m_nodeAttr >= 0 && !m_isReadOnly) { - Node node = selectNode(e->localPos(), false); - if (!node.isNull()) { - const QString& attrName = node.attrs().name(m_nodeAttr); - auto attrRange = m_nodeAttrsScope.value(attrName); - node.setAttr(m_nodeAttr, attrRange->next(node.attr(m_nodeAttr))); - clearSelection(); - emit(updateWidgets(true)); - updateCache(); - } + } + } else if (e->button() == Qt::RightButton && m_curMode == SelectionMode::NodeEdit && !node.isNull()) { + deleteNode(e->localPos()); + } else if (e->button() == Qt::RightButton && m_nodeAttr >= 0 && !m_isReadOnly) { + Node node = selectNode(e->localPos(), false); + if (!node.isNull()) { + const QString& attrName = node.attrs().name(m_nodeAttr); + auto attrRange = m_nodeAttrsScope.value(attrName); + node.setAttr(m_nodeAttr, attrRange->next(node.attr(m_nodeAttr))); + clearSelection(); + emit(updateWidgets(true)); + updateCache(); } } } @@ -517,6 +587,7 @@ void BaseGraphGL::updateNodesInspector(const Node& node) void BaseGraphGL::updateInspector(const Node& node) { m_ui->inspector->setCurrentIndex(0); + QString nodes; QString neighbors; QString edges; diff --git a/src/gui/basegraphgl.h b/src/gui/basegraphgl.h index b0adba3d..d5fa2679 100644 --- a/src/gui/basegraphgl.h +++ b/src/gui/basegraphgl.h @@ -69,7 +69,9 @@ class GraphGLInterface virtual QPointF selectedNodePos() const = 0; virtual void clearSelection() = 0; virtual CacheStatus refreshCache() = 0; - virtual inline bool inSelectedNodes(const Node node) const = 0; + virtual inline bool inSelectedNodes(const Node& node) const = 0; + virtual inline QPointF nodePoint(const QPointF& pos) = 0; + }; class BaseGraphGL : public QOpenGLWidget, public GraphGLInterface @@ -110,6 +112,9 @@ class BaseGraphGL : public QOpenGLWidget, public GraphGLInterface void clearSelection() override; void updateCache(bool force=false); + + void createNode(const QPointF& pos); + void deleteNode(const QPointF pos); inline void paintEvent(QPaintEvent*) override; void mousePressEvent(QMouseEvent* e) override; @@ -123,11 +128,13 @@ class BaseGraphGL : public QOpenGLWidget, public GraphGLInterface void nodeSelected(const Node&); void nodeDeselected(const Node&); void clearedSelected(); + void nodesMoved(); void updateWidgets(bool) const; public slots: virtual void zoomIn(); virtual void zoomOut(); + virtual void slotUpdateSelection() = 0; void slotFullInspectorVisible(int visible); void setCurrentStep(int step); @@ -135,6 +142,7 @@ public slots: void setNodeScale(int v); void slotRestarted(); void slotStatusChanged(Status s); + void slotDeleteSelectedNodes(); private slots: void slotSelectNode(int nodeid); @@ -157,9 +165,13 @@ private slots: bool m_fullInspectorVisible; QSet sneighbors; QSet sedges; + Attributes m_attrs; void attrValueChanged(int attrId) const; + void moveSelectedNodes(const Node& node, const QPointF pos); + void moveNode(Node& node, const QPointF pos); + void setupInspector(); void updateInspector(const Node& node); diff --git a/src/gui/forms/fullinspector.ui b/src/gui/forms/fullinspector.ui index 85f8fc94..a835c518 100644 --- a/src/gui/forms/fullinspector.ui +++ b/src/gui/forms/fullinspector.ui @@ -1,143 +1,150 @@ - FullInspector - - - - 0 - 0 - 420 - 558 - - - - - 300 - 347 - - - - QDockWidget::DockWidgetFloatable|QDockWidget::DockWidgetMovable - - - Full Inspector - - - - - 0 + FullInspector + + + + 0 + 0 + 420 + 558 + - - 0 + + + 300 + 400 + - - 0 + + QDockWidget::DockWidgetFloatable|QDockWidget::DockWidgetMovable - - - - true - - - QFrame::NoFrame - - - true - - - Nothing selected - - - true - - - - - - - true - - - - 20 - - - 0 - - - 20 - - - 20 - - - 0 - - - 30 - - - - - - 0 - 0 - - - - - 40 - 0 - - - - Attributes: - - - - - - - Qt::Vertical - - - - 20 - 40 - - - - - - - - - 0 - 0 - - - - - - - - Ids: - - - - - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - - - + + Full Inspector + + + + + 0 + + + 0 + + + 0 + + + + + true + + + QFrame::NoFrame + + + true + + + Nothing selected + + + true + + + + + + + true + + + + 20 + + + 0 + + + 20 + + + 20 + + + 0 + + + 30 + + + + + + 0 + 0 + + + + + 40 + 0 + + + + Attributes: + + + + + + + Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter + + + + + + + + 0 + 0 + + + + + + + + Ids: + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + Delete + + + + + + - - - + - - - + + diff --git a/src/gui/fullinspector.cpp b/src/gui/fullinspector.cpp index d7b05ec0..b439f147 100644 --- a/src/gui/fullinspector.cpp +++ b/src/gui/fullinspector.cpp @@ -29,9 +29,11 @@ FullInspector::FullInspector(QWidget* parent) : QDockWidget(parent), m_ui(new Ui_FullInspector), m_parent(parent) -{ +{ m_ui->setupUi(this); m_ui->inspectorContents->hide(); + + connect(m_ui->bdelete, SIGNAL(clicked()), SLOT(slotDelete())); } FullInspector::~FullInspector() @@ -76,6 +78,15 @@ void FullInspector::slotChangeAttrScope(AttributesScope nodeAttrScope) } +void FullInspector::slotDelete() +{ + m_ui->ids->clear(); + if (m_selectedNodes.size() > 0) { + m_selectedNodes.clear(); + emit(deleteNodes()); + } +} + void FullInspector::attrValueChanged(int attrId) const { std::shared_ptr aw; diff --git a/src/gui/fullinspector.h b/src/gui/fullinspector.h index 2f7f6205..4fc0061c 100644 --- a/src/gui/fullinspector.h +++ b/src/gui/fullinspector.h @@ -46,8 +46,11 @@ public slots: void slotShow(); void slotSelectedNode(const Node& node); void slotDeselectedNode(const Node& node); + void slotDelete(); void slotChangeAttrScope(AttributesScope nodeAttrScope); +signals: + void deleteNodes(); private: QWidget* m_parent; diff --git a/src/gui/graphdesignerpage.cpp b/src/gui/graphdesignerpage.cpp index 993d32e2..a2ce9234 100644 --- a/src/gui/graphdesignerpage.cpp +++ b/src/gui/graphdesignerpage.cpp @@ -74,9 +74,15 @@ GraphDesignerPage::GraphDesignerPage(MainGUI* mainGUI) connect(m_ui->acGraphSettings, SIGNAL(triggered()), m_graphDesigner, SLOT(slotOpenSettings())); connect(m_ui->acNodesExporter, SIGNAL(triggered()), m_graphDesigner, SLOT(slotExportNodes())); - connect(m_ui->acSelectTool, &QAction::triggered, [this]() { this->m_graphDesigner->slotChangeSelectionMode(SelectionMode::Select); }); - connect(m_ui->acNodeTool, &QAction::triggered, [this]() { this->m_graphDesigner->slotChangeSelectionMode(SelectionMode::NodeEdit); }); - connect(m_ui->acEdgeTool, &QAction::triggered, [this]() { this->m_graphDesigner->slotChangeSelectionMode(SelectionMode::EdgeEdit); }); + connect(m_ui->acSelectTool, &QAction::triggered, [this]() { + this->m_graphDesigner->slotChangeSelectionMode(SelectionMode::Select); + }); + connect(m_ui->acNodeTool, &QAction::triggered, [this]() { + this->m_graphDesigner->slotChangeSelectionMode(SelectionMode::NodeEdit); + }); + connect(m_ui->acEdgeTool, &QAction::triggered, [this]() { + this->m_graphDesigner->slotChangeSelectionMode(SelectionMode::EdgeEdit); + }); connect(inspVisible, SIGNAL(stateChanged(int)), m_graphDesigner->graphView(), SLOT(slotFullInspectorVisible(int))); connect(inspVisible, &QCheckBox::stateChanged, [this](int vis) { @@ -92,9 +98,10 @@ GraphDesignerPage::GraphDesignerPage(MainGUI* mainGUI) connect(m_graphDesigner->graphView(), &GraphView::nodeDeselected, [this](const Node& node) { this->m_inspector->slotDeselectedNode(node); }); - connect(m_graphDesigner->graphView(), SIGNAL(clearedSelected()), m_inspector, SLOT(slotClear())); + connect(m_inspector, SIGNAL(deleteNodes()), m_graphDesigner->graphView(), SLOT(slotDeleteSelectedNodes())); + setCentralWidget(m_graphDesigner); addDockWidget(Qt::RightDockWidgetArea, m_inspector); diff --git a/src/gui/graphview.cpp b/src/gui/graphview.cpp index 2fdc101b..453f6340 100644 --- a/src/gui/graphview.cpp +++ b/src/gui/graphview.cpp @@ -73,6 +73,18 @@ GraphView::Star GraphView::createStar(const Node& node, return star; } +void GraphView::slotUpdateSelection() { + for (auto selectedNode : m_selectedNodes) { + int i = selectedNode.first; + const Node node = selectedNode.second; + const QPointF xy = QPointF(node.x() * currEdgeSize(), node.y() * currEdgeSize()); + + Star selectedStar = createStar(node, currEdgeSize(), xy); + + m_selectedStars.at(i) = selectedStar; + } +} + CacheStatus GraphView::refreshCache() { if (paintingActive()) { @@ -324,6 +336,7 @@ void GraphView::drawSelectedStars(QPainter& painter, double nodeRadius) const for (auto selectedStar : m_selectedStars) { // draw shadow of the selected node + painter.save(); double shadowRadius = nodeRadius*1.5; QRadialGradient r(selectedStar.second.xy, shadowRadius, selectedStar.second.xy); diff --git a/src/gui/graphview.h b/src/gui/graphview.h index 1258bc43..7edbca28 100644 --- a/src/gui/graphview.h +++ b/src/gui/graphview.h @@ -35,21 +35,23 @@ class GraphView : public BaseGraphGL public slots: inline void zoomIn() override; inline void zoomOut() override; + void slotUpdateSelection() override; void setEdgeScale(int v); void setEdgeWidth(int v); protected: void paintFrame(QPainter& painter) const override; Node findNode(const QPointF& pos) const override; - Node selectNode(const QPointF &pos, bool center) override; + Node selectNode(const QPointF& pos, bool center) override; bool selectNode(const Node& node, bool center) override; bool deselectNode(const Node& node) override; inline Node selectedNode() const override; inline QPointF selectedNodePos() const override; inline void clearSelection() override; CacheStatus refreshCache() override; - inline bool inSelectedNodes(const Node node) const override; - + inline bool inSelectedNodes(const Node& node) const override; + inline QPointF nodePoint(const QPointF& pos) override; + private slots: void setEdgeCMap(ColorMap* cmap); @@ -82,6 +84,7 @@ private slots: Star createStar(const Node& node, const qreal& edgeSizeRate, const QPointF& xy); void drawNode(QPainter& painter, const Star& s, double r) const; + void drawEdges(QPainter& painter) const; void drawNodes(QPainter& painter, double nodeRadius) const; void drawSelectedEdge(QPainter& painter, double nodeRadius) const; @@ -120,7 +123,10 @@ inline QPointF GraphView::nodePoint(const Node& node, const qreal& edgeSizeRate) return QPointF(edgeSizeRate * node.x(), edgeSizeRate * node.y()); } -inline bool GraphView::inSelectedNodes(const Node node) const +inline QPointF GraphView::nodePoint(const QPointF& pos) +{ return QPointF(pos.x() / currEdgeSize(), pos.y() / currEdgeSize()); } + +inline bool GraphView::inSelectedNodes(const Node& node) const { return m_selectedNodes.count(node.id()) != 0; } } // evoplex diff --git a/src/gui/gridview.cpp b/src/gui/gridview.cpp index a13b9d36..656eef74 100644 --- a/src/gui/gridview.cpp +++ b/src/gui/gridview.cpp @@ -69,6 +69,17 @@ CacheStatus GridView::refreshCache() return CacheStatus::Ready; } +void GridView::slotUpdateSelection() { + for (auto selectedNode : m_selectedNodes) { + int i = selectedNode.first; + const Node node = selectedNode.second; + + QRectF selectedCellRect = cellRect(node, m_nodeRadius); + + m_selectedCells.at(i).rect = selectedCellRect; + } +} + void GridView::paintFrame(QPainter& painter) const { if (m_nodeAttr < 0 || !m_nodeCMap) { diff --git a/src/gui/gridview.h b/src/gui/gridview.h index f6812d7d..268d9e71 100644 --- a/src/gui/gridview.h +++ b/src/gui/gridview.h @@ -31,6 +31,9 @@ class GridView : public BaseGraphGL public: explicit GridView(QWidget* parent); +public slots: + void slotUpdateSelection() override; + protected: void paintFrame(QPainter& painter) const override; Node selectNode(const QPointF& pos, bool center) override; @@ -41,7 +44,8 @@ class GridView : public BaseGraphGL inline QPointF selectedNodePos() const override; void clearSelection() override; CacheStatus refreshCache() override; - inline bool inSelectedNodes(const Node node) const override; + inline bool inSelectedNodes(const Node& node) const override; + inline QPointF nodePoint(const QPointF& pos) override; private: struct Cell { @@ -74,8 +78,11 @@ inline void GridView::clearSelection() { inline QRectF GridView::cellRect(const Node& n, double length) const { return QRectF(n.x() * length, n.y() * length, length, length); } -inline bool GridView::inSelectedNodes(const Node node) const +inline bool GridView::inSelectedNodes(const Node& node) const { return m_selectedNodes.count(node.id()) != 0; } +inline QPointF GridView::nodePoint(const QPointF& pos) +{ return QPointF(pos.x() / m_nodeRadius, pos.y() / m_nodeRadius); } + } // evoplex #endif // GRIDVIEW_H