]> Creatis software - cpPlugins.git/blobdiff - lib/cpBaseQtApplication/Pipeline/Block.cxx
yet another refactoring
[cpPlugins.git] / lib / cpBaseQtApplication / Pipeline / Block.cxx
diff --git a/lib/cpBaseQtApplication/Pipeline/Block.cxx b/lib/cpBaseQtApplication/Pipeline/Block.cxx
new file mode 100644 (file)
index 0000000..3d235aa
--- /dev/null
@@ -0,0 +1,418 @@
+#include <cpBaseQtApplication/Pipeline/Block.h>\r
+\r
+#include <QDialog>\r
+#include <QFontMetrics>\r
+#include <QGraphicsScene>\r
+#include <QGraphicsSceneContextMenuEvent>\r
+#include <QGraphicsWidget>\r
+#include <QMenu>\r
+#include <QMessageBox>\r
+#include <QPainter>\r
+#include <QPen>\r
+#include <QStyleOptionGraphicsItem>\r
+\r
+#include <cpBaseQtApplication/Blocker.h>\r
+#include <cpBaseQtApplication/Pipeline/Port.h>\r
+#include <cpBaseQtApplication/Pipeline/Connection.h>\r
+#include <cpPlugins/Pipeline/Widget.h>\r
+#include <cpPlugins/Pipeline/Events.h>\r
+\r
+// -------------------------------------------------------------------------\r
+QColor cpBaseQtApplication::Pipeline::Block::\r
+SelectedAndUpdated = Qt::green;\r
+QColor cpBaseQtApplication::Pipeline::Block::\r
+NotSelectedAndUpdated = Qt::blue;\r
+QColor cpBaseQtApplication::Pipeline::Block::\r
+SelectedAndNotUpdated = Qt::yellow;\r
+QColor cpBaseQtApplication::Pipeline::Block::\r
+NotSelectedAndNotUpdated = Qt::lightGray;\r
+\r
+// -------------------------------------------------------------------------\r
+void cpBaseQtApplication::Pipeline::Block::_TFilterObserver::\r
+Execute( const itk::Object* c, const itk::EventObject& e )\r
+{\r
+  typedef cpPlugins::Pipeline::Events::Modified _TModified;\r
+  const _TModified* mod_evt = dynamic_cast< const _TModified* >( &e );\r
+  if( mod_evt != NULL )\r
+  {\r
+    std::stringstream str;\r
+    str\r
+      << "(" << mod_evt->Time << "/"\r
+      << double( mod_evt->Span ) / double( 1000 ) << "s)";\r
+    this->ObservedBlock->setInfoPort( str.str( ).c_str( ) );\r
+\r
+  } // fi\r
+}\r
+\r
+// -------------------------------------------------------------------------\r
+cpBaseQtApplication::Pipeline::Block::\r
+Block(\r
+  TFilter* filter,\r
+  QGraphicsItem* parent, QGraphicsScene* scene\r
+  )\r
+  : Superclass( parent, scene ),\r
+    m_HorzMargin( 20 ),\r
+    m_VertMargin( 5 ),\r
+    m_NamePort( NULL ),\r
+    m_InfoPort( NULL ),\r
+    m_Filter( filter )\r
+{\r
+  QPainterPath p;\r
+  p.addRoundedRect( -50, -15, 100, 30, 5, 5 );\r
+\r
+  this->setPath( p );\r
+  this->setPen( QPen( Qt::darkGreen ) );\r
+  this->setBrush( Qt::green );\r
+  this->setFlag( QGraphicsItem::ItemIsMovable );\r
+  this->setFlag( QGraphicsItem::ItemIsSelectable );\r
+\r
+  this->m_Width = this->m_HorzMargin;\r
+  this->m_Height = this->m_VertMargin;\r
+\r
+  // Configure names\r
+  this->setNamePort( filter->GetName( ) );\r
+  this->setInfoPort( "(-/-)" );\r
+  this->_setTypeInfo(\r
+    (\r
+      std::string( this->m_Filter->GetClassCategory( ) ) +\r
+      std::string( "::" ) +\r
+      std::string( this->m_Filter->GetClassName( ) )\r
+      ).c_str( )\r
+    );\r
+\r
+  // Add input ports\r
+  auto inputs = this->m_Filter->GetInputsNames( );\r
+  for( auto iIt = inputs.begin( ); iIt != inputs.end( ); ++iIt )\r
+  {\r
+    this->addInputPort(\r
+      iIt->c_str( ),\r
+      this->m_Filter->IsInputMultiple( iIt->c_str( ) )\r
+      );\r
+\r
+  } // rof\r
+\r
+  // Add output ports\r
+  auto outputs = this->m_Filter->GetOutputsNames( );\r
+  for( auto oIt = outputs.begin( ); oIt != outputs.end( ); ++oIt )\r
+    this->addOutputPort( oIt->c_str( ) );\r
+\r
+  // Add obvserver\r
+  this->m_FilterObserver = _TFilterObserver::New( );\r
+  this->m_FilterObserver->ObservedBlock = this;\r
+  this->m_FilterObserverId =\r
+    this->m_Filter->AddObserver(\r
+      cpPlugins::Pipeline::Events::Modified( ), this->m_FilterObserver\r
+      );\r
+}\r
+\r
+// -------------------------------------------------------------------------\r
+cpBaseQtApplication::Pipeline::Block::\r
+~Block( )\r
+{\r
+  this->m_Filter->RemoveObserver( this->m_FilterObserverId );\r
+}\r
+\r
+// -------------------------------------------------------------------------\r
+cpBaseQtApplication::Pipeline::Block::\r
+TFilter* cpBaseQtApplication::Pipeline::Block::\r
+filter( )\r
+{\r
+  return( this->m_Filter );\r
+}\r
+\r
+// -------------------------------------------------------------------------\r
+const cpBaseQtApplication::Pipeline::Block::\r
+TFilter* cpBaseQtApplication::Pipeline::Block::\r
+filter( ) const\r
+{\r
+  return( this->m_Filter );\r
+}\r
+\r
+// -------------------------------------------------------------------------\r
+void cpBaseQtApplication::Pipeline::Block::\r
+setNamePort( const QString& txt )\r
+{\r
+  if( this->m_NamePort == NULL )\r
+    this->m_NamePort = new NamePort( this );\r
+  this->m_NamePort->setName( txt );\r
+  this->_configPort( this->m_NamePort );\r
+}\r
+\r
+// -------------------------------------------------------------------------\r
+void cpBaseQtApplication::Pipeline::Block::\r
+setInfoPort( const QString& txt )\r
+{\r
+  if( this->m_InfoPort == NULL )\r
+    this->m_InfoPort = new InfoPort( this );\r
+  this->m_InfoPort->setName( txt );\r
+  this->_configPort( this->m_InfoPort );\r
+}\r
+\r
+// -------------------------------------------------------------------------\r
+cpBaseQtApplication::Pipeline::InputPort*\r
+cpBaseQtApplication::Pipeline::Block::\r
+addInputPort( const QString& txt, bool multiple )\r
+{\r
+  InputPort* ip = new InputPort( this, multiple );\r
+  ip->setExtendedName( "" );\r
+  ip->setName( txt );\r
+  this->m_InputPorts[ txt.toStdString( ) ] = ip;\r
+  this->_configPort( ip );\r
+  return( ip );\r
+}\r
+\r
+// -------------------------------------------------------------------------\r
+cpBaseQtApplication::Pipeline::OutputPort*\r
+cpBaseQtApplication::Pipeline::Block::\r
+addOutputPort( const QString& txt )\r
+{\r
+  OutputPort* op = new OutputPort( this );\r
+  op->setExtendedName( "" );\r
+  op->setName( txt );\r
+  this->m_OutputPorts[ txt.toStdString( ) ] = op;\r
+  this->_configPort( op );\r
+  return( op );\r
+}\r
+\r
+// -------------------------------------------------------------------------\r
+cpBaseQtApplication::Pipeline::InputPort*\r
+cpBaseQtApplication::Pipeline::Block::\r
+inputPort( const QString& txt )\r
+{\r
+  auto i = this->m_InputPorts.find( txt.toStdString( ) );\r
+  if( i != this->m_InputPorts.end( ) )\r
+    return( i->second );\r
+  else\r
+    return( NULL );\r
+}\r
+\r
+// -------------------------------------------------------------------------\r
+cpBaseQtApplication::Pipeline::OutputPort*\r
+cpBaseQtApplication::Pipeline::Block::\r
+outputPort( const QString& txt )\r
+{\r
+  auto o = this->m_OutputPorts.find( txt.toStdString( ) );\r
+  if( o != this->m_OutputPorts.end( ) )\r
+    return( o->second );\r
+  else\r
+    return( NULL );\r
+}\r
+\r
+// -------------------------------------------------------------------------\r
+QString cpBaseQtApplication::Pipeline::Block::\r
+namePort( ) const\r
+{\r
+  return( this->m_NamePort->name( ) );\r
+}\r
+\r
+// -------------------------------------------------------------------------\r
+const cpBaseQtApplication::Pipeline::InputPort*\r
+cpBaseQtApplication::Pipeline::Block::\r
+inputPort( const QString& txt ) const\r
+{\r
+  auto i = this->m_InputPorts.find( txt.toStdString( ) );\r
+  if( i != this->m_InputPorts.end( ) )\r
+    return( i->second );\r
+  else\r
+    return( NULL );\r
+}\r
+\r
+// -------------------------------------------------------------------------\r
+const cpBaseQtApplication::Pipeline::OutputPort*\r
+cpBaseQtApplication::Pipeline::Block::\r
+outputPort( const QString& txt ) const\r
+{\r
+  auto o = this->m_OutputPorts.find( txt.toStdString( ) );\r
+  if( o != this->m_OutputPorts.end( ) )\r
+    return( o->second );\r
+  else\r
+    return( NULL );\r
+}\r
+\r
+\r
+// -------------------------------------------------------------------------\r
+bool cpBaseQtApplication::Pipeline::Block::\r
+connectOutputPortSlot( QObject* receiver, const char* slot )\r
+{\r
+  bool ok = true;\r
+  for( auto p : this->m_OutputPorts )\r
+    ok &= QObject::connect(\r
+      p.second, SIGNAL( viewData( const std::string&, bool ) ),\r
+      receiver, slot\r
+      );\r
+  return( ok );\r
+}\r
+\r
+// -------------------------------------------------------------------------\r
+void cpBaseQtApplication::Pipeline::Block::\r
+setPos( const QPointF& pos )\r
+{\r
+  this->m_Filter->SetViewCoords( pos.x( ), pos.y( ) );\r
+  this->Superclass::setPos( pos );\r
+}\r
+\r
+// -------------------------------------------------------------------------\r
+void cpBaseQtApplication::Pipeline::Block::\r
+setPos( qreal x, qreal y )\r
+{\r
+  this->m_Filter->SetViewCoords( x, y );\r
+  this->Superclass::setPos( x, y );\r
+}\r
+\r
+// -------------------------------------------------------------------------\r
+void cpBaseQtApplication::Pipeline::Block::\r
+paint(\r
+  QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget\r
+  )\r
+{\r
+  Q_UNUSED( option );\r
+  Q_UNUSED( widget );\r
+\r
+  if( this->isSelected( ) )\r
+  {\r
+    painter->setPen( QPen( Qt::darkYellow ) );\r
+    painter->setBrush( Qt::yellow );\r
+  }\r
+  else\r
+  {\r
+    painter->setPen( QPen( Qt::darkGreen ) );\r
+    painter->setBrush( Qt::green );\r
+\r
+  } // fi\r
+  painter->drawPath( this->path( ) );\r
+}\r
+\r
+// -------------------------------------------------------------------------\r
+QVariant cpBaseQtApplication::Pipeline::Block::\r
+itemChange( GraphicsItemChange change, const QVariant& value )\r
+{\r
+  return( value );\r
+}\r
+\r
+// -------------------------------------------------------------------------\r
+void cpBaseQtApplication::Pipeline::Block::\r
+_setTypeInfo( const QString& txt )\r
+{\r
+  this->setToolTip( txt );\r
+}\r
+\r
+// -------------------------------------------------------------------------\r
+void cpBaseQtApplication::Pipeline::Block::\r
+_configPort( Port* port )\r
+{\r
+  port->setBlock( this );\r
+\r
+  QFontMetrics fm( this->scene( )->font( ) );\r
+  this->m_Width = 0;\r
+  foreach( QGraphicsItem* i, this->children( ) )\r
+  {\r
+    Port* p = dynamic_cast< Port* >( i );\r
+    if( p == NULL )\r
+      continue;\r
+    int w = fm.width( p->name( ) ) + ( 4 * p->radius( ) );\r
+    if( w > this->m_Width - this->m_HorzMargin )\r
+      this->m_Width = w + this->m_HorzMargin;\r
+\r
+  } // rof\r
+  int h = fm.height( );\r
+  this->m_Height = this->m_InputPorts.size( ) + this->m_OutputPorts.size( );\r
+  this->m_Height += 4;\r
+  this->m_Height *= h;\r
+\r
+  QPainterPath pth;\r
+  pth.addRoundedRect(\r
+    -this->m_Width / 2,\r
+    -this->m_Height / 2,\r
+    this->m_Width,\r
+    this->m_Height, 5, 5\r
+    );\r
+  this->setPath( pth );\r
+\r
+  int y = -this->m_Height / 2 + this->m_VertMargin + port->radius( );\r
+  foreach( QGraphicsItem* i, this->children( ) )\r
+  {\r
+    Port* p = dynamic_cast< Port* >( i );\r
+    if( p == NULL )\r
+      continue;\r
+\r
+    if(\r
+      dynamic_cast< NamePort* >( i ) != NULL ||\r
+      dynamic_cast< InfoPort* >( i ) != NULL\r
+      )\r
+    {\r
+      i->setPos( -this->m_Width / 2 + port->radius( ), y );\r
+      y += h >> 1;\r
+    }\r
+    else if( dynamic_cast< InputPort* >( i ) != NULL )\r
+      i->setPos( -this->m_Width / 2 - 2 * port->radius( ), y );\r
+    else if( dynamic_cast< OutputPort* >( i ) != NULL )\r
+      i->setPos( this->m_Width / 2, y );\r
+    y += h;\r
+\r
+  } // rof\r
+}\r
+\r
+// -------------------------------------------------------------------------\r
+void cpBaseQtApplication::Pipeline::Block::\r
+mouseReleaseEvent( QGraphicsSceneMouseEvent* evt )\r
+{\r
+  if( this->m_Filter.IsNotNull( ) )\r
+    this->m_Filter->SetViewCoords(\r
+      this->scenePos( ).x( ),\r
+      this->scenePos( ).y( )\r
+      );\r
+  this->Superclass::mouseReleaseEvent( evt );\r
+}\r
+\r
+// -------------------------------------------------------------------------\r
+void cpBaseQtApplication::Pipeline::Block::\r
+contextMenuEvent( QGraphicsSceneContextMenuEvent* evt )\r
+{\r
+  QMenu menu;\r
+  QAction* configureAction = menu.addAction( "Configure" );\r
+  QAction* updateAction = menu.addAction( "Update" );\r
+  auto widget =\r
+    dynamic_cast< cpPlugins::Pipeline::Widget* >(\r
+      this->m_Filter.GetPointer( )\r
+      );\r
+  QAction* enableAction = NULL;\r
+  if( widget != NULL )\r
+    enableAction =\r
+      menu.addAction( ( widget->GetEnabled( ) )? "Disable": "Enable" );\r
+\r
+  QAction* selectedAction = menu.exec( evt->screenPos( ) );\r
+  if( selectedAction == configureAction )\r
+  {\r
+    auto dlg = this->m_Filter->CreateQDialog( );\r
+    if( dlg != NULL )\r
+      dlg->exec( );\r
+  }\r
+  else if( selectedAction == enableAction )\r
+  {\r
+    if( widget != NULL )\r
+      widget->SetEnabled( !( widget->GetEnabled( ) ) );\r
+  }\r
+  else if( selectedAction == updateAction )\r
+  {\r
+    cpBaseQtApplication::Blocker blocker;\r
+    blocker.block( );\r
+    try\r
+    {\r
+      this->m_Filter->Update( );\r
+      blocker.unblock( );\r
+    }\r
+    catch( std::exception& err )\r
+    {\r
+      blocker.unblock( );\r
+      QMessageBox::critical(\r
+        NULL,\r
+        QMessageBox::tr( "Error updating filter" ),\r
+        QMessageBox::tr( err.what( ) )\r
+        );\r
+\r
+    } // yrt\r
+\r
+  } // fi\r
+}\r
+\r
+// eof - $RCSfile$\r