]> Creatis software - cpPlugins.git/blob - lib/cpBaseQtApplication/Pipeline/Block.cxx
5155c7acf8bb1cc21d2fac8bbf85670661d711d9
[cpPlugins.git] / lib / cpBaseQtApplication / Pipeline / Block.cxx
1 #include <cpBaseQtApplication/Pipeline/Block.h>\r
2 \r
3 #include <QDialog>\r
4 #include <QFontMetrics>\r
5 #include <QGraphicsScene>\r
6 #include <QGraphicsSceneContextMenuEvent>\r
7 #include <QGraphicsWidget>\r
8 #include <QMenu>\r
9 #include <QMessageBox>\r
10 #include <QPainter>\r
11 #include <QPen>\r
12 #include <QStyleOptionGraphicsItem>\r
13 \r
14 #include <cpBaseQtApplication/Blocker.h>\r
15 #include <cpBaseQtApplication/Pipeline/Port.h>\r
16 #include <cpBaseQtApplication/Pipeline/Connection.h>\r
17 #include <cpPlugins/BaseObjects/Widget.h>\r
18 #include <cpPlugins/BaseObjects/Events.h>\r
19 \r
20 // -------------------------------------------------------------------------\r
21 QColor cpBaseQtApplication::Pipeline::Block::\r
22 SelectedAndUpdated = Qt::green;\r
23 QColor cpBaseQtApplication::Pipeline::Block::\r
24 NotSelectedAndUpdated = Qt::blue;\r
25 QColor cpBaseQtApplication::Pipeline::Block::\r
26 SelectedAndNotUpdated = Qt::yellow;\r
27 QColor cpBaseQtApplication::Pipeline::Block::\r
28 NotSelectedAndNotUpdated = Qt::lightGray;\r
29 \r
30 // -------------------------------------------------------------------------\r
31 void cpBaseQtApplication::Pipeline::Block::_TFilterObserver::\r
32 Execute( const itk::Object* c, const itk::EventObject& e )\r
33 {\r
34   typedef cpPlugins::BaseObjects::Events::Modified _TModified;\r
35   const _TModified* mod_evt = dynamic_cast< const _TModified* >( &e );\r
36   if( mod_evt != NULL )\r
37   {\r
38     std::stringstream str;\r
39     str\r
40       << "(" << mod_evt->Time << "/"\r
41       << double( mod_evt->Span ) / double( 1000 ) << "s)";\r
42     this->ObservedBlock->setInfoPort( str.str( ).c_str( ) );\r
43 \r
44   } // fi\r
45 }\r
46 \r
47 // -------------------------------------------------------------------------\r
48 cpBaseQtApplication::Pipeline::Block::\r
49 Block(\r
50   TFilter* filter,\r
51   QGraphicsItem* parent, QGraphicsScene* scene\r
52   )\r
53   : Superclass( parent, scene ),\r
54     m_HorzMargin( 20 ),\r
55     m_VertMargin( 5 ),\r
56     m_NamePort( NULL ),\r
57     m_InfoPort( NULL ),\r
58     m_Filter( filter )\r
59 {\r
60   QPainterPath p;\r
61   p.addRoundedRect( -50, -15, 100, 30, 5, 5 );\r
62 \r
63   this->setPath( p );\r
64   this->setPen( QPen( Qt::darkGreen ) );\r
65   this->setBrush( Qt::green );\r
66   this->setFlag( QGraphicsItem::ItemIsMovable );\r
67   this->setFlag( QGraphicsItem::ItemIsSelectable );\r
68 \r
69   this->m_Width = this->m_HorzMargin;\r
70   this->m_Height = this->m_VertMargin;\r
71 \r
72   // Configure names\r
73   this->setNamePort( filter->GetName( ) );\r
74   this->setInfoPort( "(-/-)" );\r
75   this->_setTypeInfo(\r
76     (\r
77       std::string( this->m_Filter->GetClassCategory( ) ) +\r
78       std::string( "::" ) +\r
79       std::string( this->m_Filter->GetClassName( ) )\r
80       ).c_str( )\r
81     );\r
82 \r
83   // Add input ports\r
84   auto inputs = this->m_Filter->GetInputsNames( );\r
85   for( auto iIt = inputs.begin( ); iIt != inputs.end( ); ++iIt )\r
86   {\r
87     this->addInputPort(\r
88       iIt->c_str( ),\r
89       this->m_Filter->IsInputMultiple( iIt->c_str( ) )\r
90       );\r
91 \r
92   } // rof\r
93 \r
94   // Add output ports\r
95   auto outputs = this->m_Filter->GetOutputsNames( );\r
96   for( auto oIt = outputs.begin( ); oIt != outputs.end( ); ++oIt )\r
97     this->addOutputPort( oIt->c_str( ) );\r
98 \r
99   // Add obvserver\r
100   this->m_FilterObserver = _TFilterObserver::New( );\r
101   this->m_FilterObserver->ObservedBlock = this;\r
102   this->m_FilterObserverId =\r
103     this->m_Filter->AddObserver(\r
104       cpPlugins::BaseObjects::Events::Modified( ), this->m_FilterObserver\r
105       );\r
106 }\r
107 \r
108 // -------------------------------------------------------------------------\r
109 cpBaseQtApplication::Pipeline::Block::\r
110 ~Block( )\r
111 {\r
112   this->m_Filter->RemoveObserver( this->m_FilterObserverId );\r
113 }\r
114 \r
115 // -------------------------------------------------------------------------\r
116 cpBaseQtApplication::Pipeline::Block::\r
117 TFilter* cpBaseQtApplication::Pipeline::Block::\r
118 filter( )\r
119 {\r
120   return( this->m_Filter );\r
121 }\r
122 \r
123 // -------------------------------------------------------------------------\r
124 const cpBaseQtApplication::Pipeline::Block::\r
125 TFilter* cpBaseQtApplication::Pipeline::Block::\r
126 filter( ) const\r
127 {\r
128   return( this->m_Filter );\r
129 }\r
130 \r
131 // -------------------------------------------------------------------------\r
132 void cpBaseQtApplication::Pipeline::Block::\r
133 setNamePort( const QString& txt )\r
134 {\r
135   if( this->m_NamePort == NULL )\r
136     this->m_NamePort = new NamePort( this );\r
137   this->m_NamePort->setName( txt );\r
138   this->_configPort( this->m_NamePort );\r
139 }\r
140 \r
141 // -------------------------------------------------------------------------\r
142 void cpBaseQtApplication::Pipeline::Block::\r
143 setInfoPort( const QString& txt )\r
144 {\r
145   if( this->m_InfoPort == NULL )\r
146     this->m_InfoPort = new InfoPort( this );\r
147   this->m_InfoPort->setName( txt );\r
148   this->_configPort( this->m_InfoPort );\r
149 }\r
150 \r
151 // -------------------------------------------------------------------------\r
152 cpBaseQtApplication::Pipeline::InputPort*\r
153 cpBaseQtApplication::Pipeline::Block::\r
154 addInputPort( const QString& txt, bool multiple )\r
155 {\r
156   InputPort* ip = new InputPort( this, multiple );\r
157   ip->setExtendedName( "" );\r
158   ip->setName( txt );\r
159   this->m_InputPorts[ txt.toStdString( ) ] = ip;\r
160   this->_configPort( ip );\r
161   return( ip );\r
162 }\r
163 \r
164 // -------------------------------------------------------------------------\r
165 cpBaseQtApplication::Pipeline::OutputPort*\r
166 cpBaseQtApplication::Pipeline::Block::\r
167 addOutputPort( const QString& txt )\r
168 {\r
169   OutputPort* op = new OutputPort( this );\r
170   op->setExtendedName( "" );\r
171   op->setName( txt );\r
172   this->m_OutputPorts[ txt.toStdString( ) ] = op;\r
173   this->_configPort( op );\r
174   return( op );\r
175 }\r
176 \r
177 // -------------------------------------------------------------------------\r
178 cpBaseQtApplication::Pipeline::InputPort*\r
179 cpBaseQtApplication::Pipeline::Block::\r
180 inputPort( const QString& txt )\r
181 {\r
182   auto i = this->m_InputPorts.find( txt.toStdString( ) );\r
183   if( i != this->m_InputPorts.end( ) )\r
184     return( i->second );\r
185   else\r
186     return( NULL );\r
187 }\r
188 \r
189 // -------------------------------------------------------------------------\r
190 cpBaseQtApplication::Pipeline::OutputPort*\r
191 cpBaseQtApplication::Pipeline::Block::\r
192 outputPort( const QString& txt )\r
193 {\r
194   auto o = this->m_OutputPorts.find( txt.toStdString( ) );\r
195   if( o != this->m_OutputPorts.end( ) )\r
196     return( o->second );\r
197   else\r
198     return( NULL );\r
199 }\r
200 \r
201 // -------------------------------------------------------------------------\r
202 QString cpBaseQtApplication::Pipeline::Block::\r
203 namePort( ) const\r
204 {\r
205   return( this->m_NamePort->name( ) );\r
206 }\r
207 \r
208 // -------------------------------------------------------------------------\r
209 const cpBaseQtApplication::Pipeline::InputPort*\r
210 cpBaseQtApplication::Pipeline::Block::\r
211 inputPort( const QString& txt ) const\r
212 {\r
213   auto i = this->m_InputPorts.find( txt.toStdString( ) );\r
214   if( i != this->m_InputPorts.end( ) )\r
215     return( i->second );\r
216   else\r
217     return( NULL );\r
218 }\r
219 \r
220 // -------------------------------------------------------------------------\r
221 const cpBaseQtApplication::Pipeline::OutputPort*\r
222 cpBaseQtApplication::Pipeline::Block::\r
223 outputPort( const QString& txt ) const\r
224 {\r
225   auto o = this->m_OutputPorts.find( txt.toStdString( ) );\r
226   if( o != this->m_OutputPorts.end( ) )\r
227     return( o->second );\r
228   else\r
229     return( NULL );\r
230 }\r
231 \r
232 \r
233 // -------------------------------------------------------------------------\r
234 bool cpBaseQtApplication::Pipeline::Block::\r
235 connectOutputPortSlot( QObject* receiver, const char* slot )\r
236 {\r
237   bool ok = true;\r
238   for( auto p : this->m_OutputPorts )\r
239     ok &= QObject::connect(\r
240       p.second, SIGNAL( viewData( const std::string&, bool ) ),\r
241       receiver, slot\r
242       );\r
243   return( ok );\r
244 }\r
245 \r
246 // -------------------------------------------------------------------------\r
247 void cpBaseQtApplication::Pipeline::Block::\r
248 setPos( const QPointF& pos )\r
249 {\r
250   this->m_Filter->SetViewCoords( pos.x( ), pos.y( ) );\r
251   this->Superclass::setPos( pos );\r
252 }\r
253 \r
254 // -------------------------------------------------------------------------\r
255 void cpBaseQtApplication::Pipeline::Block::\r
256 setPos( qreal x, qreal y )\r
257 {\r
258   this->m_Filter->SetViewCoords( x, y );\r
259   this->Superclass::setPos( x, y );\r
260 }\r
261 \r
262 // -------------------------------------------------------------------------\r
263 void cpBaseQtApplication::Pipeline::Block::\r
264 paint(\r
265   QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget\r
266   )\r
267 {\r
268   Q_UNUSED( option );\r
269   Q_UNUSED( widget );\r
270 \r
271   if( this->isSelected( ) )\r
272   {\r
273     painter->setPen( QPen( Qt::darkYellow ) );\r
274     painter->setBrush( Qt::yellow );\r
275   }\r
276   else\r
277   {\r
278     painter->setPen( QPen( Qt::darkGreen ) );\r
279     painter->setBrush( Qt::green );\r
280 \r
281   } // fi\r
282   painter->drawPath( this->path( ) );\r
283 }\r
284 \r
285 // -------------------------------------------------------------------------\r
286 QVariant cpBaseQtApplication::Pipeline::Block::\r
287 itemChange( GraphicsItemChange change, const QVariant& value )\r
288 {\r
289   return( value );\r
290 }\r
291 \r
292 // -------------------------------------------------------------------------\r
293 void cpBaseQtApplication::Pipeline::Block::\r
294 _setTypeInfo( const QString& txt )\r
295 {\r
296   this->setToolTip( txt );\r
297 }\r
298 \r
299 // -------------------------------------------------------------------------\r
300 void cpBaseQtApplication::Pipeline::Block::\r
301 _configPort( Port* port )\r
302 {\r
303   port->setBlock( this );\r
304 \r
305   QFontMetrics fm( this->scene( )->font( ) );\r
306   this->m_Width = 0;\r
307   foreach( QGraphicsItem* i, this->children( ) )\r
308   {\r
309     Port* p = dynamic_cast< Port* >( i );\r
310     if( p == NULL )\r
311       continue;\r
312     int w = fm.width( p->name( ) ) + ( 4 * p->radius( ) );\r
313     if( w > this->m_Width - this->m_HorzMargin )\r
314       this->m_Width = w + this->m_HorzMargin;\r
315 \r
316   } // rof\r
317   int h = fm.height( );\r
318   this->m_Height = this->m_InputPorts.size( ) + this->m_OutputPorts.size( );\r
319   this->m_Height += 4;\r
320   this->m_Height *= h;\r
321 \r
322   QPainterPath pth;\r
323   pth.addRoundedRect(\r
324     -this->m_Width / 2,\r
325     -this->m_Height / 2,\r
326     this->m_Width,\r
327     this->m_Height, 5, 5\r
328     );\r
329   this->setPath( pth );\r
330 \r
331   int y = -this->m_Height / 2 + this->m_VertMargin + port->radius( );\r
332   foreach( QGraphicsItem* i, this->children( ) )\r
333   {\r
334     Port* p = dynamic_cast< Port* >( i );\r
335     if( p == NULL )\r
336       continue;\r
337 \r
338     if(\r
339       dynamic_cast< NamePort* >( i ) != NULL ||\r
340       dynamic_cast< InfoPort* >( i ) != NULL\r
341       )\r
342     {\r
343       i->setPos( -this->m_Width / 2 + port->radius( ), y );\r
344       y += h >> 1;\r
345     }\r
346     else if( dynamic_cast< InputPort* >( i ) != NULL )\r
347       i->setPos( -this->m_Width / 2 - 2 * port->radius( ), y );\r
348     else if( dynamic_cast< OutputPort* >( i ) != NULL )\r
349       i->setPos( this->m_Width / 2, y );\r
350     y += h;\r
351 \r
352   } // rof\r
353 }\r
354 \r
355 // -------------------------------------------------------------------------\r
356 void cpBaseQtApplication::Pipeline::Block::\r
357 mouseReleaseEvent( QGraphicsSceneMouseEvent* evt )\r
358 {\r
359   if( this->m_Filter.IsNotNull( ) )\r
360     this->m_Filter->SetViewCoords(\r
361       this->scenePos( ).x( ),\r
362       this->scenePos( ).y( )\r
363       );\r
364   this->Superclass::mouseReleaseEvent( evt );\r
365 }\r
366 \r
367 // -------------------------------------------------------------------------\r
368 void cpBaseQtApplication::Pipeline::Block::\r
369 contextMenuEvent( QGraphicsSceneContextMenuEvent* evt )\r
370 {\r
371   QMenu menu;\r
372   QAction* configureAction = menu.addAction( "Configure" );\r
373   QAction* updateAction = menu.addAction( "Update" );\r
374   auto widget =\r
375     dynamic_cast< cpPlugins::BaseObjects::Widget* >(\r
376       this->m_Filter.GetPointer( )\r
377       );\r
378   QAction* enableAction = NULL;\r
379   if( widget != NULL )\r
380     enableAction =\r
381       menu.addAction( ( widget->GetEnabled( ) )? "Disable": "Enable" );\r
382 \r
383   QAction* selectedAction = menu.exec( evt->screenPos( ) );\r
384   if( selectedAction == configureAction )\r
385   {\r
386     auto dlg = this->m_Filter->CreateQDialog( );\r
387     if( dlg != NULL )\r
388       dlg->exec( );\r
389   }\r
390   else if( selectedAction == enableAction )\r
391   {\r
392     if( widget != NULL )\r
393       widget->SetEnabled( !( widget->GetEnabled( ) ) );\r
394   }\r
395   else if( selectedAction == updateAction )\r
396   {\r
397     cpBaseQtApplication::Blocker blocker;\r
398     blocker.block( );\r
399     try\r
400     {\r
401       this->m_Filter->Update( );\r
402       blocker.unblock( );\r
403     }\r
404     catch( std::exception& err )\r
405     {\r
406       blocker.unblock( );\r
407       QMessageBox::critical(\r
408         NULL,\r
409         QMessageBox::tr( "Error updating filter" ),\r
410         QMessageBox::tr( err.what( ) )\r
411         );\r
412 \r
413     } // yrt\r
414 \r
415   } // fi\r
416 }\r
417 \r
418 // eof - $RCSfile$\r