55#include < dsr/gui/viewers/graph_viewer/graph_edge.h>
66#include < dsr/gui/viewers/graph_viewer/graph_viewer.h>
77#include < QMessageBox>
8+ #include < graphviz/cgraph.h>
9+ #include < graphviz/gvc.h>
10+ #include < graphviz/types.h>
11+ #include < qglobal.h>
12+ #include < string>
813
914using namespace DSR ;
1015
@@ -18,6 +23,9 @@ GraphViewer::GraphViewer(std::shared_ptr<DSR::DSRGraph> G_, QWidget *parent) :
1823 G = std::move (G_);
1924 own = std::shared_ptr<GraphViewer>(this );
2025
26+ graphviz_context = gvContext ();
27+ graphviz_graph = agopen ((char *)" G" , Agdirected, nullptr );
28+
2129 contextMenu = new QMenu (this );
2230 showMenu = contextMenu->addMenu (tr (" &Show:" ));
2331
@@ -55,6 +63,8 @@ GraphViewer::~GraphViewer()
5563
5664 }
5765 scene.clear ();
66+ agclose (graphviz_graph);
67+ gvFreeContext (graphviz_context);
5868}
5969
6070void GraphViewer::createGraph ()
@@ -157,6 +167,12 @@ void GraphViewer::add_or_assign_node_SLOT(uint64_t id, const std::string &type)
157167 color = G->get_attrib_by_name <color_att>(n.value ()).value_or (color);
158168 gnode->set_color (color);
159169 gnode->setType (type);
170+ auto id_str = std::to_string (id);
171+ Agnode_t* gvnode = agnode (graphviz_graph, id_str.data (), 1 );
172+ agset (gvnode, (char *)" width" , (char *)" 1.5" );
173+ agset (gvnode, (char *)" height" , (char *)" 1.5" );
174+ agset (gvnode, (char *)" shape" , (char *)" box" );
175+ agset (gvnode, (char *)" fixedsize" , (char *)" true" );
160176 }
161177 else
162178 {
@@ -186,6 +202,9 @@ void GraphViewer::add_or_assign_node_SLOT(uint64_t id, const std::string &type)
186202 add_or_assign_edge_SLOT (edges.from (), edges.to (), edges.type ());
187203 }
188204 }
205+
206+ this ->scene .setSceneRect (scene.itemsBoundingRect ());
207+ this ->fitInView (scene.itemsBoundingRect (), Qt::KeepAspectRatio );
189208}
190209
191210GraphNode* GraphViewer::new_visual_node (uint64_t id, const std::string &type, const std::string &name, bool debug)
@@ -215,6 +234,15 @@ void GraphViewer::add_or_assign_edge_SLOT(std::uint64_t from, std::uint64_t to,
215234 {
216235 auto item = this ->new_visual_edge (from, to, edge_tag);
217236 gmap_edges.insert (std::make_pair (key, item));
237+
238+ auto from_str = std::to_string (from);
239+ auto to_str = std::to_string (to);
240+ Agnode_t *gvnode_f = agfindnode (graphviz_graph, from_str.data ());
241+ Agnode_t *gvnode_t = agfindnode (graphviz_graph, to_str.data ());
242+
243+ Agedge_t* gvedge = agedge (graphviz_graph, gvnode_f, gvnode_t , nullptr , 1 );
244+ agset (gvedge, (char *)" type" , (char *)edge_tag.data ());
245+
218246 }
219247 if (gmap_edges[key]) gmap_edges[key]->change_detected ();
220248 }
@@ -266,6 +294,15 @@ void GraphViewer::del_edge_SLOT(std::uint64_t from, std::uint64_t to, const std:
266294 scene.removeItem (edge);
267295 delete edge;
268296 }
297+
298+ auto from_str = std::to_string (from);
299+ auto to_str = std::to_string (to);
300+ Agnode_t *gvnode_f = agfindnode (graphviz_graph, from_str.data ());
301+ Agnode_t *gvnode_t = agfindnode (graphviz_graph, to_str.data ());
302+
303+ if (Agedge_t *gvedge = agfindedge (graphviz_graph, gvnode_f, gvnode_t )) {
304+ agdeledge (graphviz_graph, gvedge);
305+ }
269306 }
270307 } catch (const std::exception &e) { std::cout << e.what () <<" Error " <<__FUNCTION__<<" :" <<__LINE__<< std::endl;}
271308
@@ -282,6 +319,10 @@ void GraphViewer::del_node_SLOT(uint64_t id)
282319 scene.removeItem (item);
283320 delete item;
284321 gmap.erase (id);
322+ auto id_str = std::to_string (id);
323+ if (Agnode_t *gvnode = agfindnode (graphviz_graph, id_str.data ())) {
324+ agdelnode (graphviz_graph, gvnode);
325+ }
285326 }
286327 } catch (const std::exception &e) { std::cout << e.what () <<" Error " <<__FUNCTION__<<" :" <<__LINE__<< std::endl;}
287328
@@ -333,4 +374,38 @@ void GraphViewer::remove_node_SLOT(uint64_t node_id)
333374{
334375 std::cout << " Remove node in graph_viewer class" <<node_id <<std::endl;
335376 G->delete_node (node_id);
377+ }
378+
379+ void GraphViewer::compute_layout (const char * alg) {
380+
381+ gvLayout (graphviz_context, graphviz_graph, alg);
382+
383+ qreal root_x = 0.0 , root_y = 0.0 ;
384+ for (Agnode_t* n = agfstnode (graphviz_graph); n; n = agnxtnode (graphviz_graph, n)) {
385+ auto name = agnameof (n);
386+ uint64_t id = std::stoull (name);
387+ double x = ND_coord (n).x ;
388+ double y = ND_coord (n).y ;
389+ auto *gnode = gmap.at (id);
390+ if (gnode) gnode->setPos (x, y);
391+ if (std::string_view (name) == std::string_view (" root" )) {
392+ root_x = x;
393+ root_y = y;
394+ }
395+ // We don't need to process the edges to render them
396+ // Uncomment this is the layout propagation is desired
397+ /* qDebug() << __FILE__ <<":"<<__FUNCTION__<< " node id in graphnode: " << id ;
398+ std::optional<Node> g_node = G->get_node(id);
399+ if (g_node.has_value()) {
400+ G->add_or_modify_attrib_local<pos_x_att>(*g_node, (float) x);
401+ G->add_or_modify_attrib_local<pos_y_att>(*g_node, (float) y);
402+ G->update_node(*g_node);
403+ }*/
404+ }
405+
406+ centerOn (root_x, root_y);
407+ this ->scene .setSceneRect (scene.itemsBoundingRect ());
408+ this ->fitInView (scene.itemsBoundingRect (), Qt::KeepAspectRatio );
409+
410+ gvFreeLayout (graphviz_context, graphviz_graph);
336411}
0 commit comments