YARP
Yet Another Robot Platform
 
Loading...
Searching...
No Matches
MainWindow.cpp
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2006-2021 Istituto Italiano di Tecnologia (IIT)
3 * SPDX-License-Identifier: GPL-3.0-or-later
4 */
5
6#include <fstream>
7
8#include "MainWindow.h"
9#include "moc_MainWindow.cpp"
10#include "ui_MainWindow.h"
11#include "QGVScene.h"
12#include "QGVNode.h"
13#include "QGVEdge.h"
14#include "QGVSubGraph.h"
15#include <QMessageBox>
16#include <QFileDialog>
17#include <QtPrintSupport/QPrinter>
18#include <QInputDialog>
19
20#include <yarp/os/Time.h>
21#include <yarp/os/LogStream.h>
23
24#include "informationdialog.h"
25#include "qosconfigdialog.h"
26#include "portloggerdialog.h"
27#include "batchqosconfdialog.h"
28#include <iomanip>
29#include <random>
30
31using namespace yarp::os;
32using namespace yarp::profiler;
33using namespace yarp::profiler::graph;
34
35
36MainWindow::MainWindow(QWidget *parent) :
37 QMainWindow(parent),
38 ui(new Ui::MainWindow),
39 scene(nullptr),
40 progressDlg(nullptr),
41 currentGraph(nullptr)
42{
43 ui->setupUi(this);
44 stringModel.setStringList(messages);
45 ui->messageView->setModel(&stringModel);
46 ui->messageView->setVisible(false);
47
48 // initialize the scene
49 initScene();
50
51 connect(ui->actionProfile_YARP_network, SIGNAL(triggered()),this,SLOT(onProfileYarpNetwork()));
52 connect(ui->actionHighlight_Loops, SIGNAL(triggered()),this,SLOT(onHighlightLoops()));
53 connect(ui->actionHideConnectionsLable, SIGNAL(triggered()),this,SLOT(onUpdateGraph()));
54 connect(ui->actionHideDisconnectedPorts, SIGNAL(triggered()),this,SLOT(onUpdateGraph()));
55 connect(ui->actionDebugMode, SIGNAL(triggered()),this,SLOT(onUpdateGraph()));
56 connect(ui->actionColorMode, SIGNAL(triggered()),this,SLOT(onUpdateGraph()));
57 connect(ui->actionOrthogonal, SIGNAL(triggered()),this,SLOT(onLayoutOrthogonal()));
58 connect(ui->actionCurved, SIGNAL(triggered()),this,SLOT(onLayoutCurved()));
59 connect(ui->actionPolyline, SIGNAL(triggered()),this,SLOT(onLayoutPolyline()));
60 connect(ui->actionLine, SIGNAL(triggered()),this,SLOT(onLayoutLine()));
61 connect(ui->actionSubgraph, SIGNAL(triggered()),this,SLOT(onUpdateGraph()));
62 connect(ui->actionHidePorts, SIGNAL(triggered()),this,SLOT(onUpdateGraph()));
63 connect(ui->nodesTreeWidget, SIGNAL(itemClicked(QTreeWidgetItem*, int)), this,
64 SLOT(onNodesTreeItemClicked(QTreeWidgetItem *, int)));
65 connect(ui->actionMessageBox, SIGNAL(triggered()),this,SLOT(onWindowMessageBox()));
66 connect(ui->actionItemswindow, SIGNAL(triggered()),this,SLOT(onWindowItem()));
67 connect(ui->actionExport_scene, SIGNAL(triggered()),this,SLOT(onExportScene()));
68 connect(ui->actionExport_connections_list, SIGNAL(triggered()),this,SLOT(onExportConList()));
69 connect(ui->actionConfigure_connections_QOS, SIGNAL(triggered()),this,SLOT(onConfigureConsQos()));
70 connect(ui->actionUpdateConnectionQosStatus, SIGNAL(triggered()),this,SLOT(onUpdateQosStatus()));
71 connect(ui->actionProfilePortsRate, SIGNAL(triggered()),this,SLOT(onProfilePortsRate()));
72 connect(ui->actionAbout, SIGNAL(triggered()),this,SLOT(onAbout()));
73 connect(ui->actionBackground_grid, SIGNAL(triggered()),this,SLOT(onBackgroundGrid()));
74
75 //progressDlg = new QProgressDialog("...", "Cancel", 0, 100, this);
76
77 layoutStyle = "ortho";
78 ui->actionOrthogonal->setChecked(true);
79 layoutSubgraph = true;
80 ui->actionSubgraph->setChecked(true);
81 ui->actionMessageBox->setChecked(false);
82 ui->actionItemswindow->setChecked(true);
83
84 ui->actionHighlight_Loops->setEnabled(false);
85 ui->actionHidePorts->setEnabled(false);
86 ui->actionHideDisconnectedPorts->setEnabled(false);
87 ui->actionHideConnectionsLable->setEnabled(false);
88 ui->actionDebugMode->setEnabled(false);
89 ui->actionUpdateConnectionQosStatus->setEnabled(false);
90
91 ui->action_Save_project->setEnabled(false);
92 ui->action_Load_project->setEnabled(false);
93 ui->actionDocumentaion->setEnabled(false);
94 ui->actionProfilePortsRate->setEnabled(false);
95 moduleParentItem = new QTreeWidgetItem( ui->nodesTreeWidget, QStringList("Modules"));
96 portParentItem = new QTreeWidgetItem( ui->nodesTreeWidget, QStringList("Ports"));
97 machinesParentItem = new QTreeWidgetItem( ui->nodesTreeWidget, QStringList("Machines"));
98 moduleParentItem->setIcon(0, QIcon(":icons/resources/module.svg"));
99 portParentItem->setIcon(0, QIcon(":icons/resources/port.svg"));
100 machinesParentItem->setIcon(0, QIcon(":icons/resources/computer_B.svg"));
101
102}
103
105{
106 delete ui;
107}
108
109void MainWindow::initScene() {
110 if(scene) {
111 scene->clear();
112 delete scene;
113 }
114 scene = new QGVScene("yarpviz", this);
115 sceneNodeMap.clear();
116 sceneSubGraphMap.clear();
117 ui->graphicsView->setBackgroundBrush(QBrush(QColor("#2e3e56"), Qt::SolidPattern));
118 ui->graphicsView->setScene(scene);
119 connect(scene, SIGNAL(nodeContextMenu(QGVNode*)), SLOT(nodeContextMenu(QGVNode*)));
120 connect(scene, SIGNAL(subGraphContextMenu(QGVSubGraph*)), SLOT(onSubGraphContextMenuProcess(QGVSubGraph*)));
121 connect(scene, SIGNAL(nodeDoubleClick(QGVNode*)), SLOT(nodeDoubleClick(QGVNode*)));
122 connect(scene, SIGNAL(edgeContextMenu(QGVEdge*)), SLOT(edgeContextMenu(QGVEdge*)));
123}
124
125void MainWindow::onProgress(unsigned int percentage) {
126 //yInfo()<<percentage<<"%";
127 if (progressDlg) {
128 progressDlg->setValue(percentage);
129 }
130}
131
133{
134 initScene();
135 if (graph.nodesCount() == 0) {
136 return;
137 }
138
139 layoutSubgraph = ui->actionSubgraph->isChecked();
140
141
142 //Configure scene attributes
143 //scene->setGraphAttribute("label", "yarp-viz");
144 scene->setGraphAttribute("splines", layoutStyle.c_str()); //curved, polyline, line. ortho
145 scene->setGraphAttribute("rankdir", "LR");
146 scene->setGraphAttribute("bgcolor", "#2e3e56");
147 //scene->setGraphAttribute("concentrate", "true"); //Error !
148 scene->setGraphAttribute("nodesep", "0.4");
149 scene->setGraphAttribute("ranksep", "0.5");
150 //scene->setNodeAttribute("shape", "box");
151 scene->setNodeAttribute("style", "filled");
152 scene->setNodeAttribute("fillcolor", "gray");
153 scene->setNodeAttribute("height", "1.0");
154 scene->setEdgeAttribute("minlen", "2.0");
155 //scene->setEdgeAttribute("dir", "both");
156
157 // drawing nodes
158 // create a map between graph nodes and their visualization
159 //std::map<const Vertex*, QGVNode*> nodeSet;
160
161 //adding all machine subgraphs
163 const pvertex_set& vertices = graph.vertices();
164 int countChild =0;
165 for(itr = vertices.begin(); itr!=vertices.end(); itr++) {
166 dynamic_cast<GraphicVertex*>(*itr)->setGraphicItem(nullptr);
167 const Property& prop = (*itr)->property;
169 if(dynamic_cast<MachineVertex*>(*itr))
170 {
171 std::string hostname = prop.find("hostname").asString();
172 if(layoutSubgraph) {
173 std::stringstream key;
174 key<<hostname;
175 if(sceneSubGraphMap[key.str()] == nullptr)
176 {
177 sgraph = scene->addSubGraph(prop.toString().c_str());
178 sceneSubGraphMap[key.str()] = sgraph;
179 dynamic_cast<GraphicVertex*>(*itr)->setGraphicItem(sgraph);
180 sgraph->setVertex(*itr);
181 //sgraph->setAttribute("label", prop.find("name").asString().c_str());
182 sgraph->setAttribute("color", "#FFFFFF");
183 std::string sgraphLabel = prop.find("hostname").toString();
184 int blankLength = std::max(int(sgraphLabel.length()/2.5),4);
186 std::string nodeS(size_t(blankLength/2), ' ');
188 sgraph->setAttribute("label", sgraphLabel.c_str());
189 std::string host = prop.find("os").asString();
190 if (host == "Linux") {
191 sgraph->setIcon(QImage(":/icons/resources/os-linux.png"));
192 } else if (host == "Windows") {
193 sgraph->setIcon(QImage(":/icons/resources/os-windows.png"));
194 } else if (host == "Mac") {
195 sgraph->setIcon(QImage(":/icons/resources/os-macos.png"));
196 } else {
197 sgraph->setIcon(QImage(":/icons/resources/system-run.png"));
198 }
199 std::string endNodeName = key.str() + ".end";
200 QGVNode * node = sgraph->addNode(endNodeName.c_str());
201 node->setAttribute("shape", "circle");
202 node->setAttribute("height", "0.0000000000001"); //a subgraph cannot be empty, adding fake hidden node
203 node->setAttribute("fixedsize", "true");
204 node->setAttribute("label", "");
205 node->setAttribute("fillcolor", "#2e3e56");
206 node->setAttribute("color", "#2e3e56");
207 node->setAttribute("node_type", "end");
208 node->setAttribute("rawname", endNodeName.c_str());
209 sceneNodeMap[endNodeName] = node;
210 }
211 }
212 }
213 }
214
215
216 // adding all process subgraphs
217
218 for(itr = vertices.begin(); itr!=vertices.end(); itr++) {
219 dynamic_cast<GraphicVertex*>(*itr)->setGraphicItem(nullptr);
220 const Property& prop = (*itr)->property;
222 if(dynamic_cast<ProcessVertex*>(*itr) && !prop.find("hidden").asBool())
223 {
224 int randNum = rand()%(16777214 - 0 + 1) + 0;
225 std::stringstream hexStream;
226 hexStream<<std::hex<< randNum;
227 std::string hexRandNum ="#" + hexStream.str();
228 std::string name = std::string(prop.find("name").asString()) + std::to_string(countChild);
229 if(layoutSubgraph)
230 {
231 std::stringstream key;
232 key<<prop.find("hostname").asString();
233 QGVSubGraph *sgraphParent = sceneSubGraphMap[key.str()];
234 if(sgraphParent == nullptr || (!ui->actionDebugMode->isChecked() && name.find("yarplogger") != std::string::npos))
235 {
236 continue;
237 }
238 sgraph = sgraphParent->addSubGraph(name.c_str());
239 countChild++;
240 }
241 else
242 {
243 continue;
244 }
245
246 std::stringstream labelStream;
247 labelStream << prop.find("name").asString().c_str()
248 << " (" << prop.find("pid").asInt32() << ")";
249 int blankLength = std::max(int(labelStream.str().length()/2.5),4);
251 std::string nodeS(size_t(blankLength/2), ' ');
252 std::string label = nodeS+labelStream.str()+nodeS;
253 sgraph->setAttribute("shape", "box");
254 sgraph->setAttribute("label", label.c_str());
255 if(prop.check("color")) {
256 sgraph->setAttribute("fillcolor", prop.find("color").asString().c_str());
257 sgraph->setAttribute("color", prop.find("color").asString().c_str());
258 }else {
259 sgraph->setAttribute("fillcolor", "#a5cf80");
260 sgraph->setAttribute("color", "#a5cf80");
261 }
262 sgraph->setAttribute("colorOfTheProcess", hexRandNum.c_str());
263 //nodeSet[*itr] = node;
264 dynamic_cast<GraphicVertex*>(*itr)->setGraphicItem(sgraph);
265 sgraph->setVertex(*itr);
266 std::stringstream keyProcess;
267 keyProcess<<prop.find("hostname").asString()<<prop.find("pid").asInt32();
268 std::string endNodeName = keyProcess.str() + ".end";
269 QGVNode * node = sgraph->addNode(endNodeName.c_str());
270 node->setAttribute("shape", "circle");
271 node->setAttribute("height", "0.0000000000001"); //a subgraph cannot be empty, adding fake hidden node
272 node->setAttribute("fixedsize", "true");
273 node->setAttribute("label", "");
274 node->setAttribute("fillcolor", "#2e3e56");
275 node->setAttribute("color", "#2e3e56");
276 node->setAttribute("node_type", "end");
277 node->setAttribute("rawname", endNodeName.c_str());
278 sceneNodeMap[endNodeName] = node;
279 sceneSubGraphMap[keyProcess.str()]= sgraph;
280 }
281 }
282
283 // adding port nodes
284 //pvertex_const_iterator itr;
285 //const pvertex_set& vertices = graph.vertices();
286 int portCounts = 0;
287
288 for(itr = vertices.begin(); itr!=vertices.end(); itr++) {
289 const Property& prop = (*itr)->property;
290 std::string portName = prop.find("name").asString();
291 if(dynamic_cast<PortVertex*>(*itr)) {
292 auto* pv = dynamic_cast<PortVertex*>(*itr);
293 auto* v = (ProcessVertex*) pv->getOwner();
294 if (ui->actionHideDisconnectedPorts->isChecked() && pv->property.find("orphan").asBool()) {
295 continue;
296 }
297 if (!ui->actionDebugMode->isChecked() && (portName.find("/log") != std::string::npos || portName.find("/yarplogger") != std::string::npos)) {
298 continue;
299 }
300 std::stringstream key;
301 if(v->property.find("hidden").asBool())
302 {
303 pv->property.put("hidden",true);
304 updateNodeWidgetItems();
305 continue;
306 } else if (prop.find("hidden").asBool()) {
307 continue;
308 }
309 QGVNode *node;
311
312 int blankLength = std::round(portName.length()/7);
314 std::string nodeS(size_t(blankLength/2), ' ');
315 std::string nodeName = nodeS+portName+nodeS;
316 if(layoutSubgraph) {
317 key<<v->property.find("hostname").asString()<<v->property.find("pid").asInt32();
318 QGVSubGraph *sgraph = sceneSubGraphMap[key.str()];
319 if(sgraph)
320 {
321 node = sgraph->addNode(nodeName.c_str());
322 if(ui->actionColorMode->isChecked())
323 {
324 QColor color(sgraph->getAttribute("colorOfTheProcess"));
325 if (color.lightness() < 100) {
326 node->setAttribute("labelfontcolor", "#ffffff");
327 }
328 colorProcess = sgraph->getAttribute("colorOfTheProcess");
329 }
330 } else {
331 node = scene->addNode(nodeName.c_str());
332 }
333 } else {
334 node = scene->addNode(nodeName.c_str());
335 }
336 node->setAttribute("shape", "ellipse");
337 if(prop.check("color")) {
338 node->setAttribute("fillcolor", prop.find("color").asString().c_str());
339 node->setAttribute("color", prop.find("color").asString().c_str());
340 }
341 else if(!colorProcess.isEmpty())
342 {
343 node->setAttribute("fillcolor", colorProcess);
344 node->setAttribute("color", colorProcess);
345 }
346 else {
347 node->setAttribute("fillcolor", "#edad56");
348 node->setAttribute("color", "#edad56");
349 }
350 //nodeSet[*itr] = node;
351 dynamic_cast<GraphicVertex*>(*itr)->setGraphicItem(node);
352 node->setVertex(*itr);
353 portCounts++;
354 }
355 }
356
357 // arrange the nodes deifferently if they are not port nodes
358 if(portCounts == 0) {
359 scene->setGraphAttribute("nodesep", "0.5");
360 scene->setGraphAttribute("ranksep", "1.5");
361 }
362
363 for(itr = vertices.begin(); itr!=vertices.end(); itr++) {
364 const Vertex &v1 = (**itr);
365 for(const auto& edge : v1.outEdges()) {
366 const Vertex &v2 = edge.second();
367 std::string targetName = v2.property.find("name").asString();
368 if (!ui->actionDebugMode->isChecked() && targetName.find("/yarplogger") != std::string::npos) {
369 continue;
370 }
371 //yInfo()<<"Drawing:"<<v1.property.find("name").asString()<<" -> "<<v2.property.find("name").asString();
372 // add ownership edges
373 if(!v1.property.find("hidden").asBool() && !v2.property.find("hidden").asBool()) {
374 if(edge.property.find("type").asString() == "ownership" &&
375 edge.property.find("dir").asString() != "unknown") {
376 continue;
377 }
378
379 if(edge.property.find("type").asString() == "connection") {
380 //QGVEdge* gve = scene->addEdge(nodeSet[&v1], nodeSet[&v2],
381 // edge.property.find("carrier").asString().c_str());
382 std::string label;
383 if(!ui->actionHideConnectionsLable->isChecked())
384 {
385 label = edge.property.find("carrier").asString();
386 int blankLength = std::max(int(label.length()/2.5),4);
388 std::string nodeS(size_t(blankLength/2), ' ');
389 label = nodeS+label+nodeS;
390 }
391 QGVEdge* gve = scene->addEdge((QGVNode*)((GraphicVertex*)&v1)->getGraphicItem(),
392 (QGVNode*)((GraphicVertex*)&v2)->getGraphicItem(),
393 label.c_str());
395 (QosStyle::PacketPriorityLevel)edge.property.find("FromPacketPriority").asInt32();
396 switch (level) {
398 gve->setAttribute("color", "white");
399 break;
401 gve->setAttribute("color", "orange");
402 break;
404 gve->setAttribute("color", "red");
405 break;
407 gve->setAttribute("color", "yellow");
408 break;
409 default:
410 gve->setAttribute("color", "white");
411 break;
412 }
413 //gve->setToolTip("hello!");
414 gve->setEdge(&edge);
415 }
416 }
417 }
418 }
419
420 //Layout scene
421 scene->applyLayout();
422
423 //Fit in view
424 ui->graphicsView->fitInView(scene->sceneRect(), Qt::KeepAspectRatio);
425
426 //QGVSubGraph *ssgraph = sgraph->addSubGraph("SUB2");
427 //ssgraph->setAttribute("label", "DESK");
428 //scene->addEdge(snode1, ssgraph->addNode("PC0155"), "S10");
429}
430
431void MainWindow::edgeContextMenu(QGVEdge* edge) {
432 const Edge* e = (const Edge*)edge->getEdge();
433 if (e == nullptr) {
434 return;
435 }
436
437 //yInfo()<<"edge clicked!";
438 //Context menu example
439 QMenu menu(edge->label());
440 menu.addSeparator();
441 menu.addAction(tr("Information..."));
442 menu.addAction(tr("Configure Qos..."));
443 //menu.addAction(tr("Hide"));
444 QAction *action = menu.exec(QCursor::pos());
445 if (action == nullptr) {
446 return;
447 }
448 if(action->text().toStdString() == "Information...") {
450 dialog.setEdgeInfo((Edge*)e);
451 dialog.setModal(true);
452 dialog.exec();
453 }
454 else if(action->text().toStdString() == "Configure Qos...") {
456 dialog.setModal(true);
457 dialog.exec();
458 }
459}
460
461void MainWindow::nodeContextMenu(QGVNode *node)
462{
463 auto* v = (GraphicVertex*) node->getVertex();
464 yAssert(v != nullptr);
465 if (v->property.find("type").asString() == "port") {
466 onNodeContextMenuPort(node, v);
467 } else {
468 yWarning() << "nodeContextMenu(): Unknown node!";
469 }
470}
471
472void MainWindow::onSubGraphContextMenuProcess(QGVSubGraph *sgraph) {
473 GraphicVertex* vertex;
474 vertex = (GraphicVertex*) sgraph->getVertex();
475
476 if (!vertex || vertex->property.find("type").asString() != "process") {
477 return;
478 }
479
480
481 QMenu menu(sgraph->getAttribute("label"));
482 menu.addSeparator();
483 menu.addAction(tr("Information..."));
484 menu.addAction(tr("Hide"));
485 QAction *action = menu.exec(QCursor::pos());
486 if (action == nullptr) {
487 return;
488 }
489 if(action->text().toStdString() == "Information...") {
491 dialog.setProcessVertexInfo((ProcessVertex*)vertex);
492 dialog.setModal(true);
493 dialog.exec();
494 }
495 else if(action->text().toStdString() == "Hide") {
496 vertex->property.put("hidden", true);
497 updateNodeWidgetItems();
498 drawGraph(*currentGraph);
499 }
500}
501
502void MainWindow::onAbout() {
503 QMessageBox::about(this, "yarpviz (version 2.0.0)",
504 "A graphical tool for a graphical tool for profiling and visualizing YARP network!");
505}
506
507void MainWindow::onNodeContextMenuPort(QGVNode *node, GraphicVertex* vertex) {
508 //Context menu example
509 QMenu menu(node->label());
510 menu.addSeparator();
511 menu.addAction(tr("Information..."));
512 menu.addAction(tr("Hide"));
513 QAction *action = menu.exec(QCursor::pos());
514 if (action == nullptr) {
515 return;
516 }
517 if(action->text().toStdString() == "Information...") {
519 dialog.setPortVertexInfo((PortVertex*)vertex);
520 dialog.setModal(true);
521 dialog.exec();
522 }
523 else if(action->text().toStdString() == "Hide") {
524 vertex->property.put("hidden", true);
525 updateNodeWidgetItems();
526 drawGraph(*currentGraph);
527 }
528}
529
530
531void MainWindow::nodeDoubleClick(QGVNode *node)
532{
533 QMessageBox::information(this, tr("Node double clicked"), tr("Node %1").arg(node->label()));
534}
535
536void MainWindow::onProfileYarpNetwork() {
537
538 if(mainGraph.nodesCount()) {
539 QMessageBox::StandardButton reply;
540 reply = QMessageBox::question(this, "Profiling: clear current project", "Running profiler will clear the current project.\n Are you sure?",
541 QMessageBox::Yes|QMessageBox::No);
542 if (reply == QMessageBox::No) {
543 return;
544 }
545 }
546
547 mainGraph.clear();
549 inputDialog->setOptions(QInputDialog::NoButtons);
550
551 bool ok=false;
552
553 float timeout = inputDialog->getDouble(nullptr ,"Profiling: yarp clean",
554 "Do you want to run yarp clean before profiling?\n\n"
555 "Be aware that yarp clean with a little timetout could\n"
556 "unregister ports that are actually open.\n\n"
557 "Timeout(seconds):", 0.3, 0, 2147483647, 1, &ok);
558 if (ok)
559 {
560 messages.append("Cleaning death ports...");
561 NetworkProfiler::yarpClean(timeout);
562 }
563
564 messages.append("Getting the ports list...");
566 NetworkProfiler::getPortsList(ports);
567
568
569 messages.append("Getting the ports details...");
571 progressDlg = new QProgressDialog("...", "Cancel", 0, 100, this);
572
573 progressDlg->setLabelText("Getting the ports details...");
574 progressDlg->reset();
575 progressDlg->setRange(0, ports.size());
576 progressDlg->setValue(0);
577 progressDlg->setWindowModality(Qt::WindowModal);
578 progressDlg->show();
579 for(size_t i=0; i<ports.size(); i++) {
581 std::string portname = ports[i].name;
582 std::string msg = std::string("Checking ") + portname + "...";
583 messages.append(QString(msg.c_str()));
584 if (NetworkProfiler::getPortDetails(portname, info)) {
585 portsInfo.push_back(info);
586 }
587 progressDlg->setValue(i);
588 if (progressDlg->wasCanceled()) {
589 return;
590 }
591 }
592 //progressDlg->setValue(ports.size());
593 stringModel.setStringList(messages);
594 ui->messageView->update();
595
597 progressDlg->setLabelText("Generating the graph...");
598 progressDlg->setRange(0, 100);
599 progressDlg->setValue(0);
601 progressDlg->close();
602 delete progressDlg;
603 progressDlg = nullptr;
604
605
606 // update QoS
608 moduleParentItem->setExpanded(true);
609 portParentItem->setExpanded(true);
610 machinesParentItem->setExpanded(true);
611 currentGraph = &mainGraph;
612
613 // add process and port nodes to the tree
614 populateTreeWidget();
615
616 drawGraph(*currentGraph);
617 ui->actionHighlight_Loops->setEnabled(true);
618 ui->actionHidePorts->setEnabled(true);
619 ui->actionHideDisconnectedPorts->setEnabled(true);
620 ui->actionHideConnectionsLable->setEnabled(true);
621 ui->actionDebugMode->setEnabled(true);
622 ui->actionUpdateConnectionQosStatus->setEnabled(true);
623 ui->actionProfilePortsRate->setEnabled(true);
624}
625
626void MainWindow::onHighlightLoops() {
627 if (!currentGraph) {
628 return;
629 }
630
631 if(ui->actionHighlight_Loops->isChecked()) {
633 Algorithm::calcSCC(*currentGraph, scc);
634
635 std::default_random_engine randengine;
636 std::uniform_int_distribution<int> udistH(128, 255);
637 std::uniform_int_distribution<int> udistL(0, 128);
638
639 for(auto& vset : scc) {
641 for (auto& j : vset) {
642 j->property.put("color", color.name().toStdString());
643 }
644 }
645 }
646 else {
648 const pvertex_set& vertices = currentGraph->vertices();
649 for(itr = vertices.begin(); itr!=vertices.end(); itr++) {
650 (*itr)->property.unput("color");
651 }
652 }
653 drawGraph(*currentGraph);
654}
655
656
657void MainWindow::updateNodeWidgetItems() {
658
659 NodeWidgetItem* item= nullptr;
660 for (int i= moduleParentItem->childCount()-1; i>-1; i--) {
661 item = (NodeWidgetItem*) moduleParentItem->child(i);
662 yAssert(item != nullptr);
663 item->check(!item->getVertex()->property.find("hidden").asBool());
664 }
665 for (int i= portParentItem->childCount()-1; i>-1; i--) {
666 item = (NodeWidgetItem*) portParentItem->child(i);
667 yAssert(item != nullptr);
668 item->check(!item->getVertex()->property.find("hidden").asBool());
669 }
670 for (int i= machinesParentItem->childCount()-1; i>-1; i--) {
671 item = (NodeWidgetItem*) machinesParentItem->child(i);
672 yAssert(item != nullptr);
673 item->check(!item->getVertex()->property.find("hidden").asBool());
674 }
675}
676
677void MainWindow::populateTreeWidget(){
678 QTreeWidgetItem* item= nullptr;
679 for (int i= moduleParentItem->childCount()-1; i>-1; i--) {
680 item = moduleParentItem->child(i);
681 delete item;
682 }
683 for (int i= portParentItem->childCount()-1; i>-1; i--) {
684 item = portParentItem->child(i);
685 delete item;
686 }
687 for (int i= machinesParentItem->childCount()-1; i>-1; i--) {
688 item = machinesParentItem->child(i);
689 delete item;
690 }
692 const pvertex_set& vertices = currentGraph->vertices();
693 for(itr = vertices.begin(); itr!=vertices.end(); itr++) {
694 const Property& prop = (*itr)->property;
695 if(dynamic_cast<ProcessVertex*>(*itr)) {
696 std::string processName = prop.find("name").asString();
697 if(!ui->actionDebugMode->isChecked() && processName.find("yarplogger") != std::string::npos)
698 {
699 continue;
700 }
701 auto* moduleItem = new NodeWidgetItem(moduleParentItem, (*itr), MODULE);
702 moduleItem->setFlags( Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsUserCheckable );
703 moduleItem->check(true);
704 }
705 else if(dynamic_cast<PortVertex*>(*itr) && !ui->actionHidePorts->isChecked()) {
706 std::string portName = prop.find("name").asString();
707 if(ui->actionHideDisconnectedPorts->isChecked()){
708 if (prop.check("orphan")) {
709 continue;
710 }
711 }
712 if (!ui->actionDebugMode->isChecked() && (portName.find("/log") != std::string::npos || portName.find("/yarplogger") != std::string::npos)) {
713 continue;
714 }
715 auto* portItem = new NodeWidgetItem(portParentItem, (*itr), PORT);
716 portItem->setFlags( Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsUserCheckable );
717 portItem->check(true);
718 }
719 else if(dynamic_cast<MachineVertex*>(*itr)) {
720 auto* machineItem = new NodeWidgetItem(machinesParentItem, (*itr), MACHINE);
721 machineItem->setFlags( /*Qt::ItemIsSelectable | */Qt::ItemIsEnabled /*| Qt::ItemIsUserCheckable */);
722 machineItem->check(true);
723 }
724 }
725 moduleParentItem->setExpanded(true);
726 portParentItem->setExpanded(true);
727 machinesParentItem->setExpanded(true);
728}
729
730void MainWindow::onLayoutOrthogonal() {
731 ui->actionPolyline->setChecked(false);
732 ui->actionLine->setChecked(false);
733 ui->actionCurved->setChecked(false);
734 layoutStyle = "ortho";
735 if (currentGraph) {
736 drawGraph(*currentGraph);
737 }
738}
739
740void MainWindow::onLayoutPolyline() {
741 ui->actionOrthogonal->setChecked(false);
742 ui->actionLine->setChecked(false);
743 ui->actionCurved->setChecked(false);
744 layoutStyle = "polyline";
745 if (currentGraph) {
746 drawGraph(*currentGraph);
747 }
748}
749
750void MainWindow::onLayoutLine() {
751 ui->actionOrthogonal->setChecked(false);
752 ui->actionPolyline->setChecked(false);
753 ui->actionCurved->setChecked(false);
754 layoutStyle = "line";
755 if (currentGraph) {
756 drawGraph(*currentGraph);
757 }
758}
759
760void MainWindow::onLayoutCurved() {
761 ui->actionOrthogonal->setChecked(false);
762 ui->actionPolyline->setChecked(false);
763 ui->actionLine->setChecked(false);
764 layoutStyle = "curved";
765 drawGraph(*currentGraph);
766}
767
768
769void MainWindow::onUpdateGraph() {
770 if(currentGraph)
771 {
772 if(ui->actionHidePorts->isChecked()){
773 NetworkProfiler::creatSimpleModuleGraph(mainGraph, simpleGraph);
774 currentGraph = &simpleGraph;
775 }
776 else{
777 currentGraph = &mainGraph;
778 }
779 populateTreeWidget();
780 drawGraph(*currentGraph);
781 }
782}
783
784void MainWindow::onNodesTreeItemClicked(QTreeWidgetItem *item, int column){
785 if (item->type() != MODULE && item->type() != PORT) {
786 return;
787 }
788
789 bool state = (item->checkState(column) == Qt::Checked);
790 bool needUpdate = state != ((NodeWidgetItem*)(item))->checked();
791 ((NodeWidgetItem*)(item))->check(state);
792 if (needUpdate) {
793 drawGraph(*currentGraph);
794 }
795
796 QList<QGraphicsItem *> items = scene->selectedItems();
797 foreach( QGraphicsItem *item, items )
798 item->setSelected(false);
799 auto* yv = (GraphicVertex*)((NodeWidgetItem*)(item))->getVertex();
800 auto* graphicItem = (QGraphicsItem*) yv->getGraphicItem();
801 if(graphicItem) {
802 graphicItem->setSelected(true);
803 if(state){
804 ui->graphicsView->centerOn(graphicItem);
805 }
806 }
807}
808
809void MainWindow::onWindowMessageBox() {
810 ui->messageView->setVisible(ui->actionMessageBox->isChecked());
811}
812
813void MainWindow::onWindowItem() {
814 ui->nodesTreeWidget->setVisible(ui->actionItemswindow->isChecked());
815}
816
817void MainWindow::onUpdateQosStatus() {
819 drawGraph(*currentGraph);
820}
821
822void MainWindow::onProfilePortsRate() {
823 yAssert(currentGraph!=nullptr);
824 PortLoggerDialog dialog(currentGraph);
825 dialog.setModal(false);
826 dialog.exec();
827}
828
829void MainWindow::onConfigureConsQos() {
831 dialog.setModal(false);
832 dialog.exec();
833}
834
835void MainWindow::onExportConList() {
836 QString filters("Text files (*.txt);;All files (*.*)");
837 QString defaultFilter("Image file (*.txt)");
838 QString filename = QFileDialog::getSaveFileName(nullptr, "Export connections list",
839 QDir::homePath(),
841 if (filename.size() == 0) {
842 return;
843 }
844
845 std::ofstream file;
846 file.open(filename.toStdString().c_str());
847 if(!file.is_open()) {
848 QMessageBox::critical(nullptr, QObject::tr("Error"), QObject::tr("Cannot open the file for saving"));
849 return;
850 }
851
852 // adding all process nodes and subgraphs
854 const pvertex_set& vertices = currentGraph->vertices();
855 for(itr = vertices.begin(); itr!=vertices.end(); itr++) {
856 const Vertex &v1 = (**itr);
857 for(const auto& i : v1.outEdges()) {
858 Edge& edge = (Edge&) i;
859 const Vertex &v2 = edge.second();
860 if(!v1.property.find("hidden").asBool() && !v2.property.find("hidden").asBool()) {
861 if(edge.property.find("type").asString() == "connection") {
862 Bottle bt;
863 bt.addString(v1.property.find("name").asString());
864 bt.addString(v2.property.find("name").asString());
865 bt.addString(edge.property.find("carrier").asString());
866 file<<bt.toString().c_str()<<'\n';
867 //yInfo()<<v1.property.find("name").asString()<<"->"<<v2.property.find("name").asString();
868 }
869 }
870 }
871 }
872 file.close();
873
874}
875
876void MainWindow::onExportScene() {
877 QString filters("Image files (*.png);;All files (*.*)");
878 QString defaultFilter("Image file (*.png)");
879 QString filename = QFileDialog::getSaveFileName(nullptr, "Export scene",
880 QDir::homePath(),
882 if (filename.size() == 0) {
883 return;
884 }
885
886 QImage image(scene->sceneRect().size().toSize(), QImage::Format_ARGB32); // Create the image with the exact size of the shrunk scene
887 image.fill(QColor("#2e3e56"));
889 painter.setRenderHint(QPainter::Antialiasing);
890 scene->render(&painter);
891 if (!image.save(filename)) {
892 yError() << "Cannot save scene to" << filename.toStdString();
893 }
894
895 /*
896 QPrinter printer( QPrinter::HighResolution );
897 //printer.setPageSize( QPrinter::A4 );
898 printer.setOrientation( QPrinter::Landscape );
899 printer.setOutputFormat( QPrinter::PdfFormat );
900 printer.setOutputFileName( filename ); // file will be created in your build directory (where debug/release directories are)
901 QPainter p;
902 if(!p.begin(&printer)){
903 yError() << "Error!";
904 return;
905 }
906 this->scene->render( &p );
907 p.end();
908 */
909}
910
911void MainWindow::onBackgroundGrid()
912{
913 scene->enableBgGrid(ui->actionBackground_grid->isChecked());
914}
std::vector< pvertex_set > graph_subset
Definition Graph.h:37
pvertex_set::const_iterator pvertex_const_iterator
Definition Graph.h:35
std::vector< yarp::profiler::graph::Vertex * > pvertex_set
Definition Graph.h:33
#define yError(...)
Definition Log.h:361
#define yAssert(x)
Definition Log.h:388
#define yWarning(...)
Definition Log.h:340
@ PORT
Definition MainWindow.h:20
@ MODULE
Definition MainWindow.h:19
@ MACHINE
Definition MainWindow.h:21
std::default_random_engine randengine
Definition Random.cpp:13
int SIGNAL(int pid, int signum)
MainWindow class.
Definition display.h:22
MainWindow(const yarp::os::ResourceFinder &rf, yarp::dev::IBattery *ibat, QWidget *parent=0, double refresh_period=10.0)
Definition display.cpp:186
std::string portname
Definition display.h:67
QGraphicsScene * scene
Definition display.h:37
void drawGraph(yarp::profiler::graph::Graph &graph)
void onProgress(unsigned int percentage) override
A simple collection of objects that can be described and transmitted in a portable way.
Definition Bottle.h:64
void addString(const char *str)
Places a string in the bottle, at the end of the list.
Definition Bottle.cpp:170
std::string toString() const override
Gives a human-readable textual representation of the bottle.
Definition Bottle.cpp:211
A mini-server for performing network communication in the background.
void close() override
Stop port activity.
A class for storing options and configuration information.
Definition Property.h:33
Value & find(const std::string &key) const override
Gets a value corresponding to a given keyword.
std::string toString() const override
Return a standard text representation of the content of the object.
void put(const std::string &key, const std::string &value)
Associate the given key with the given string.
Definition Property.cpp:987
bool check(const std::string &key) const override
Check if there exists a property of the given name.
PacketPriorityLevel
The PacketPriorityLevel defines the packets quality of service (priority) levels.
Definition QosStyle.h:30
bool check(const std::string &key) const override
Check if there exists a property of the given name.
virtual bool asBool() const
Get boolean value.
Definition Value.cpp:186
virtual std::int32_t asInt32() const
Get 32-bit integer value.
Definition Value.cpp:204
std::string toString() const override
Return a standard text representation of the content of the object.
Definition Value.cpp:356
virtual std::string asString() const
Get string value.
Definition Value.cpp:234
std::vector< PortDetails > ports_detail_set
static bool updateConnectionQosStatus(yarp::profiler::graph::Graph &graph)
static bool creatNetworkGraph(ports_detail_set details, yarp::profiler::graph::Graph &graph)
creatNetworkGraph
static bool creatSimpleModuleGraph(yarp::profiler::graph::Graph &graph, yarp::profiler::graph::Graph &subgraph)
static void setProgressCallback(ProgressCallback *callback)
static bool calcSCC(yarp::profiler::graph::Graph &graph, graph_subset &scc)
calcSCC
Definition Graph.cpp:249
The yarp::profiler::graph::Edge class.
Definition Graph.h:45
const yarp::profiler::graph::Vertex & second() const
Definition Graph.cpp:44
yarp::os::Property property
Definition Graph.h:61
The yarp::profiler::graph::Graph class.
Definition Graph.h:104
const pvertex_set & vertices()
Definition Graph.h:126
void setGraphicItem(void *item)
Definition Graph.h:152
The yarp::profiler::graph::Vertex class.
Definition Graph.h:72
yarp::os::Property property
Definition Graph.h:89
Definition aboutdlg.h:11
const yarp::sig::VectorOf< std::pair< int, int > > vertices
An interface to the operating system, including Port based communication.