]> Creatis software - cpPlugins.git/blob - appli/cpPipelineEditor/GraphWidget.cxx
Pipeline editor added.
[cpPlugins.git] / appli / cpPipelineEditor / GraphWidget.cxx
1 /****************************************************************************
2  **
3  ** Copyright (C) 2015 The Qt Company Ltd.
4  ** Contact: http://www.qt.io/licensing/
5  **
6  ** This file is part of the examples of the Qt Toolkit.
7  **
8  ** $QT_BEGIN_LICENSE:BSD$
9  ** You may use this file under the terms of the BSD license as follows:
10  **
11  ** "Redistribution and use in source and binary forms, with or without
12  ** modification, are permitted provided that the following conditions are
13  ** met:
14  **   * Redistributions of source code must retain the above copyright
15  **     notice, this list of conditions and the following disclaimer.
16  **   * Redistributions in binary form must reproduce the above copyright
17  **     notice, this list of conditions and the following disclaimer in
18  **     the documentation and/or other materials provided with the
19  **     distribution.
20  **   * Neither the name of The Qt Company Ltd nor the names of its
21  **     contributors may be used to endorse or promote products derived
22  **     from this software without specific prior written permission.
23  **
24  **
25  ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26  ** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27  ** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
28  ** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
29  ** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30  ** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
31  ** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32  ** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33  ** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34  ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35  ** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
36  **
37  ** $QT_END_LICENSE$
38  **
39  ****************************************************************************/
40
41 #include "GraphWidget.h"
42 #include "Edge.h"
43 #include "Node.h"
44
45 #include <QtGui>
46
47 #include <cpPlugins/Interface/Workspace.h>
48
49 #include <math.h>
50
51 GraphWidget::GraphWidget( QWidget* parent )
52   : QGraphicsView( parent ),
53     timerId( 0 ),
54     m_Workspace( NULL )
55 {
56   QGraphicsScene* scene = new QGraphicsScene( this );
57   scene->setItemIndexMethod( QGraphicsScene::NoIndex );
58   // TODO: scene->setSceneRect( -200, -200, 400, 400 );
59   this->setScene( scene );
60   /* TODO
61      this->setCacheMode(CacheBackground);
62      this->setViewportUpdateMode(BoundingRectViewportUpdate);
63      this->setRenderHint(QPainter::Antialiasing);
64      this->setTransformationAnchor(AnchorUnderMouse);
65      this->scale(qreal(0.8), qreal(0.8));
66      this->setMinimumSize(400, 400);
67      this->setWindowTitle( tr("Elastic Nodes") );
68   */
69
70   /*
71     Node *node1 = new Node(this);
72     Node *node2 = new Node(this);
73     Node *node3 = new Node(this);
74     Node *node4 = new Node(this);
75     centerNode = new Node(this);
76     Node *node6 = new Node(this);
77     Node *node7 = new Node(this);
78     Node *node8 = new Node(this);
79     Node *node9 = new Node(this);
80     scene->addItem(node1);
81     scene->addItem(node2);
82     scene->addItem(node3);
83     scene->addItem(node4);
84     scene->addItem(centerNode);
85     scene->addItem(node6);
86     scene->addItem(node7);
87     scene->addItem(node8);
88     scene->addItem(node9);
89     scene->addItem(new Edge(node1, node2));
90     scene->addItem(new Edge(node2, node3));
91     scene->addItem(new Edge(node2, centerNode));
92     scene->addItem(new Edge(node3, node6));
93     scene->addItem(new Edge(node4, node1));
94     scene->addItem(new Edge(node4, centerNode));
95     scene->addItem(new Edge(centerNode, node6));
96     scene->addItem(new Edge(centerNode, node8));
97     scene->addItem(new Edge(node6, node9));
98     scene->addItem(new Edge(node7, node4));
99     scene->addItem(new Edge(node8, node7));
100     scene->addItem(new Edge(node9, node8));
101
102     node1->setPos(-50, -50);
103     node2->setPos(0, -50);
104     node3->setPos(50, -50);
105     node4->setPos(-50, 0);
106     centerNode->setPos(0, 0);
107     node6->setPos(50, 0);
108     node7->setPos(-50, 50);
109     node8->setPos(0, 50);
110     node9->setPos(50, 50);
111   */
112 }
113
114 // -------------------------------------------------------------------------
115 cpPlugins::Interface::Workspace* GraphWidget::
116 workspace( )
117 {
118   return( this->m_Workspace );
119 }
120
121 // -------------------------------------------------------------------------
122 const cpPlugins::Interface::Workspace* GraphWidget::
123 workspace( ) const
124 {
125   return( this->m_Workspace );
126 }
127
128 // -------------------------------------------------------------------------
129 void GraphWidget::
130 setWorkspace( cpPlugins::Interface::Workspace* ws )
131 {
132   if( this->m_Workspace == ws )
133     return;
134   this->m_Workspace = ws;
135   QGraphicsScene* scene = this->scene( );
136
137   // Create graph
138   this->m_Graph = TGraph::New( );
139
140   // Add vertices
141   auto vIt = this->m_Workspace->GetGraph( )->BeginVertices( );
142   auto vIt_end = this->m_Workspace->GetGraph( )->EndVertices( );
143   for( ; vIt != vIt_end; ++vIt )
144   {
145     std::string label = vIt->second->GetName( ) + std::string( "\n" );
146     label += vIt->second->GetClassName( );
147
148     Node* node = new Node( this, label );
149     this->m_Graph->InsertVertex( vIt->first, node );
150     scene->addItem( node );
151
152   } // rof
153
154   // Add edges
155   auto rIt = this->m_Workspace->GetGraph( )->BeginEdgesRows( );
156   auto rIt_end = this->m_Workspace->GetGraph( )->EndEdgesRows( );
157   for( ; rIt != rIt_end; ++rIt )
158   {
159     Node* a = this->m_Graph->GetVertex( rIt->first );
160     if( a == NULL )
161       continue;
162     auto cIt = rIt->second.begin( );
163     for( ; cIt != rIt->second.end( ); ++cIt )
164     {
165       Node* b = this->m_Graph->GetVertex( cIt->first );
166       if( b == NULL )
167         continue;
168       Edge* e = new Edge( a, b );
169       this->m_Graph->AddConnection( rIt->first, cIt->first, e );
170       scene->addItem( e );
171
172     } // rof
173
174   } // rof
175 }
176
177 // -------------------------------------------------------------------------
178 void GraphWidget::
179 draw( )
180 {
181   if( this->m_Workspace == NULL )
182     return;
183 }
184
185 // -------------------------------------------------------------------------
186 void GraphWidget::itemMoved()
187 {
188   if (!timerId)
189     timerId = startTimer(1000 / 25);
190 }
191
192 void GraphWidget::keyPressEvent(QKeyEvent *event)
193 {
194   switch (event->key()) {
195   case Qt::Key_Up:
196     centerNode->moveBy(0, -20);
197     break;
198   case Qt::Key_Down:
199     centerNode->moveBy(0, 20);
200     break;
201   case Qt::Key_Left:
202     centerNode->moveBy(-20, 0);
203     break;
204   case Qt::Key_Right:
205     centerNode->moveBy(20, 0);
206     break;
207   case Qt::Key_Plus:
208     zoomIn();
209     break;
210   case Qt::Key_Minus:
211     zoomOut();
212     break;
213   case Qt::Key_Space:
214   case Qt::Key_Enter:
215     shuffle();
216     break;
217   default:
218     QGraphicsView::keyPressEvent(event);
219   }
220 }
221
222 void GraphWidget::timerEvent(QTimerEvent *event)
223 {
224   Q_UNUSED(event);
225
226   QList<Node *> nodes;
227   foreach (QGraphicsItem *item, scene()->items()) {
228     if (Node *node = qgraphicsitem_cast<Node *>(item))
229       nodes << node;
230   }
231
232   foreach (Node *node, nodes)
233     node->calculateForces();
234
235   bool itemsMoved = false;
236   foreach (Node *node, nodes) {
237     if (node->advance())
238       itemsMoved = true;
239   }
240
241   if (!itemsMoved) {
242     killTimer(timerId);
243     timerId = 0;
244   }
245 }
246
247 void GraphWidget::wheelEvent(QWheelEvent *event)
248 {
249   scaleView(pow((double)2, -event->delta() / 240.0));
250 }
251
252 void GraphWidget::drawBackground(QPainter *painter, const QRectF &rect)
253 {
254   //Q_UNUSED(rect);
255
256   // Shadow
257   QRectF sceneRect = rect;//this->sceneRect();
258   QRectF rightShadow(sceneRect.right(), sceneRect.top() + 5, 5, sceneRect.height());
259   QRectF bottomShadow(sceneRect.left() + 5, sceneRect.bottom(), sceneRect.width(), 5);
260   if (rightShadow.intersects(rect) || rightShadow.contains(rect))
261     painter->fillRect(rightShadow, Qt::darkGray);
262   if (bottomShadow.intersects(rect) || bottomShadow.contains(rect))
263     painter->fillRect(bottomShadow, Qt::darkGray);
264
265   // Fill
266   QLinearGradient gradient(sceneRect.topLeft(), sceneRect.bottomRight());
267   gradient.setColorAt(0, Qt::white);
268   gradient.setColorAt(1, Qt::lightGray);
269   painter->fillRect(rect.intersect(sceneRect), gradient);
270   painter->setBrush(Qt::NoBrush);
271   painter->drawRect(sceneRect);
272
273 #if !defined(Q_OS_SYMBIAN) && !defined(Q_WS_MAEMO_5)
274   // Text
275   QRectF textRect(sceneRect.left() + 4, sceneRect.top() + 4,
276                   sceneRect.width() - 4, sceneRect.height() - 4);
277   QString message(tr("Click and drag the nodes around, and zoom with the mouse "
278                      "wheel or the '+' and '-' keys"));
279
280   QFont font = painter->font();
281   font.setBold(true);
282   font.setPointSize(14);
283   painter->setFont(font);
284   painter->setPen(Qt::lightGray);
285   painter->drawText(textRect.translated(2, 2), message);
286   painter->setPen(Qt::black);
287   painter->drawText(textRect, message);
288 #endif
289 }
290
291 void GraphWidget::scaleView(qreal scaleFactor)
292 {
293   qreal factor = transform().scale(scaleFactor, scaleFactor).mapRect(QRectF(0, 0, 1, 1)).width();
294   if (factor < 0.07 || factor > 100)
295     return;
296
297   scale(scaleFactor, scaleFactor);
298 }
299
300 void GraphWidget::shuffle()
301 {
302   foreach (QGraphicsItem *item, scene()->items()) {
303     if (qgraphicsitem_cast<Node *>(item))
304       item->setPos(-150 + qrand() % 300, -150 + qrand() % 300);
305   }
306 }
307
308 void GraphWidget::zoomIn()
309 {
310   scaleView(qreal(1.2));
311 }
312
313 void GraphWidget::zoomOut()
314 {
315   scaleView(1 / qreal(1.2));
316 }