1
//---------------------------------------------------------------------------
3
// Project: OpenWalnut ( http://www.openwalnut.org )
5
// Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS
6
// For more information see http://www.openwalnut.org/copying
8
// This file is part of OpenWalnut.
10
// OpenWalnut is free software: you can redistribute it and/or modify
11
// it under the terms of the GNU Lesser General Public License as published by
12
// the Free Software Foundation, either version 3 of the License, or
13
// (at your option) any later version.
15
// OpenWalnut is distributed in the hope that it will be useful,
16
// but WITHOUT ANY WARRANTY; without even the implied warranty of
17
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18
// GNU Lesser General Public License for more details.
20
// You should have received a copy of the GNU Lesser General Public License
21
// along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
23
//---------------------------------------------------------------------------
29
#include <boost/shared_ptr.hpp>
31
#include <QtGui/QKeyEvent>
32
#include <QtGui/QGraphicsView>
33
#include <QtGui/QGraphicsItem>
34
#include <QtGui/QGraphicsItemGroup>
36
#include "../WMainWindow.h"
37
#include "WQtNetworkPort.h"
39
#include "core/kernel/combiner/WDisconnectCombiner.h"
40
#include "core/kernel/WKernel.h"
41
#include "core/kernel/WModule.h"
42
#include "core/kernel/WModuleFactory.h"
43
#include "../controlPanel/WQtControlPanel.h"
44
#include "../events/WEventTypes.h"
45
#include "../events/WModuleAssocEvent.h"
46
#include "../events/WModuleConnectEvent.h"
47
#include "../events/WModuleDeleteEvent.h"
48
#include "../events/WModuleDisconnectEvent.h"
49
#include "../events/WModuleReadyEvent.h"
50
#include "../events/WModuleRemovedEvent.h"
52
#include "WQtNetworkEditor.h"
53
#include "WQtNetworkEditor.moc"
55
WQtNetworkEditor::WQtNetworkEditor( WMainWindow* parent )
56
: QDockWidget( "Module Graph", parent ),
59
setObjectName( "Module Graph Dock" );
60
m_mainWindow = parent;
62
QWidget *panel = new QWidget( this );
64
QGraphicsView *view = new QGraphicsView();
65
view->setDragMode( QGraphicsView::RubberBandDrag );
66
view->setRenderHint( QPainter::Antialiasing );
67
view->setMinimumSize( 20, 20 );
69
m_scene = new WQtNetworkScene();
70
// m_scene->setSceneRect( -200.0, -200.0, 400.0, 400.0 );
71
m_scene->setSceneRect( m_scene->itemsBoundingRect() );
73
view->setScene( m_scene );
75
QVBoxLayout *layout = new QVBoxLayout;
76
layout->addWidget( view );
78
panel->setLayout( layout );
80
this->setAllowedAreas( Qt::AllDockWidgetAreas );
81
this->setFeatures( QDockWidget::DockWidgetClosable |QDockWidget::DockWidgetMovable | QDockWidget::DockWidgetFloatable );
83
connect( m_scene, SIGNAL( selectionChanged() ), this, SLOT( selectItem() ) );
85
// this fakeitem is added to the scene to get a better behavior of the forced
86
// based layout. ALL WQtNetworkItems in the scene are "connected" to this
87
// object to avoid that conneceted groups push away each other.
88
QGraphicsRectItem *fake = new QGraphicsRectItem();
89
fake->setRect( 0, 0, 10, 10 );
91
fake->setBrush( Qt::green );
92
fake->setFlag( QGraphicsItem::ItemIsMovable, true );
93
m_scene->addItem( fake );
94
m_scene->setFakeItem( fake );
96
m_layout = new WNetworkLayout();
99
WQtNetworkEditor::~WQtNetworkEditor()
104
void WQtNetworkEditor::selectItem()
106
boost::shared_ptr< WModule > module;
108
if( m_scene->selectedItems().size() != 0 &&
109
m_scene->selectedItems().at( 0 )->type() == WQtNetworkItem::Type )
111
if( m_scene->selectedItems().at(0)->type() == WQtNetworkItem::Type )
113
module = ( static_cast< WQtNetworkItem* >( m_scene->selectedItems().at( 0 ) ) )->getModule();
116
// crashed modules should not provide any props
117
if( module->isCrashed()() )
122
m_mainWindow->getControlPanel()->setNewActiveModule( module );
126
m_mainWindow->getControlPanel()->setNewActiveModule( module );
130
void WQtNetworkEditor::deleteSelectedItems()
132
QList< WQtNetworkItem *> itemList;
133
QList< WQtNetworkArrow *> arrowList;
134
foreach( QGraphicsItem *item, m_scene->selectedItems() )
136
if( item->type() == WQtNetworkItem::Type )
138
WQtNetworkItem *netItem = qgraphicsitem_cast<WQtNetworkItem *>( item );
139
itemList.append( netItem );
141
else if( item->type() == WQtNetworkArrow::Type )
143
WQtNetworkArrow *netArrow = qgraphicsitem_cast<WQtNetworkArrow *>( item );
144
arrowList.append( netArrow );
148
foreach( WQtNetworkArrow *ar, arrowList )
152
boost::shared_ptr< WDisconnectCombiner > disconnectCombiner =
153
boost::shared_ptr< WDisconnectCombiner >( new WDisconnectCombiner(
154
ar->getStartPort()->getConnector()->getModule(),
155
ar->getStartPort()->getConnector()->getName(),
156
ar->getEndPort()->getConnector()->getModule(),
157
ar->getEndPort()->getConnector()->getName() ) );
158
disconnectCombiner->run();
159
disconnectCombiner->wait();
163
foreach( WQtNetworkItem *it, itemList )
167
WKernel::getRunningKernel()->getRootContainer()->remove( it->getModule() );
168
m_scene->removeItem( it );
175
void WQtNetworkEditor::addModule( boost::shared_ptr< WModule > module )
177
WQtNetworkItem *netItem = new WQtNetworkItem( this, module );
178
m_items.push_back( netItem );
180
// set the object at a random start position
182
netItem->setPos( ( std::rand() + m_time ) % 200, ( std::rand() + m_time ) % 200 ); // NOLINT - no we want std::rand instead of rand_r
184
m_scene->addItem( netItem );
189
bool WQtNetworkEditor::event( QEvent* event )
191
// a module got associated with the root container -> add it to the list
192
if( event->type() == WQT_ASSOC_EVENT )
194
// convert event to assoc event
195
WModuleAssocEvent* e1 = dynamic_cast< WModuleAssocEvent* >( event ); // NOLINT
198
WLogger::getLogger()->addLogMessage( "Inserting \"" + e1->getModule()->getName() + "\".",
199
"NetworkEditor", LL_DEBUG );
200
//addModule( e1->getModule() );
201
WQtNetworkItem *item = new WQtNetworkItem( this, e1->getModule() );
202
m_items.push_back( item );
203
m_layout->addItem( item );
204
m_scene->addItem( item );
207
//TODO(skiunke): disablen des moduls solange nicht rdy!
211
// a module changed its state to "ready" -> activate it in dataset browser
212
if( event->type() == WQT_READY_EVENT )
214
// convert event to ready event
215
WModuleReadyEvent* e = dynamic_cast< WModuleReadyEvent* >( event ); // NOLINT
218
// this should never happen, since the type is set to WQT_READY_EVENT.
219
WLogger::getLogger()->addLogMessage( "Event is not an WModueReadyEvent although its type claims it. Ignoring event.",
220
"NetworkEditor", LL_WARNING );
225
WLogger::getLogger()->addLogMessage( "Activating \"" + e->getModule()->getName() + "\".",
226
"NetworkEditor", LL_DEBUG );
228
// search all the item matching the module
229
WQtNetworkItem *item = findItemByModule( e->getModule() );
232
item->activate( true );
238
// a module tree item was connected to another one
239
if( event->type() == WQT_MODULE_CONNECT_EVENT )
241
WModuleConnectEvent* e = dynamic_cast< WModuleConnectEvent* >( event ); // NOLINT
244
// this should never happen, since the type is set to WQT_MODULE_CONNECT_EVENT.
245
WLogger::getLogger()->addLogMessage( "Event is not an WModuleConnectEvent although its type claims it. Ignoring event.",
246
"NetworkEditor", LL_WARNING );
250
WLogger::getLogger()->addLogMessage( "Connecting \"" + e->getInput()->getModule()->getName() +
251
"\" and \"" + e->getOutput()->getModule()->getName() + "\".", "NetworkEditor", LL_DEBUG );
253
boost::shared_ptr< WModule > mIn;
254
boost::shared_ptr< WModule > mOut;
256
if( e->getInput()->isInputConnector() == true &&
257
e->getOutput()->isOutputConnector() == true )
259
mIn = e->getInput()->getModule();
260
mOut = e->getOutput()->getModule();
262
else if( e->getInput()->isOutputConnector() == true &&
263
e->getOutput()->isInputConnector() == true )
265
mIn = e->getOutput()->getModule();
266
mOut = e->getInput()->getModule();
271
//TODO(skiunke): warning
274
WQtNetworkItem *inItem = findItemByModule( mIn );
275
WQtNetworkItem *outItem = findItemByModule( mOut );
277
WQtNetworkInputPort *ip = NULL;
278
WQtNetworkOutputPort *op = NULL;
280
for( QList< WQtNetworkInputPort* >::const_iterator iter = inItem->getInPorts().begin();
281
iter != inItem->getInPorts().end();
284
WQtNetworkInputPort *inP = dynamic_cast< WQtNetworkInputPort* >( *iter );
285
if( e->getInput() == inP->getConnector() )
291
for( QList< WQtNetworkOutputPort* >::const_iterator iter = outItem->getOutPorts().begin();
292
iter != outItem->getOutPorts().end();
295
WQtNetworkOutputPort *outP = dynamic_cast< WQtNetworkOutputPort* >( *iter );
296
if( e->getOutput() == outP->getConnector() )
305
WQtNetworkArrow *arrow = new WQtNetworkArrow( op, ip );
307
arrow->setZValue( -1000.0 );
308
op->addArrow( arrow );
309
ip->addArrow( arrow );
310
arrow->updatePosition();
312
m_scene->addItem( arrow );
314
m_layout->connectItems( outItem, inItem );
319
// a module tree item was disconnected from another one
320
if( event->type() == WQT_MODULE_DISCONNECT_EVENT )
322
WModuleDisconnectEvent* e = dynamic_cast< WModuleDisconnectEvent* >( event ); // NOLINT
325
// this should never happen, since the type is set to WQT_MODULE_DISCONNECT_EVENT.
326
WLogger::getLogger()->addLogMessage( "Event is not an WModuleDisconnectEvent although its type claims it. Ignoring event.",
327
"NetworkEditor", LL_WARNING );
331
WLogger::getLogger()->addLogMessage( "Disconnecting \"" + e->getInput()->getCanonicalName() +
332
"\" and \"" + e->getOutput()->getCanonicalName() +
333
"\"." , "NetworkEditor", LL_DEBUG );
335
boost::shared_ptr< WModule > mIn;
336
boost::shared_ptr< WModule > mOut;
338
if( e->getInput()->isInputConnector() == true &&
339
e->getOutput()->isOutputConnector() == true )
341
mIn = e->getInput()->getModule();
342
mOut = e->getOutput()->getModule();
344
else if( e->getInput()->isOutputConnector() == true &&
345
e->getOutput()->isInputConnector() == true )
347
mIn = e->getOutput()->getModule();
348
mOut = e->getInput()->getModule();
353
//TODO(skiunke): warning
357
WQtNetworkItem *inItem = findItemByModule( mIn );
358
WQtNetworkItem *outItem = findItemByModule( mOut );
360
WQtNetworkInputPort *ip = NULL;
361
WQtNetworkOutputPort *op = NULL;
363
for( QList< WQtNetworkInputPort* >::const_iterator iter = inItem->getInPorts().begin();
364
iter != inItem->getInPorts().end();
367
WQtNetworkInputPort *inP = dynamic_cast< WQtNetworkInputPort* >( *iter );
368
if( e->getInput() == inP->getConnector() )
373
for( QList< WQtNetworkOutputPort* >::const_iterator iter = outItem->getOutPorts().begin();
374
iter != outItem->getOutPorts().end();
377
WQtNetworkOutputPort *outP = dynamic_cast< WQtNetworkOutputPort* >( *iter );
378
if( e->getOutput() == outP->getConnector() )
384
WQtNetworkArrow *ar = NULL;
386
for( QList< QGraphicsItem * >::const_iterator iter = m_scene->items().begin();
387
iter != m_scene->items().end();
390
ar = dynamic_cast< WQtNetworkArrow* >( *iter );
392
ar->getStartPort() == op &&
393
ar->getEndPort() == ip )
400
m_layout->disconnectNodes( outItem, inItem );
402
op->removeArrow( ar );
403
ip->removeArrow( ar );
404
if( ar->scene() != NULL )
406
m_scene->removeItem( ar );
412
WLogger::getLogger()->addLogMessage( "Arrow not found!.", "NetworkEditor", LL_ERROR );
418
// a module was removed from the container
419
if( event->type() == WQT_MODULE_REMOVE_EVENT )
421
WModuleRemovedEvent* e = dynamic_cast< WModuleRemovedEvent* >( event );
424
// this should never happen, since the type is set to WQT_MODULE_REMOVE_EVENT.
425
WLogger::getLogger()->addLogMessage( "Event is not an WModuleRemovedEvent although its type claims it. Ignoring event.",
426
"NetworkEditor", LL_WARNING );
430
WLogger::getLogger()->addLogMessage( "Removing \"" + e->getModule()->getName() + "\".",
431
"NetworkEditor", LL_DEBUG );
434
WQtNetworkItem *item = findItemByModule( e->getModule() );
437
item->activate( false );
438
e->getModule()->requestStop();
444
// a module tree item should be deleted
445
if( event->type() == WQT_MODULE_DELETE_EVENT )
447
WModuleDeleteEvent* e = dynamic_cast< WModuleDeleteEvent* >( event );
450
// this should never happen, since the type is set to WQT_MODULE_REMOVE_EVENT.
451
WLogger::getLogger()->addLogMessage( "Event is not an WModuleRemovedEvent although"
452
"its type claims it. Ignoring event.",
453
"NetworkEditor", LL_WARNING );
457
WLogger::getLogger()->addLogMessage( "Deleting \"" + e->getTreeItem()->getModule()->getName() + "\".",
458
"NetworkEditor", LL_DEBUG );
460
WQtNetworkItem *item = findItemByModule( e->getTreeItem()->getModule() );
464
m_layout->removeItem( item );
466
if( item->scene() != NULL )
468
m_scene->removeItem( item );
470
m_items.removeAll( item );
477
return QDockWidget::event( event );
480
WQtNetworkItem* WQtNetworkEditor::findItemByModule( boost::shared_ptr< WModule > module )
482
for( QList< WQtNetworkItem* >::const_iterator iter = m_items.begin(); iter != m_items.end(); ++iter )
484
WQtNetworkItem *itemModule = dynamic_cast< WQtNetworkItem* >( *iter );
485
if( itemModule && itemModule->getModule() == module )
493
void WQtNetworkEditor::itemMoved()
496
timerId = startTimer( 1000 / 25 );
499
void WQtNetworkEditor::timerEvent( QTimerEvent* /*event*/ )
503
//QList< WQtNetworkItem *> items;
504
//foreach( QGraphicsItem *item, m_scene->items() )
506
// if( WQtNetworkItem *netItem = dynamic_cast< WQtNetworkItem *>( item ) )
510
//foreach( WQtNetworkItem *netItem, items )
511
// netItem->calculateForces();
513
//bool itemsMoved = false;
514
//foreach( WQtNetworkItem *netItem, items )
516
// if( netItem->advance() )
517
// itemsMoved = true;
522
// killTimer( timerId );