Commit ed078576 authored by Sebastian Eichelbaum's avatar Sebastian Eichelbaum
Browse files

[FIX] - fixed crash if clicked on a tree header

[CHANGE] - some minor extensions in combiners, factory and container
parent 77918642
......@@ -737,14 +737,18 @@ WQtCombinerToolbar* WQtDatasetBrowser::createCompatibleButtons( boost::shared_pt
m_connectWithPrototypeAction->setMenu( m );
// build the module menu
comps = WKernel::getRunningKernel()->getRootContainer()->getPossibleConnections( module );
WCombinerTypes::WCompatiblesList containerComps = WKernel::getRunningKernel()->getRootContainer()->getPossibleConnections( module );
m = new QMenu( m_moduleTreeWidget );
m->addActions( WQtCombinerActionList( m, m_mainWindow->getIconManager(), comps ) );
m->addActions( WQtCombinerActionList( m, m_mainWindow->getIconManager(), containerComps ) );
delete( m_connectWithModuleAction->menu() ); // ensure that combiners get free'd
m_connectWithModuleAction->setMenu( m );
// build the disconnect menu
// TODO(ebaum): do
m = new QMenu( m_moduleTreeWidget );
m->addAction( new QAction( "Not Yet Implemented.", m_moduleTreeWidget ) );
delete( m_disconnectAction->menu() ); // ensure that combiners get free'd
m_disconnectAction->setMenu( m );
return new WQtCombinerToolbar( m_mainWindow, comps );
}
......
......@@ -36,15 +36,33 @@ WQtApplyModuleAction::WQtApplyModuleAction( QWidget* parent, WIconManager* iconM
// NOTE: all the tooltips and so on for this action are used from the first combiner in the group
// use the name property of the modules
std::string srcName = "";
std::string targetName = m_combiner->getTargetModule()->getProperties()->getProperty( "Name" )->toPropString()->get();
// might be null ( for example if a module should be added that does not require an input)
if ( m_combiner->getSrcModule() )
{
from = m_combiner->getSrcModule()->getName() + ":" + m_combiner->getSrcConnector() + " -> ";
srcName = m_combiner->getSrcModule()->getProperties()->getProperty( "Name" )->toPropString()->get();
// append real module name if it is different from user specified name
if ( srcName != m_combiner->getSrcModule()->getName() )
{
srcName+=" (" + m_combiner->getSrcModule()->getName() + ")";
}
}
// append real module name if it is different from user specified name
if ( targetName != m_combiner->getTargetModule()->getName() )
{
targetName+=" (" + m_combiner->getTargetModule()->getName() + ")";
}
std::string tooltip = from + m_combiner->getTargetModule()->getName() + ":" + m_combiner->getTargetConnector();
from = srcName + ":" + m_combiner->getSrcConnector() + " -> ";
std::string tooltip = from + targetName + ":" + m_combiner->getTargetConnector();
setToolTip( tooltip.c_str() );
setText( advancedText ? tooltip.c_str() : m_combiner->getTargetModule()->getName().c_str() );
setIconText( advancedText ? tooltip.c_str() : m_combiner->getTargetModule()->getName().c_str() );
setText( advancedText ? tooltip.c_str() : targetName.c_str() );
setIconText( advancedText ? tooltip.c_str() : targetName.c_str() );
setIcon( iconManager->getIcon( m_combiner->getTargetModule()->getName().c_str() ) );
// we need to use released signal here, as the pushed signal also gets emitted on newly created buttons which are under the mouse pointer with
......
......@@ -127,13 +127,15 @@ void WModuleConnector::connect( boost::shared_ptr<WModuleConnector> con )
// check whether they are already connected
if ( isConnectedTo( con ) )
{
// is this worth an exception?
WLogger::getLogger()->addLogMessage( con->getCanonicalName() + " and " + getCanonicalName() + " are already connected.",
"ModuleContainer (" + containerName + ")", LL_INFO );
return;
}
boost::unique_lock<boost::shared_mutex> lock;
try
{
// TODO(ebaum): really ensure that only one connection is possible for inputs...
// add to list
lock = boost::unique_lock<boost::shared_mutex>( m_connectionListLock );
m_connected.insert( con );
......
......@@ -41,7 +41,6 @@
#include "WModuleOutputConnector.h"
#include "WModuleTypes.h"
#include "combiner/WApplyCombiner.h"
#include "combiner/WApplyModuleCombiner.h"
#include "exceptions/WModuleAlreadyAssociated.h"
#include "exceptions/WModuleSignalSubscriptionFailed.h"
#include "exceptions/WModuleUninitialized.h"
......@@ -79,6 +78,11 @@ boost::shared_ptr< WModule > WModuleContainer::factory() const
void WModuleContainer::add( boost::shared_ptr< WModule > module, bool run )
{
if ( !module )
{ // just ignore NULL Pointer
return;
}
WLogger::getLogger()->addLogMessage( "Adding module \"" + module->getName() + "\" to container." ,
"ModuleContainer (" + getName() + ")", LL_INFO );
......@@ -93,6 +97,8 @@ void WModuleContainer::add( boost::shared_ptr< WModule > module, bool run )
// already associated with this container?
if ( module->getAssociatedContainer() == shared_from_this() )
{
WLogger::getLogger()->addLogMessage( "Adding module \"" + module->getName() + "\" to container not needed. Its already inside." ,
"ModuleContainer (" + getName() + ")", LL_INFO );
return;
}
......@@ -444,6 +450,12 @@ WCombinerTypes::WCompatiblesList WModuleContainer::getPossibleConnections( boost
{
WCombinerTypes::WCompatiblesList complist;
if ( !module )
{
// be nice in case of a null pointer
return complist;
}
// read lock the container
ModuleSharedContainerType::ReadTicket lock = m_modules.getReadTicket();
......@@ -452,7 +464,7 @@ WCombinerTypes::WCompatiblesList WModuleContainer::getPossibleConnections( boost
// handle each module
for( ModuleConstIterator listIter = lock->get().begin(); listIter != lock->get().end(); ++listIter )
{
WCombinerTypes::WCompatibleCombiners lComp = WApplyCombiner::createCombinerList< WApplyModuleCombiner>( module, ( *listIter ) );
WCombinerTypes::WCompatibleCombiners lComp = WApplyCombiner::createCombinerList< WApplyCombiner>( module, ( *listIter ) );
if ( lComp.size() != 0 )
{
......
......@@ -67,7 +67,7 @@
#include "../modules/writeTracts/WMWriteTracts.h"
#include "../modules/splineSurface/WMSplineSurface.h"
#include "../modules/atlasSurfaces/WMAtlasSurfaces.h"
#include "combiner/WApplyPrototypeCombiner.h"
#include "combiner/WApplyCombiner.h"
#include "exceptions/WPrototypeNotUnique.h"
#include "exceptions/WPrototypeUnknown.h"
#include "WModuleFactory.h"
......@@ -269,7 +269,7 @@ WCombinerTypes::WCompatiblesList WModuleFactory::getCompatiblePrototypes( boost:
std::vector< boost::shared_ptr< WApplyCombiner > > lComp;
// NOTE: it is OK here to use the variable module even if it is NULL as the combiner in this case only adds the specified module
lComp.push_back( boost::shared_ptr< WApplyCombiner >( new WApplyPrototypeCombiner( module, "", *listIter, "" ) ) );
lComp.push_back( boost::shared_ptr< WApplyCombiner >( new WApplyCombiner( module, "", *listIter, "" ) ) );
// add this list
compatibles.push_back( WCombinerTypes::WCompatiblesGroup( ( *listIter ), lComp ) );
......@@ -286,7 +286,7 @@ WCombinerTypes::WCompatiblesList WModuleFactory::getCompatiblePrototypes( boost:
for( PrototypeContainerIteratorType listIter = l->get().begin(); listIter != l->get().end();
++listIter )
{
WCombinerTypes::WCompatibleCombiners lComp = WApplyCombiner::createCombinerList< WApplyPrototypeCombiner >( module, ( *listIter ) );
WCombinerTypes::WCompatibleCombiners lComp = WApplyCombiner::createCombinerList< WApplyCombiner >( module, ( *listIter ) );
// add the group
if ( lComp.size() != 0 )
......
......@@ -22,6 +22,8 @@
//
//---------------------------------------------------------------------------
#include "../WModuleFactory.h"
#include "WApplyCombiner.h"
WApplyCombiner::WApplyCombiner( boost::shared_ptr< WModuleContainer > target,
......@@ -70,3 +72,65 @@ std::string WApplyCombiner::getTargetConnector() const
return m_targetConnector;
}
void WApplyCombiner::apply()
{
// create the modules from the prototypes if needed
boost::shared_ptr< WModule > srcModule = m_srcModule;
boost::shared_ptr< WModule > targetModule = m_targetModule;
// create module instance if src is a prototype
if ( srcModule && WModuleFactory::isPrototype( srcModule ) )
{
srcModule = WModuleFactory::getModuleFactory()->create( m_srcModule );
}
// create module instance if target is a prototype
if ( targetModule && WModuleFactory::isPrototype( targetModule ) )
{
targetModule = WModuleFactory::getModuleFactory()->create( m_targetModule );
}
// add the src and target module to the container
// NOTE: the container does nothing if a NULL pointer has been specified and it also does nothing if the module already is associated with
// the container
m_container->add( srcModule );
m_container->add( targetModule );
// wait for the source module if there is any
if ( srcModule )
{
srcModule->isReadyOrCrashed().wait();
if ( srcModule->isCrashed()() )
{
// NOTE: throwing an exception here should not be needed as the module container already has forwarded the exception
wlog::error( "Prototype Combiner" ) << "The source module \"" << srcModule->getName() << "\" has crashed. Abort.";
return;
}
}
// wait for the source module if there is any
if ( targetModule )
{
targetModule->isReadyOrCrashed().wait();
if ( targetModule->isCrashed()() )
{
// NOTE: throwing an exception here should not be needed as the module container already has forwarded the exception
wlog::error( "Prototype Combiner" ) << "The target module \"" << targetModule->getName() << "\" has crashed. Abort.";
return;
}
}
// if the connector is an empty string -> do not connect, just add
if ( ( m_srcConnector.empty() ) || ( m_targetConnector.empty() ) )
{
return;
}
// and connect them finally:
if ( srcModule && targetModule )
{
targetModule->getInputConnector( m_targetConnector )->connect( srcModule->getOutputConnector( m_srcConnector ) );
}
}
......@@ -49,7 +49,7 @@ public:
/**
* Creates a combiner which sets up the specified modules and prototype combination. Specifying a NULL pointer to the srcModule parameter
* causes the combiner to only add the target module without any connections. This is especially useful for modules which do not provide any
* input which must be connected.
* input which must be connected. It is possible to specify prototypes here. The will get created upon apply.
*
*
* \param target the target container
......@@ -66,7 +66,7 @@ public:
* Creates a combiner which sets up the specified modules and prototype combination. This constructor automatically uses the kernel's root
* container as target container. Specifying a NULL pointer to the srcModule parameter
* causes the combiner to only add the target module without any connections. This is especially useful for modules which do not provide any
* input which must be connected.
* input which must be connected. It is possible to specify prototypes here. The will get created upon apply.
*
* \param srcModule the module whose output should be connected with the prototypes input
* \param srcConnector the output connector of the module
......@@ -85,7 +85,7 @@ public:
* Apply the internal module structure to the target container. Be aware, that this operation might take some time, as modules can be
* connected only if they are "ready", which, at least with WMData modules, might take some time. It applies the loaded project file.
*/
virtual void apply() = 0;
virtual void apply();
/**
* Gets the source module. This module's output connector is connected with the target.
......
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