Commit 73230200 authored by Alexander Wiebel's avatar Alexander Wiebel
Browse files

[MERGE]

parents 5dd0b8db 634076cd
......@@ -212,22 +212,28 @@ WCombinerTypes::WCompatiblesList WModuleFactory::getCompatiblePrototypes( boost:
// for this a read lock is sufficient, gets unlocked if it looses scope
PrototypeSharedContainerType::ReadTicket l = m_prototypes.getReadTicket();
// First, add all modules with no input connector.
for( PrototypeContainerConstIteratorType listIter = l->get().begin(); listIter != l->get().end();
++listIter )
// has the module an output? If not, return.
bool addModulesWithoutInput = !module;
if( addModulesWithoutInput )
{
// get connectors of this prototype
WModule::InputConnectorList pcons = ( *listIter )->getInputConnectors();
if( pcons.size() == 0 )
// First, add all modules with no input connector.
for( PrototypeContainerConstIteratorType listIter = l->get().begin(); listIter != l->get().end();
++listIter )
{
// the modules which match every time need their own groups
WCombinerTypes::WOneToOneCombiners lComp;
// get connectors of this prototype
WModule::InputConnectorList pcons = ( *listIter )->getInputConnectors();
if( pcons.size() == 0 )
{
// the modules which match every time need their own groups
WCombinerTypes::WOneToOneCombiners 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 WApplyCombiner( module, "", *listIter, "" ) ) );
// 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 WApplyCombiner( module, "", *listIter, "" ) ) );
// add this list
compatibles.push_back( WCombinerTypes::WCompatiblesGroup( ( *listIter ), lComp ) );
// add this list
compatibles.push_back( WCombinerTypes::WCompatiblesGroup( ( *listIter ), lComp ) );
}
}
}
......@@ -256,3 +262,34 @@ WCombinerTypes::WCompatiblesList WModuleFactory::getCompatiblePrototypes( boost:
return compatibles;
}
WCombinerTypes::WCompatiblesList WModuleFactory::getAllPrototypes()
{
WCombinerTypes::WCompatiblesList compatibles;
// for this a read lock is sufficient, gets unlocked if it looses scope
PrototypeSharedContainerType::ReadTicket l = m_prototypes.getReadTicket();
// Add all modules.
for( PrototypeContainerConstIteratorType listIter = l->get().begin(); listIter != l->get().end();
++listIter )
{
// the modules which match every time need their own groups
WCombinerTypes::WOneToOneCombiners 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 WApplyCombiner( *listIter ) ) );
// add this list
compatibles.push_back( WCombinerTypes::WCompatiblesGroup( ( *listIter ), lComp ) );
}
// unlock. No locking needed for further steps.
l.reset();
// sort the compatibles
std::sort( compatibles.begin(), compatibles.end(), WCombinerTypes::compatiblesSort );
return compatibles;
}
......@@ -155,7 +155,8 @@ public:
* \param module the module to find the compatibles for.
*
* \note as the default parameter denotes, providing a NULL pointer (or calling the method without a parameter) returns the list of modules
* which are compatible to every other module. In other words, it returns all modules without input connectors.
* which are compatible to every other module. In other words, it returns all modules without input connectors. If the specified module is
* not NULL, the modules without input are not listed.
*
* \return set of compatible combiners.
*/
......@@ -163,6 +164,13 @@ public:
boost::shared_ptr< WModule > module = boost::shared_ptr< WModule >()
);
/**
* Creates a list of \ref WApplyCombiner for all modules known by the factory.
*
* \return list of apply combiner.
*/
WCombinerTypes::WCompatiblesList getAllPrototypes();
/**
* This method uses a newly created instance of WModule and initializes it properly. After using this method, the module is
* properly initialized and ready to be used.
......
......@@ -42,6 +42,16 @@ class WProjectFile: public WThreadedRunner,
public boost::enable_shared_from_this< WProjectFile >
{
public:
/**
* Abbreviation for a shared pointer.
*/
typedef boost::shared_ptr< WProjectFile > SPtr;
/**
* Abbreviation for const shared pointer.
*/
typedef boost::shared_ptr< const WProjectFile > ConstSPtr;
/**
* Default constructor. It does NOT parse the file. Parsing is done by apply().
*
......
......@@ -29,18 +29,23 @@
#include "WApplyCombiner.h"
WApplyCombiner::WApplyCombiner( boost::shared_ptr< WModuleContainer > target,
boost::shared_ptr< WModule > srcModule, std::string srcConnector,
boost::shared_ptr< WModule > targetModule, std::string targetConnector ):
WModule::SPtr srcModule, std::string srcConnector,
WModule::SPtr targetModule, std::string targetConnector ):
WModuleOneToOneCombiner( target, srcModule, srcConnector, targetModule, targetConnector )
{
}
WApplyCombiner::WApplyCombiner( boost::shared_ptr< WModule > srcModule, std::string srcConnector,
boost::shared_ptr< WModule > targetModule, std::string targetConnector ):
WApplyCombiner::WApplyCombiner( WModule::SPtr srcModule, std::string srcConnector,
WModule::SPtr targetModule, std::string targetConnector ):
WModuleOneToOneCombiner( srcModule, srcConnector, targetModule, targetConnector )
{
}
WApplyCombiner::WApplyCombiner( WModule::SPtr module ):
WModuleOneToOneCombiner( WModule::SPtr(), "", module, "" )
{
}
WApplyCombiner::~WApplyCombiner()
{
// cleanup
......
......@@ -59,8 +59,8 @@ public:
* \param targetConnector the input connector of the prototype to connect with srcConnector.
*/
WApplyCombiner( boost::shared_ptr< WModuleContainer > target,
boost::shared_ptr< WModule > srcModule, std::string srcConnector,
boost::shared_ptr< WModule > targetModule, std::string targetConnector );
WModule::SPtr srcModule, std::string srcConnector,
WModule::SPtr targetModule, std::string targetConnector );
/**
* Creates a combiner which sets up the specified modules and prototype combination. This constructor automatically uses the kernel's root
......@@ -73,8 +73,18 @@ public:
* \param targetModule the module/prototype to use for connecting the module with
* \param targetConnector the input connector of the prototype to connect with srcConnector.
*/
WApplyCombiner( boost::shared_ptr< WModule > srcModule, std::string srcConnector,
boost::shared_ptr< WModule > targetModule, std::string targetConnector );
WApplyCombiner( WModule::SPtr srcModule, std::string srcConnector,
WModule::SPtr targetModule, std::string targetConnector );
/**
* Creates a combiner which only adds the given module. 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. It is possible to specify prototypes here. The will get created upon apply.
*
* \param module the module to add
*/
explicit WApplyCombiner( WModule::SPtr module );
/**
* Destructor.
......@@ -88,7 +98,8 @@ public:
virtual void apply();
/**
* This method creates a list of possible combiners for connections between the specified modules. Both modules can be prototypes.
* This method creates a list of possible combiners for connections between the specified modules. Both modules can be prototypes. This
* method lists only connections from module1's outputs to module2's inputs.
*
* \param module1 the first module
* \param module2 the second module
......@@ -96,7 +107,7 @@ public:
* \return the list of combiner for one-to-one connections
*/
template < typename T >
static WCombinerTypes::WOneToOneCombiners createCombinerList( boost::shared_ptr< WModule > module1, boost::shared_ptr< WModule > module2 )
static WCombinerTypes::WOneToOneCombiners createCombinerList( WModule::SPtr module1, WModule::SPtr module2 )
{
// this list contains all connections for the current module with the other one
WCombinerTypes::WOneToOneCombiners lComp;
......
......@@ -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.
*/
......
......@@ -29,6 +29,7 @@
#include <boost/thread.hpp>
#include <boost/regex.hpp>
#include <boost/filesystem.hpp>
#include <QtGui/QApplication>
#include <QtGui/QCloseEvent>
......@@ -274,20 +275,16 @@ void WMainWindow::setupGUI()
QAction* roiButton = new QAction( m_iconManager.getIcon( "ROI icon" ), "ROI", m_permanentToolBar );
QAction* resetButton = new QAction( m_iconManager.getIcon( "view" ), "Reset", m_permanentToolBar );
resetButton->setShortcut( QKeySequence( Qt::Key_Escape ) );
QAction* projectLoadButton = new QAction( m_iconManager.getIcon( "loadProject" ), "Load Project", m_permanentToolBar );
QAction* projectSaveButton = new QAction( m_iconManager.getIcon( "saveProject" ), "Save Project", m_permanentToolBar );
projectLoadButton->setShortcut( QKeySequence( Qt::CTRL + Qt::SHIFT + Qt::Key_O ) );
connect( m_loadButton, SIGNAL( triggered( bool ) ), this, SLOT( openLoadDialog() ) );
connect( resetButton, SIGNAL( triggered( bool ) ), m_mainGLWidget.get(), SLOT( reset() ) );
connect( roiButton, SIGNAL( triggered( bool ) ), this, SLOT( newRoi() ) );
connect( projectLoadButton, SIGNAL( triggered( bool ) ), this, SLOT( projectLoad() ) );
connect( projectSaveButton, SIGNAL( triggered( bool ) ), this, SLOT( projectSaveAll() ) );
m_loadButton->setToolTip( "Load a dataset from file" );
resetButton->setToolTip( "Reset main view" );
roiButton->setToolTip( "Create new ROI" );
projectLoadButton->setToolTip( "Load a project from file" );
projectSaveButton->setToolTip( "Save current project to file" );
// we want the upper most tree item to be selected. This helps to make the always compatible modules
......@@ -308,8 +305,6 @@ void WMainWindow::setupGUI()
QMenu* fileMenu = m_menuBar->addMenu( "File" );
fileMenu->addAction( m_loadButton );
fileMenu->addSeparator();
fileMenu->addAction( projectLoadButton );
QMenu* saveMenu = fileMenu->addMenu( m_iconManager.getIcon( "saveProject" ), "Save Project" );
saveMenu->addAction( "Save Project", this, SLOT( projectSaveAll() ), QKeySequence::Save );
saveMenu->addAction( "Save Modules Only", this, SLOT( projectSaveModuleOnly() ) );
......@@ -317,6 +312,7 @@ void WMainWindow::setupGUI()
saveMenu->addAction( "Save ROIs Only", this, SLOT( projectSaveROIOnly() ) );
projectSaveButton->setMenu( saveMenu );
fileMenu->addSeparator();
// TODO(all): If all distributions provide a newer QT version we should use QKeySequence::Quit here
//fileMenu->addAction( m_iconManager.getIcon( "quit" ), "Quit", this, SLOT( close() ), QKeySequence( QKeySequence::Quit ) );
fileMenu->addAction( m_iconManager.getIcon( "quit" ), "Quit", this, SLOT( close() ), QKeySequence( Qt::CTRL + Qt::Key_Q ) );
......@@ -464,8 +460,6 @@ void WMainWindow::setupGUI()
// setup permanent toolbar
m_permanentToolBar->addAction( m_loadButton );
m_permanentToolBar->addSeparator();
m_permanentToolBar->addAction( projectLoadButton );
m_permanentToolBar->addAction( projectSaveButton );
m_permanentToolBar->addSeparator();
m_permanentToolBar->addAction( m_mainGLWidgetScreenCapture->getScreenshotTrigger() );
......@@ -670,41 +664,14 @@ bool WMainWindow::projectSaveModuleOnly()
return projectSave( w );
}
void WMainWindow::projectLoad()
{
QFileDialog fd;
fd.setFileMode( QFileDialog::ExistingFiles );
QStringList filters;
filters << "Simple Project File (*.owproj *.owp)"
<< "Any files (*)";
fd.setNameFilters( filters );
fd.setViewMode( QFileDialog::Detail );
QStringList filenames;
if( fd.exec() )
{
filenames = fd.selectedFiles();
}
QStringList::const_iterator constIterator;
for( constIterator = filenames.constBegin(); constIterator != filenames.constEnd(); ++constIterator )
{
boost::shared_ptr< WProjectFile > proj = boost::shared_ptr< WProjectFile >(
new WProjectFile( ( *constIterator ).toStdString() )
);
// This call is asynchronous. It parses the file and the starts a thread to actually do all the stuff
proj->load();
}
}
void WMainWindow::openLoadDialog()
{
QFileDialog fd;
fd.setFileMode( QFileDialog::ExistingFiles );
QStringList filters;
filters << "Known file types (*.cnt *.edf *.asc *.nii *.nii.gz *.fib)"
filters << "Known file types (*.cnt *.edf *.asc *.nii *.nii.gz *.fib *.owproj *.owp)"
<< "Simple Project File (*.owproj *.owp)"
<< "EEG files (*.cnt *.edf *.asc)"
<< "NIfTI (*.nii *.nii.gz)"
<< "Fibers (*.fib)"
......@@ -717,15 +684,29 @@ void WMainWindow::openLoadDialog()
filenames = fd.selectedFiles();
}
std::vector< std::string > stdFilenames;
std::vector< std::string > loadDataFilenames;
QStringList::const_iterator constIterator;
for( constIterator = filenames.constBegin(); constIterator != filenames.constEnd(); ++constIterator )
{
stdFilenames.push_back( ( *constIterator ).toLocal8Bit().constData() );
boost::filesystem::path fn( ( *constIterator ).toLocal8Bit().constData() );
std::string suffix = getSuffix( fn );
// is this a project file?
if( ( suffix == ".owp" ) || ( suffix == ".owproj" ) )
{
WProjectFile::SPtr proj( new WProjectFile( fn.string() ) );
// This call is asynchronous. It parses the file and the starts a thread to actually do all the stuff
proj->load();
}
else
{
// this is not a project. So we assume it is a data file
loadDataFilenames.push_back( fn.string() );
}
}
m_loaderSignal( stdFilenames );
m_loaderSignal( loadDataFilenames );
}
void WMainWindow::openAboutQtDialog()
......@@ -1153,8 +1134,7 @@ void WMainWindow::dropEvent( QDropEvent *event )
}
else
{
if( suffix == "owp"
|| suffix == "owproj" )
if( suffix == "owp" || suffix == "owproj" )
{
projects.push_back( path.toStdString() );
}
......
......@@ -299,11 +299,6 @@ public slots:
*/
void newRoi();
/**
* Gets called whenever the user presses the project button.
*/
void projectLoad();
/**
* Gets called whenever the user presses the project save button.
*/
......
......@@ -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()
......
......@@ -92,9 +92,11 @@ WQtControlPanel::WQtControlPanel( WMainWindow* parent )
separator->setSeparator( true );
m_moduleTreeWidget->addAction( separator );
m_connectWithPrototypeAction = new QAction( "Connect with new module", m_moduleTreeWidget );
m_addModuleAction = new QAction( "Add Module", m_moduleTreeWidget );
m_moduleTreeWidget->addAction( m_addModuleAction );
m_connectWithPrototypeAction = new QAction( "Add Module and Connect", m_moduleTreeWidget );
m_moduleTreeWidget->addAction( m_connectWithPrototypeAction );
m_connectWithModuleAction = new QAction( "Connect with module", m_moduleTreeWidget );
m_connectWithModuleAction = new QAction( "Connect Existing Module", m_moduleTreeWidget );
m_moduleTreeWidget->addAction( m_connectWithModuleAction );
m_disconnectAction = new QAction( "Disconnect", m_moduleTreeWidget );
m_moduleTreeWidget->addAction( m_disconnectAction );
......@@ -128,6 +130,8 @@ WQtControlPanel::WQtControlPanel( WMainWindow* parent )
if( m_mainWindow->getNetworkEditor() )
{
m_mainWindow->getNetworkEditor()->setContextMenuPolicy( Qt::ActionsContextMenu );
m_mainWindow->getNetworkEditor()->addAction( m_addModuleAction );
m_mainWindow->getNetworkEditor()->addAction( separator );
m_mainWindow->getNetworkEditor()->addAction( m_connectWithPrototypeAction );
m_mainWindow->getNetworkEditor()->addAction( m_connectWithModuleAction );
m_mainWindow->getNetworkEditor()->addAction( m_disconnectAction );
......@@ -824,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;
......@@ -859,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 );
......@@ -968,6 +975,7 @@ void deepDeleteActionList( QList< QAction* >& l ) // NOLINT - we need the no
void WQtControlPanel::createCompatibleButtons( boost::shared_ptr< WModule > module )
{
// we need to clean up the action lists
deepDeleteActionList( m_addModuleActionList );
deepDeleteActionList( m_connectWithPrototypeActionList );
deepDeleteActionList( m_connectWithModuleActionList );
deepDeleteActionList( m_disconnectActionList );
......@@ -979,13 +987,24 @@ void WQtControlPanel::createCompatibleButtons( boost::shared_ptr< WModule > modu
m_connectWithModuleActionList = WQtCombinerActionList( this, m_mainWindow->getIconManager(),
WKernel::getRunningKernel()->getRootContainer()->getPossibleConnections( module ),
0, true );
m_addModuleActionList = WQtCombinerActionList( this, m_mainWindow->getIconManager(),
WModuleFactory::getModuleFactory()->getAllPrototypes(),
0, false );
if( module )
{
m_disconnectActionList = WQtCombinerActionList( this, m_mainWindow->getIconManager(), module->getPossibleDisconnections() );
}
// build the prototype menu
// build the add menu
QMenu* m = new QMenu( m_moduleTreeWidget );
m->addActions( m_addModuleActionList );
m_addModuleAction->setDisabled( !m_addModuleActionList.size() || module ); // disable if no entry inside or a module was selected
delete( m_addModuleAction->menu() ); // ensure that combiners get free'd
m_addModuleAction->setMenu( m );
// build the prototype menu
m = new QMenu( m_moduleTreeWidget );
m->addActions( m_connectWithPrototypeActionList );
m_connectWithPrototypeAction->setDisabled( !m_connectWithPrototypeActionList.size() ); // disable if no entry inside
delete( m_connectWithPrototypeAction->menu() ); // ensure that combiners get free'd
......@@ -1117,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(
......@@ -1130,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()
);
}
}
}
......
......@@ -311,11 +311,24 @@ private:
*/
QAction* m_connectWithPrototypeAction;
/**
* Action which uses a list of all modules allowing them to be added without any connections.
*/
QAction* m_addModuleAction;
/**
* Action which disconnects a connector from the module.
*/
QAction* m_disconnectAction;
/**
* List all actions created for applying a prototype. Is needed for m_addModuleAction.
*
* \note We need to store this action list here as Qt is not able to delete the actions if they get replaced. We need to handle this
* manually.
*/
WQtCombinerActionList m_addModuleActionList;
/**
* List all actions created for applying a prototype. Is needed for m_connectWithPrototypeAction.
*
......
......@@ -59,6 +59,31 @@ 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 );
/**
* Color of the busy indicator.
*/
const QColor BusyIndicator = QColor( 255, 45, 45 );
/**
* Color of the busy indicator background.
*/
const QColor BusyIndicatorBackground = QColor( 255, 255, 255 );
}
#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"
......@@ -71,13 +72,14 @@ WQtNetworkEditor::WQtNetworkEditor( WMainWindow* parent )
this->setFeatures( QDockWidget::DockWidgetClosable |QDockWidget::DockWidgetMovable | QDockWidget::DockWidgetFloatable );
setWidget( m_view );
connect( m_scene, SIGNAL( selectionChanged() ), this, SLOT( selectItem() ) );
connect( m_view, SIGNAL( loadAction() ), m_mainWindow, SLOT( openLoadDialog() ) );
m_layout = new WNetworkLayout();
// as the QGraphicsItems are not derived from QObject, they cannot utilize the event system. We need to provide some possibility to update
// them regularly. We use a timer here.
QTimer* updater = new QTimer( this );
updater->start( 50 );
updater->start( 100 );
connect( updater, SIGNAL( timeout() ), this, SLOT( updateCylce() ) );
}