TestProject  0.0.1
graph_display.cpp
1 #include <tulip/PluginLoaderTxt.h>
2 #include <tulip/PluginLibraryLoader.h>
3 #include <tulip/GlMainWidget.h>
4 #include <tulip/MouseInteractors.h>
5 #include <tulip/TlpQtTools.h>
6 #include <tulip/LayoutProperty.h>
7 #include <tulip/SizeProperty.h>
8 #include <tulip/StringProperty.h>
9 #include <tulip/DoubleProperty.h>
10 #include <tulip/IntegerProperty.h>
11 #include <tulip/TulipViewSettings.h>
12 #include <tulip/GlGraphComposite.h>
13 #include <tulip/GlGraphRenderingParameters.h>
14 #include <tulip/ForEach.h>
15 #include <QApplication>
16 #include <QString>
17 #include <iostream>
18 
19 #include <QEvent>
20 #include <QKeyEvent>
21 
22 using namespace tlp;
23 using namespace std;
24 
25 class InteractorPlugin : public MousePanNZoomNavigator {
26  Graph *graph;
27  GlMainWidget *mainWidget;
28 public:
29  /*
30  Basic constructor
31  In this constructor we create a label to display information
32  And a QGraphicsProxyWidget to show information in Tulip QGraphics system
33  */
34  InteractorPlugin(Graph *_g, GlMainWidget *_widget) : graph(_g), mainWidget(_widget), MousePanNZoomNavigator()
35  {
36 
37  }
38 
39  /*
40  Most important function of an interactor component
41  When an event arrive on your interactor : this function is call
42  You have to process it and return true. If the event do nothing in your interactor : this function return false;
43  */
44  bool eventFilter(QObject *obj, QEvent* e) {
45  bool apply_plugin = false;
46  bool handled = false;
47 
48  float cluster_spacing = 0;
49  graph->getAttribute("cluster_spacing", cluster_spacing);
50 
51  if (e->type() == QEvent::KeyPress) {
52  QKeyEvent *ke = static_cast<QKeyEvent*>(e);
53  int delta = (ke->isAutoRepeat() ? 3 : 1);
54 
55  switch (ke->key()) {
56  case Qt::Key_A:
57  cluster_spacing -= 0.01f;
58  if (cluster_spacing < 0)
59  cluster_spacing = 0;
60  apply_plugin = true;
61  handled = true;
62  break;
63  case Qt::Key_S:
64  cluster_spacing += 0.01f;
65  apply_plugin = true;
66  handled = true;
67  break;
68  }
69  }
70 
71  if (apply_plugin)
72  {
73  graph->setAttribute("cluster_spacing", cluster_spacing);
74  LayoutProperty *viewLayout = graph->getProperty<LayoutProperty>("viewLayout");
75  std::string errMsg;
76  graph->applyPropertyAlgorithm("SFCLayout", viewLayout, errMsg);
77  cout << "SFCLayout errMsg: " << errMsg << endl;
78 
79  mainWidget->draw();
80  }
81 
82  if (handled)
83  return true;
84 
85  return MousePanNZoomNavigator::eventFilter(obj, e);
86  }
87 };
88 
89 void addChildren(Graph *graph, node root, int depth, int degree) {
90  if (depth > 0) {
91  for (int i = 0; i < degree; ++i) {
92  node child = graph->addNode();
93  graph->addEdge(root, child);
94  addChildren(graph, child, depth - 1, degree);
95  }
96  }
97 }
98 
99 Graph *createCompleteTree(int depth, int degree) {
100  Graph *graph = newGraph();
101  node root = graph->addNode();
102  addChildren(graph, root, depth, degree);
103  return graph;
104 }
105 
106 void setVisualProperties(Graph *tree) {
107  // Labels the node with their id
108  StringProperty *viewLabel = tree->getProperty<StringProperty>("viewLabel");
109  node n;
110  forEach(n, tree->getNodes()) {
111  viewLabel->setNodeValue(n, QString::number(n.id).toStdString());
112  }
113  // Add a border to the nodes, keep the default color who is black
114  DoubleProperty *viewBorderWidth = tree->getProperty<DoubleProperty>("viewBorderWidth");
115  viewBorderWidth->setAllNodeValue(1);
116 }
117 
118 void setGraphRenderingParameters(GlGraphComposite *glGraphComposite) {
119  GlGraphRenderingParameters *renderingParameters = glGraphComposite->getRenderingParametersPointer();
120  // Activate the display of edge extremities (arrows by default)
121  renderingParameters->setAntialiasing(true);
122 
123  renderingParameters->setDisplayNodes(true);
124 
125  renderingParameters->setLabelsDensity(100);
126 
127  renderingParameters->setViewArrow(false);
128  // No color interpolation for the edges
129  renderingParameters->setEdgeColorInterpolate(false);
130  // Size interpolation for the edges
131  renderingParameters->setEdgeSizeInterpolate(false);
132  // Scale labels to node sizes
133  renderingParameters->setLabelScaled(true);
134 }
135 
136 int main(int argc, char** argv) {
137  // A QApplication must always be declared at the beginning of the main function if you intend to use the tulip-gui library
138  // This must be done before calling tlp::initTulipSoftware()
139  QApplication app(argc, argv);
140 
141  // Initialize the library and load all plugins
142 tlp:PluginLoader * plugin_loader = new tlp::PluginLoaderTxt();
143  tlp::initTulipSoftware(plugin_loader);
144  Graph* g = NULL;
145 
146  if (QApplication::arguments().size() == 2) {
147  // Load the file passed as first argument into a graph.
148  // This method will select the default Tulip algorithm plugin (TLP)
149  QString filename = QApplication::arguments()[1];
150  if (!((filename.endsWith(".tlp")) || (filename.endsWith(".tlp.gz")))) {
151  cout << "File " << filename.toStdString() << " not compatible. Use a tlp file or a tlp.gz file" << endl;
152  exit(EXIT_FAILURE);
153  }
154  g = tlp::loadGraph(filename.toStdString());
155  }
156  else {
157  // If no arguments were given to the command, create a complete tree of depth 5
158  // and degree 6 for demo purpose
159  g = createCompleteTree(5, 6);
160  // Set some visual properties in order to visualize the tree
161  //setTreeVisualProperties(g);
162  }
163 
164  float cluster_spacing = 2;
165  g->setAttribute("cluster_spacing", cluster_spacing);
166 
167  LayoutProperty *viewLayout = g->getProperty<LayoutProperty>("viewLayout");
168  std::string errMsg;
169  g->applyPropertyAlgorithm("SFCLayout", viewLayout, errMsg);
170  cout << "SFCLayout errMsg: " << errMsg << endl;
171 
172  // Creates the main widget that will display our graph
173  GlMainWidget* mainWidget = new GlMainWidget(NULL);
174  // Adds a layer to the scene
175  GlLayer* mainLayer = mainWidget->getScene()->createLayer("Main");
176 
177  // Adds the graph to this layer
178  //mainLayer->addGraph(g,"graph");
179  Graph * sg = g->getSubGraph("original");
180  //Graph * sg = g->getSubGraph("clustering");
181  setVisualProperties(sg);
182  mainLayer->addGraph(sg, "graph");
183 
184  // Sets some rendering parameters on the graph to visualize
185  setGraphRenderingParameters(mainWidget->getScene()->getGlGraphComposite());
186  // Display the widget
187  mainWidget->show();
188  // Flush event loop in order to let paint events pass through in order for the scene to be initialized.
189  QApplication::processEvents();
190  // Center the camera and draw the graph
191  mainWidget->centerScene();
192  mainWidget->draw();
193  // Adds Zoom and pan navigation to the widget
194  mainWidget->installEventFilter(new MouseNKeysNavigator);
195  //InteractorComposite * interactorPlugin = tlp::PluginLister::instance()->getPluginObject<InteractorComposite>("InteractorPlugin", 0);
196  InteractorPlugin interactorPlugin(g, mainWidget);
197  //InteractorPluginComponent interactorPlugin;
198  //interactorPlugin.install(mainWidget);
199  mainWidget->installEventFilter(&interactorPlugin);
200  //mainWidget->setCurrentInteractor(interactorPlugin);
201  return app.exec();
202 }