Commit ba9f3613 authored by Sebastian Eichelbaum's avatar Sebastian Eichelbaum

[CHANGE] - network manager now handles crashed modules too

parent c440c2b8
......@@ -61,6 +61,7 @@
#include <osg/StateAttribute>
#include "core/kernel/WKernel.h"
#include "core/common/exceptions/WFileNotFound.h"
#include "core/common/WColor.h"
#include "core/common/WPathHelper.h"
#include "core/common/WPropertyHelper.h"
......@@ -330,6 +331,11 @@ void WMTemplate::properties()
// each added property does NOT contain any constraints. If a property gets an information property AFTER its creation, like m_aStringOutput,
// then it keeps its constraints!
// We now add another trigger. Pressing this button will cause an exception to be thrown. This demonstrates how the GUI and OpenWalnut
// handles modules which throw an exception without catching it.
m_exceptionTrigger = m_properties->addProperty( "Press to crash Module", "Pressing this button lets the module intentionally crash.",
WPVBaseTypes::PV_TRIGGER_READY, m_propCondition );
WModule::properties();
}
......@@ -647,6 +653,18 @@ void WMTemplate::moduleMain()
infoLog() << "The user likes " << s.at( i )->getName();
}
}
// Trigger an exception? We do this whenever the user pressed the exception-button
if( m_exceptionTrigger->get( true ) == WPVBaseTypes::PV_TRIGGER_TRIGGERED )
{
// Throw an exception and do not catch it. Please note that OpenWalnut provides several exceptions which usually cover the most
// needs. If not, derive your own exceptions from WException. Using WExceptions has one nice advantage: it provides a backtrace on
// systems which support this.
throw WFileNotFound( "This is a demonstration of an exception being thrown from within a module." );
// OpenWalnut then automatically catches it and transports it to the kernel and the registered callbacks. This usually is the GUI
// which shows a dialog or something similar. Additionally, the m_isCrashed flag is set to true. Once a module is crahsed, it cannot
// be "restored".
}
}
// At this point, the container managing this module signaled to shutdown. The main loop has ended and you should clean up:
......
......@@ -272,6 +272,11 @@ private:
*/
WPropTrigger m_hideButton;
/**
* This causes an exception to be thrown on press to demonstrate how the GUI handles crashing modules.
*/
WPropTrigger m_exceptionTrigger;
/**
* The callback triggering the hide flag of m_aColor for demonstration.
*/
......
......@@ -87,6 +87,7 @@ WQt4Gui::~WQt4Gui()
void WQt4Gui::moduleError( boost::shared_ptr< WModule > module, const WException& exception )
{
QCoreApplication::postEvent( m_mainWindow, new WModuleCrashEvent( module, exception.what() ) );
QCoreApplication::postEvent( m_mainWindow->getNetworkEditor(), new WModuleCrashEvent( module, exception.what() ) );
}
WMainWindow* WQt4Gui::getMainWindow()
......
......@@ -828,7 +828,7 @@ void WQtControlPanel::setActiveModule( WModule::SPtr module, bool forceUpdate )
m_ignoreSelectionChange = true;
// is module NULL? remove everything
if( !module || module->isCrashed() )
if( !module )
{
deactivateModuleSelection();
m_ignoreSelectionChange = false;
......@@ -863,8 +863,11 @@ void WQtControlPanel::setActiveModule( WModule::SPtr module, bool forceUpdate )
// remove property tabs
clearAndDeleteTabs();
// set new property tabs
buildPropTab( module->getProperties(), module->getInformationProperties() );
// set new property tabs if module is not crashed
if( !module->isCrashed() )
{
buildPropTab( module->getProperties(), module->getInformationProperties() );
}
// update compatibles toolbar
createCompatibleButtons( module );
......@@ -1133,6 +1136,12 @@ void WQtControlPanel::deleteModule()
if( ( m_moduleTreeWidget->selectedItems().at( 0 )->type() == MODULE ) ||
( m_moduleTreeWidget->selectedItems().at( 0 )->type() == DATASET ) )
{
// deleting crashed modules is not really save as we do not know the internal state of it
if( static_cast< WQtTreeItem* >( m_moduleTreeWidget->selectedItems().at( 0 ) )->getModule()->isCrashed() )
{
return;
}
// remove from the container. It will create a new event in the GUI after it has been removed which is then handled by the tree item.
// This method deep removes the module ( it also removes depending modules )
WKernel::getRunningKernel()->getRootContainer()->remove(
......@@ -1146,10 +1155,18 @@ void WQtControlPanel::deleteModule()
else if( m_mainWindow->getNetworkEditor()->hasFocus() )
{
if( m_mainWindow->getNetworkEditor()->selectedItems().count() > 0 )
{
// deleting crashed modules is not really save as we do not know the internal state of it
if( static_cast< WQtNetworkItem* >( m_mainWindow->getNetworkEditor()->selectedItems().at( 0 ) )->getModule()->isCrashed() )
{
return;
}
// This method deep removes the module ( it also removes depending modules )
WKernel::getRunningKernel()->getRootContainer()->remove(
static_cast< WQtNetworkItem* >( m_mainWindow->getNetworkEditor()->selectedItems().at( 0 ) )->getModule()
);
}
}
}
......
......@@ -59,6 +59,21 @@ namespace WQtNetworkColors
* Color used for input connectors
*/
const QColor InputConnector = QColor( 255, 255, 255 );
/**
* Color for an active module's activator
*/
const QColor ActivatorActive = QColor( 255, 255, 255 );
/**
* Color for an inactive module's activator
*/
const QColor ActivatorInactive = QColor( 0, 0, 0 );
/**
* Color for crashed modules
*/
const QColor ModuleCrashed = QColor( 215, 37, 46 );
}
#endif // WQTNETWORKCOLORS_H
......
......@@ -48,6 +48,7 @@
#include "../events/WModuleDisconnectEvent.h"
#include "../events/WModuleReadyEvent.h"
#include "../events/WModuleRemovedEvent.h"
#include "../events/WModuleCrashEvent.h"
#include "WQtNetworkEditor.h"
#include "WQtNetworkEditor.moc"
......@@ -124,56 +125,11 @@ void WQtNetworkEditor::selectItem()
m_mainWindow->getControlPanel()->deactivateModuleSelection();
}
void WQtNetworkEditor::deleteSelectedItems()
{
QList< WQtNetworkItem *> itemList;
QList< WQtNetworkArrow *> arrowList;
foreach( QGraphicsItem *item, m_scene->selectedItems() )
{
if( item->type() == WQtNetworkItem::Type )
{
WQtNetworkItem *netItem = qgraphicsitem_cast<WQtNetworkItem *>( item );
itemList.append( netItem );
}
else if( item->type() == WQtNetworkArrow::Type )
{
WQtNetworkArrow *netArrow = qgraphicsitem_cast<WQtNetworkArrow *>( item );
arrowList.append( netArrow );
}
}
foreach( WQtNetworkArrow *ar, arrowList )
{
if( ar != 0 )
{
boost::shared_ptr< WDisconnectCombiner > disconnectCombiner =
boost::shared_ptr< WDisconnectCombiner >( new WDisconnectCombiner(
ar->getStartPort()->getConnector()->getModule(),
ar->getStartPort()->getConnector()->getName(),
ar->getEndPort()->getConnector()->getModule(),
ar->getEndPort()->getConnector()->getName() ) );
disconnectCombiner->run();
disconnectCombiner->wait();
}
}
foreach( WQtNetworkItem *it, itemList )
{
if( it != 0 )
{
WKernel::getRunningKernel()->getRootContainer()->remove( it->getModule() );
m_scene->removeItem( it );
}
}
itemList.clear();
arrowList.clear();
}
void WQtNetworkEditor::updateCylce()
{
for( QList< WQtNetworkItem* >::const_iterator i = m_items.begin(); i != m_items.end(); ++i )
{
( *i )->update();
( *i )->updater();
}
}
......@@ -469,6 +425,28 @@ bool WQtNetworkEditor::event( QEvent* event )
return true;
}
if( event->type() == WQT_CRASH_EVENT )
{
// change module state
WModuleCrashEvent* e = dynamic_cast< WModuleCrashEvent* >( event );
if( !e )
{
// this should never happen, since the type is set to WQT_MODULE_REMOVE_EVENT.
WLogger::getLogger()->addLogMessage( "Event is not an WModuleCrashEvent although"
"its type claims it. Ignoring event.",
"NetworkEditor", LL_WARNING );
return true;
}
WLogger::getLogger()->addLogMessage( "Marking \"" + e->getModule()->getName() + "\" as crashed.",
"NetworkEditor", LL_DEBUG );
WQtNetworkItem *item = findItemByModule( e->getModule() );
item->setCrashed();
return true;
}
return QDockWidget::event( event );
}
......
......@@ -78,11 +78,6 @@ public:
*/
void connectSlots();
/**
* Deletes all items in the scene who are selected.
**/
void deleteSelectedItems();
/**
* Query a list of selected items.
*
......
......@@ -41,7 +41,9 @@
#include "WQtNetworkEditorGlobals.h"
WQtNetworkItem::WQtNetworkItem( WQtNetworkEditor *editor, boost::shared_ptr< WModule > module )
: QGraphicsRectItem()
: QGraphicsRectItem(),
m_isHovered( false ),
m_isSelected( false )
{
m_networkEditor = editor;
m_module = module;
......@@ -122,8 +124,6 @@ WQtNetworkItem::WQtNetworkItem( WQtNetworkEditor *editor, boost::shared_ptr< WMo
fitLook();
m_layoutNode = NULL;
changeState( Disabled );
}
WQtNetworkItem::~WQtNetworkItem()
......@@ -146,48 +146,77 @@ int WQtNetworkItem::type() const
return Type;
}
void WQtNetworkItem::update()
void WQtNetworkItem::updater()
{
// check progress.
// TODO(ebaum): implement progress updates, crash handling and similar.
}
void WQtNetworkItem::hoverEnterEvent( QGraphicsSceneHoverEvent *event )
{
Q_UNUSED( event );
if( !isSelected() )
{
changeState( Hovered );
}
m_isHovered = true;
update();
}
void WQtNetworkItem::hoverLeaveEvent( QGraphicsSceneHoverEvent *event )
{
Q_UNUSED( event );
if( !isSelected() )
{
changeState( Idle );
}
m_isHovered = false;
update();
}
void WQtNetworkItem::paint( QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* w )
{
if( isSelected() )
// This is the default appearance
QPen newPen = QPen( m_itemColor, 1, Qt::SolidLine, Qt::SquareCap, Qt::RoundJoin );
QColor fillColor = m_itemColor;
// change appearance due to state changes
switch( m_currentState )
{
changeState( Selected );
case Disabled:
fillColor = m_itemColor.darker( 300 );
break;
case Crashed:
fillColor = WQtNetworkColors::ModuleCrashed;
break;
case Idle:
default:
// default behaviour
break;
}
// if hovered:
if( m_isHovered )
{
fillColor = fillColor.lighter();
}
// if selected:
if( m_isSelected )
{
newPen = QPen( Qt::black, 2, Qt::DotLine, Qt::SquareCap, Qt::RoundJoin );
}
// only set brush and pen if they have changed
QBrush newBrush = QBrush( fillColor );
if( newBrush != brush() )
{
setBrush( newBrush );
}
if( newPen != pen() )
{
setPen( newPen );
}
QStyleOptionGraphicsItem *o = const_cast<QStyleOptionGraphicsItem*>( option );
o->state &= ~QStyle::State_Selected;
QGraphicsRectItem::paint( painter, o, w );
painter->setBrush( QBrush( Qt::white ) );
painter->setPen( QPen( QBrush( Qt::white ), 0.01 ) );
painter->setOpacity( 0.30 );
QRectF rect( 0, 0, m_width, m_height/2.0 );
painter->drawRect( rect );
// strike through crashed modules
if( m_currentState == Crashed )
{
painter->setPen( QPen( Qt::black, 1, Qt::SolidLine, Qt::SquareCap, Qt::RoundJoin ) );
painter->drawLine( QPoint( 0.0, 0.0 ), QPoint( m_width, m_height ) );
painter->drawLine( QPoint( 0.0, m_height ), QPoint( m_width, 0.0 ) );
}
}
void WQtNetworkItem::mouseMoveEvent( QGraphicsSceneMouseEvent *mouseEvent )
......@@ -216,7 +245,8 @@ QVariant WQtNetworkItem::itemChange( GraphicsItemChange change, const QVariant &
switch( change )
{
case ItemSelectedHasChanged:
changeState( Idle );
m_isSelected = isSelected();
break;
case ItemPositionHasChanged:
foreach( WQtNetworkPort *port, m_inPorts )
{
......@@ -391,8 +421,6 @@ void WQtNetworkItem::fitLook()
port->alignPosition( m_outPorts.size(), portNumber, m_rect, true );
portNumber++;
}
changeState( Idle );
}
void WQtNetworkItem::setTextItem( QGraphicsTextItem *text )
......@@ -405,41 +433,15 @@ QString WQtNetworkItem::getText()
return QString::fromStdString( m_textFull );
}
void WQtNetworkItem::setCrashed()
{
changeState( Crashed );
}
void WQtNetworkItem::changeState( State state )
{
m_currentState = state;
// This is the default appearance
QPen pen = QPen( m_itemColor, 1, Qt::SolidLine, Qt::SquareCap, Qt::RoundJoin );
QLinearGradient gradient;
gradient.setStart( 0, 0 );
gradient.setFinalStop( 0, m_height );
gradient.setColorAt( 0.0, m_itemColor );
gradient.setColorAt( 1.0, m_itemColor );
// change appearance due to state changes
switch( state )
{
case Disabled:
gradient.setColorAt( 0.0, m_itemColor.darker( 300 ) );
gradient.setColorAt( 1.0, m_itemColor.darker( 300 ) );
break;
case Idle:
// default behaviour
break;
case Hovered:
gradient.setColorAt( 0.0, m_itemColor.lighter() );
gradient.setColorAt( 1.0, m_itemColor.lighter() );
break;
case Selected:
pen = QPen( Qt::black, 2, Qt::DotLine, Qt::SquareCap, Qt::RoundJoin );
break;
default:
break;
}
setBrush( gradient );
setPen( pen );
update();
}
boost::shared_ptr< WModule > WQtNetworkItem::getModule()
......@@ -456,7 +458,7 @@ void WQtNetworkItem::activate( bool active )
setAcceptsHoverEvents( true );
setFlag( QGraphicsItem::ItemIsSelectable );
setFlag( QGraphicsItem::ItemIsMovable );
changeState( Idle );
changeState( m_module->isCrashed() ? Crashed : Idle );
}
if( active == false )
{
......
......@@ -154,7 +154,12 @@ public:
/**
* Can be used for polling the module states. It is called by a timer.
*/
virtual void update();
virtual void updater();
/**
* Mark this module as crashed.
*/
void setCrashed();
protected:
/**
......@@ -213,8 +218,7 @@ private:
{
Disabled = 0,
Idle,
Hovered,
Selected
Crashed
};
/**
......@@ -252,5 +256,15 @@ private:
State m_currentState; //!< denotes the state the item currently is in
WQtNetworkItemActivator *m_hidden; //!< indicator showing if module's graphics are activated (allows to activate it)
/**
* If true, the item is hovered.
*/
bool m_isHovered;
/**
* If true, the item is selected
*/
bool m_isSelected;
};
#endif // WQTNETWORKITEM_H
......@@ -38,7 +38,8 @@
#include "WQtNetworkItemActivator.h"
WQtNetworkItemActivator::WQtNetworkItemActivator( boost::shared_ptr< WModule > module )
: m_module( module ), m_activeColor( Qt::white ), m_inactiveColor( Qt::black )
: m_module( module ), m_activeColor( WQtNetworkColors::ActivatorActive ),
m_inactiveColor( WQtNetworkColors::ActivatorInactive )
{
// create the shape using a polygon
QPolygonF poly;
......@@ -93,6 +94,13 @@ void WQtNetworkItemActivator::paint( QPainter* painter, const QStyleOptionGraphi
void WQtNetworkItemActivator::mousePressEvent( QGraphicsSceneMouseEvent *mouseEvent )
{
// if module is crashed -> do not de-activate module
if( m_module->isCrashed() )
{
mouseEvent->accept();
return;
}
QList<QGraphicsItem *> startItem = scene()->items( mouseEvent->scenePos() );
if( !startItem.isEmpty() )
{
......@@ -111,6 +119,12 @@ void WQtNetworkItemActivator::mousePressEvent( QGraphicsSceneMouseEvent *mouseEv
void WQtNetworkItemActivator::handleActiveState()
{
// if module is crashed -> do not de-activate module
if( m_module->isCrashed() )
{
return;
}
if( m_module->getProperties()->getProperty( "active" )->toPropBool()->get() )
{
setBrush( QBrush( m_activeColor ) );
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment