WQtControlPanel.cpp 46 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
//---------------------------------------------------------------------------
//
// Project: OpenWalnut ( http://www.openwalnut.org )
//
// Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS
// For more information see http://www.openwalnut.org/copying
//
// This file is part of OpenWalnut.
//
// OpenWalnut is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// OpenWalnut is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
//
//---------------------------------------------------------------------------

25
#include <iostream>
Sebastian Eichelbaum's avatar
[STYLE]  
Sebastian Eichelbaum committed
26
#include <list>
27
#include <map>
Sebastian Eichelbaum's avatar
[MERGE]  
Sebastian Eichelbaum committed
28
#include <set>
29
#include <string>
30
#include <vector>
31

32
#include <QtCore/QList>
33
#include <QtGui/QMenu>
34
#include <QtGui/QScrollArea>
schurade's avatar
schurade committed
35
#include <QtGui/QShortcut>
36
#include <QtGui/QSplitter>
37
#include <QtGui/QMessageBox>
38

39
#include "core/common/WLogger.h"
40
#include "core/common/WPredicateHelper.h"
41
#include "core/dataHandler/WDataSet.h"
42
#include "core/kernel/WDataModule.h"
43 44 45 46 47
#include "core/kernel/WKernel.h"
#include "core/kernel/WModule.h"
#include "core/kernel/WModuleContainer.h"
#include "core/kernel/WModuleFactory.h"
#include "core/kernel/WROIManager.h"
48 49 50 51
#include "../WMainWindow.h"
#include "../WQt4Gui.h"
#include "../WQtCombinerActionList.h"
#include "../WQtModuleConfig.h"
52
#include "../events/WEventTypes.h"
53
#include "../events/WModuleAssocEvent.h"
54
#include "../events/WModuleConnectEvent.h"
55
#include "../events/WModuleConnectorEvent.h"
56
#include "../events/WModuleDeleteEvent.h"
57
#include "../events/WModuleDisconnectEvent.h"
58
#include "../events/WModuleReadyEvent.h"
59
#include "../events/WModuleRemovedEvent.h"
60 61
#include "../events/WRoiAssocEvent.h"
#include "../events/WRoiRemoveEvent.h"
62
#include "../guiElements/WQtModuleMetaInfo.h"
63
#include "../guiElements/WQtMenuFiltered.h"
64
#include "../networkEditor/WQtNetworkEditor.h"
65
#include "WQtBranchTreeItem.h"
66
#include "WQtColormapper.h"
67

68 69 70
#include "WQtControlPanel.h"
#include "WQtControlPanel.moc"

71
WQtControlPanel::WQtControlPanel( WMainWindow* parent )
72
    : QDockWidget( "Control Panel", parent ),
73
    m_ignoreSelectionChange( false ),
74 75
    m_activeModule( WModule::SPtr() ),
    m_previousTab()
76
{
77 78
    setObjectName( "Control Panel Dock" );

79
    m_mainWindow = parent;
80
    setMinimumWidth( 200 );
81

82
    m_moduleTreeWidget = new WQtTreeWidget();
83
    m_moduleTreeWidget->setContextMenuPolicy( Qt::ActionsContextMenu );
84

85 86
    m_moduleTreeWidget->setHeaderLabel( QString( "Module Tree" ) );
    m_moduleTreeWidget->setDragEnabled( false );
87 88
    m_moduleTreeWidget->viewport()->setAcceptDrops( true );
    m_moduleTreeWidget->setDropIndicatorShown( true );
89
    m_moduleTreeWidget->setMinimumHeight( 100 );
90

91
    // create context menu for tree items
92 93 94 95 96

    // a separator to clean up the tree widget's context menu
    QAction* separator = new QAction( m_moduleTreeWidget );
    separator->setSeparator( true );
    m_moduleTreeWidget->addAction( separator );
97

98
    m_addModuleAction = new QAction( WQt4Gui::getMainWindow()->getIconManager()->getIcon( "add" ), "Add Module", m_moduleTreeWidget );
99
    m_moduleTreeWidget->addAction( m_addModuleAction );
100 101
    m_connectWithPrototypeAction = new QAction( WQt4Gui::getMainWindow()->getIconManager()->getIcon( "addAndLink" ), "Add Module and Connect",
                                                m_moduleTreeWidget );
102
    m_moduleTreeWidget->addAction( m_connectWithPrototypeAction );
103 104
    m_connectWithModuleAction = new QAction( WQt4Gui::getMainWindow()->getIconManager()->getIcon( "link" ), "Connect Existing Module",
                                            m_moduleTreeWidget );
105
    m_moduleTreeWidget->addAction( m_connectWithModuleAction );
106
    m_disconnectAction = new QAction( WQt4Gui::getMainWindow()->getIconManager()->getIcon( "unlink" ), "Disconnect", m_moduleTreeWidget );
107 108
    m_moduleTreeWidget->addAction( m_disconnectAction );

109 110 111 112
    // a separator to clean up the tree widget's context menu
    m_moduleTreeWidget->addAction( separator );

    m_deleteModuleAction = new QAction( WQt4Gui::getMainWindow()->getIconManager()->getIcon( "remove" ), "Remove Module", m_moduleTreeWidget );
113 114
    {
        // Set the key for removing modules
115 116
        //m_deleteModuleAction->setShortcutContext( Qt::WidgetShortcut );
        m_deleteModuleAction->setShortcutContext( Qt::WidgetWithChildrenShortcut );
117
        m_deleteModuleAction->setShortcut( QKeySequence::Delete );
118
        m_deleteModuleAction->setIconVisibleInMenu( true );
119
    }
120
    connect( m_deleteModuleAction, SIGNAL( triggered() ), this, SLOT( deleteModule() ) );
121 122
    m_moduleTreeWidget->addAction( m_deleteModuleAction );

123 124 125 126 127 128 129 130 131 132 133
    // a separator to clean up the tree widget's context menu
    m_moduleTreeWidget->addAction( separator );

    // add an entry for those who search their module without luck
    m_missingModuleAction = new QAction( WQt4Gui::getMainWindow()->getIconManager()->getIcon( "missingModule" ), "Missing Module?",
                                          m_moduleTreeWidget );
    m_missingModuleAction->setToolTip( "Having trouble finding your module? This opens the module configuration, which allows you to define the "
                                       "modules that should be shown or hidden." );
    m_missingModuleAction->setIconVisibleInMenu( true );
    m_moduleTreeWidget->addAction( m_missingModuleAction );

134 135 136
    // the network editor also needs the context menu
    if( m_mainWindow->getNetworkEditor() )
    {
137 138 139 140 141 142 143 144
        m_mainWindow->getNetworkEditor()->getView()->setContextMenuPolicy( Qt::ActionsContextMenu );
        m_mainWindow->getNetworkEditor()->getView()->addAction( m_addModuleAction );
        m_mainWindow->getNetworkEditor()->getView()->addAction( m_connectWithPrototypeAction );
        m_mainWindow->getNetworkEditor()->getView()->addAction( m_connectWithModuleAction );
        m_mainWindow->getNetworkEditor()->getView()->addAction( m_disconnectAction );
        m_mainWindow->getNetworkEditor()->getView()->addAction( m_deleteModuleAction );
        m_mainWindow->getNetworkEditor()->getView()->addAction( separator );
        m_mainWindow->getNetworkEditor()->getView()->addAction( m_missingModuleAction );
145
    }
146

147 148
    m_colormapper = new WQtColormapper( m_mainWindow );
    m_colormapper->setToolTip( "Reorder the textures." );
149

150
    m_tabWidget = new QTabWidget(  );
151
    m_tabWidget->setMinimumHeight( 100 );
152

153 154 155
    m_moduleDock = new QDockWidget( "Module Tree", m_mainWindow );
    m_moduleDock->setObjectName( "Module Dock" );
    m_moduleDock->setWidget( m_moduleTreeWidget );
156

157 158
    m_roiDock = new QDockWidget( "ROIs", m_mainWindow );
    m_roiDock->setObjectName( "ROI Dock" );
159
    m_roiTreeWidget = new WQtTreeWidget();
160
    m_roiTreeWidget->setToolTip( "Regions of intrest (ROIs) for selecting fiber  clusters. Branches are combined using logic <b>or</b>, "
161
                                 "inside the branches the ROIs are combined using logic <b>and</b>." );
162 163 164 165 166 167
    m_roiTreeWidget->setHeaderLabel( QString( "ROIs" ) );
    m_roiTreeWidget->setHeaderHidden( true );
    m_roiTreeWidget->setDragEnabled( true );
    m_roiTreeWidget->viewport()->setAcceptDrops( true );
    m_roiTreeWidget->setDropIndicatorShown( true );
    m_roiTreeWidget->setDragDropMode( QAbstractItemView::InternalMove );
168
    m_roiDock->setWidget( m_roiTreeWidget );
169

170
    m_moduleExcluder = new WQtModuleConfig( parent );
171
    connect( m_missingModuleAction, SIGNAL( triggered( bool ) ), m_moduleExcluder, SLOT( configure() ) );
172

173 174
    this->setAllowedAreas( Qt::AllDockWidgetAreas );
    this->setFeatures( QDockWidget::DockWidgetClosable | QDockWidget::DockWidgetMovable | QDockWidget::DockWidgetFloatable );
175
    this->setWidget( m_tabWidget );
176

177
    m_tiModules = new WQtModuleHeaderTreeItem( m_moduleTreeWidget );
178 179
    m_tiModules->setText( 0, QString( "Subject-independent Modules" ) );
    m_tiModules->setToolTip( 0, "Subject-independent modules and modules for which no parent module could be detected." );
180
    m_tiRois = new WQtRoiHeaderTreeItem( m_roiTreeWidget );
Alexander Wiebel's avatar
Alexander Wiebel committed
181
    m_tiRois->setText( 0, QString( "ROIs" ) );
182

183
    connectSlots();
184

185 186
    // similar to the module delete action: a ROI delete action
    m_deleteRoiAction = new QAction( WQt4Gui::getMainWindow()->getIconManager()->getIcon( "remove" ), "Remove ROI", m_roiTreeWidget );
187
    {
188 189
        // Set the key for removing modules
        m_deleteRoiAction->setShortcutContext( Qt::WidgetShortcut );
190
        m_deleteRoiAction->setShortcut( QKeySequence::Delete );
191
        m_deleteRoiAction->setIconVisibleInMenu( true );
192
    }
193 194
    connect( m_deleteRoiAction, SIGNAL( triggered() ), this, SLOT( deleteROITreeItem() ) );
    m_roiTreeWidget->addAction( m_deleteModuleAction );
195
    m_roiTreeWidget->addAction( m_deleteRoiAction );
196 197
}

198
WQtControlPanel::~WQtControlPanel()
199 200 201
{
}

202 203
void WQtControlPanel::completeGuiSetup()
{
204
    m_mainWindow->addGlobalMenu( m_mainWindow->getNetworkEditor()->getView() );
205 206
}

207
void WQtControlPanel::connectSlots()
208
{
209
    // if the user changes some white/blacklist setting: update.
210
    connect( m_moduleExcluder, SIGNAL( updated() ), this, SLOT( reselectTreeItem() ) );
211
    connect( m_moduleTreeWidget, SIGNAL( itemSelectionChanged() ), this, SLOT( selectTreeItem() ) );
212
    connect( m_moduleTreeWidget, SIGNAL( itemClicked( QTreeWidgetItem*, int ) ), this, SLOT( changeTreeItem( QTreeWidgetItem*, int ) ) );
213 214 215
    connect( m_moduleTreeWidget, SIGNAL( itemClicked( QTreeWidgetItem*, int ) ),  m_roiTreeWidget, SLOT( clearSelection() ) );
    connect( m_roiTreeWidget, SIGNAL( itemClicked( QTreeWidgetItem*, int ) ), this, SLOT( selectRoiTreeItem() ) );
    connect( m_roiTreeWidget, SIGNAL( itemClicked( QTreeWidgetItem*, int ) ), m_moduleTreeWidget, SLOT( clearSelection() ) );
216 217
    connect( m_colormapper, SIGNAL( textureSelectionChanged( osg::ref_ptr< WGETexture3D > ) ),
             this, SLOT( selectDataModule( osg::ref_ptr< WGETexture3D > ) ) );
218
    connect( m_roiTreeWidget, SIGNAL( dragDrop() ), this, SLOT( handleRoiDragDrop() ) );
219
}
220

221
WQtSubjectTreeItem* WQtControlPanel::addSubject( std::string name )
222
{
223
    WQtSubjectTreeItem* subject = new WQtSubjectTreeItem( m_moduleTreeWidget );
224 225 226
    subject->setText( 0, QString::fromStdString( name ) );
    subject->setToolTip( 0, QString::fromStdString( "All data and modules that are children of this tree item belong to the subject \"" +
                name + "\"." ) );
227 228 229 230

    return subject;
}

231
bool WQtControlPanel::event( QEvent* event )
232
{
233
    if( event->type() == WQT_ROI_ASSOC_EVENT )
234 235
    {
        WRoiAssocEvent* e2 = dynamic_cast< WRoiAssocEvent* >( event );     // NOLINT
236
        if( e2 )
237 238
        {
            addRoi( e2->getRoi() );
239
            WLogger::getLogger()->addLogMessage( "Inserting ROI to control panel.", "ControlPanel", LL_DEBUG );
240 241 242 243 244 245 246 247 248 249
        }

        return true;
    }
    if( event->type() == WQT_ROI_REMOVE_EVENT )
    {
        WRoiRemoveEvent* e3 = dynamic_cast< WRoiRemoveEvent* >( event );
        if( e3 )
        {
            removeRoi( e3->getRoi() );
250
            WLogger::getLogger()->addLogMessage( "Removing ROI from control panel.", "ControlPanel", LL_DEBUG );
251 252 253 254 255
        }

        return true;
    }

256
    // a module got associated with the root container -> add it to the list
257
    if( event->type() == WQT_ASSOC_EVENT )
258 259
    {
        // convert event to assoc event
schurade's avatar
schurade committed
260
        WModuleAssocEvent* e1 = dynamic_cast< WModuleAssocEvent* >( event );     // NOLINT
261
        if( e1 )
262
        {
263 264
            WLogger::getLogger()->addLogMessage( "Inserting module " + e1->getModule()->getName() + " to control panel.",
                                                 "ControlPanel", LL_DEBUG );
265

266 267 268 269 270 271 272 273 274 275
            // show deprecation message?
            if( e1->getModule()->isDeprecated() )
            {
                std::string d = e1->getModule()->getDeprecationMessage();
                std::string m = "The module \"" + e1->getModule()->getName() + "\" is marked deprecated. You should avoid using it."
                                "<br><br>"
                                "Message: " + d;
                QMessageBox::warning( this, "Deprecation Warning", QString::fromStdString( m ) );
            }

schurade's avatar
schurade committed
276 277
            // finally add the module
            // TODO(schurade): is this differentiation between data and "normal" modules really needed?
278
            if( boost::shared_dynamic_cast< WDataModule >( e1->getModule() ).get() )
schurade's avatar
schurade committed
279 280 281 282 283 284 285
            {
                addDataset( e1->getModule(), 0 );
            }
            else
            {
                addModule( e1->getModule() );
            }
286
        }
schurade's avatar
schurade committed
287 288
        return true;
    }
289

290
    // a module changed its state to "ready" -> activate it in control panel
291
    if( event->type() == WQT_READY_EVENT )
schurade's avatar
schurade committed
292
    {
293 294
        // convert event to assoc event
        WModuleReadyEvent* e = dynamic_cast< WModuleReadyEvent* >( event );     // NOLINT
295
        if( !e )
296
        {
297
            // this should never happen, since the type is set to WQT_READY_EVENT.
298
            WLogger::getLogger()->addLogMessage( "Event is not an WModueReadyEvent although its type claims it. Ignoring event.",
299
                                                 "ControlPanel", LL_WARNING );
300 301

            return true;
302 303
        }

304
        std::list< WQtTreeItem* > items = findItemsByModule( e->getModule() );
305
        for( std::list< WQtTreeItem* >::const_iterator it = items.begin(); it != items.end(); ++it )
306
        {
307
            ( *it )->setDisabled( false );
308 309
        }

310
        setActiveModule( e->getModule() );
311

312 313
        return true;
    }
314

315
    // a module tree item was connected to another one
316
    if( event->type() == WQT_MODULE_CONNECT_EVENT )
317
    {
318
        WModuleConnectEvent* e = dynamic_cast< WModuleConnectEvent* >( event );     // NOLINT
319
        if( !e )
320
        {
321
            // this should never happen, since the type is set to WQT_MODULE_CONNECT_EVENT.
322
            WLogger::getLogger()->addLogMessage( "Event is not an WModuleConnectEvent although its type claims it. Ignoring event.",
323
                                                 "ControlPanel", LL_WARNING );
324
            return true;
325 326
        }

327 328 329 330
        // get the module of the input involved in this connection
        boost::shared_ptr< WModule > mIn = e->getInput()->getModule();
        boost::shared_ptr< WModule > mOut = e->getOutput()->getModule();

331 332
        // NOTE: the following is ugly. We definitely should rethink our GUI

333 334 335
        // at this moment items for each input connector are inside the tree.
        // search the items not yet associated with some other module for the first item
        std::list< WQtTreeItem* > items = findItemsByModule( mIn, m_tiModules );
336
        for( std::list< WQtTreeItem* >::const_iterator iter = items.begin(); iter != items.end(); ++iter )
337 338 339 340 341 342 343
        {
            ( *iter )->setHidden( false );
            ( *iter )->setHandledInput( e->getInput()->getName() );
            ( *iter )->setHandledOutput( e->getOutput()->getName() );

            // move it to the module with the involved output
            std::list< WQtTreeItem* > possibleParents = findItemsByModule( mOut );
344
            for( std::list< WQtTreeItem* >::const_iterator parIter = possibleParents.begin(); parIter != possibleParents.end(); ++parIter )
345 346 347
            {
                // remove child from tiModules
                m_tiModules->removeChild( *iter );
348
                if( !( *parIter )->isHidden() )
349 350 351 352 353
                {
                    ( *parIter )->addChild( *iter );
                    ( *parIter )->setExpanded( true );
                    break;
                }
354 355 356 357 358
            }

            // job done.
            break;
        }
359 360 361
    }

    // a module tree item was disconnected from another one
362
    if( event->type() == WQT_MODULE_DISCONNECT_EVENT )
363 364
    {
        WModuleDisconnectEvent* e = dynamic_cast< WModuleDisconnectEvent* >( event );     // NOLINT
365
        if( !e )
366
        {
367
            // this should never happen, since the type is set to WQT_MODULE_DISCONNECT_EVENT.
368
            WLogger::getLogger()->addLogMessage( "Event is not an WModuleDisconnectEvent although its type claims it. Ignoring event.",
369
                                                 "ControlPanel", LL_WARNING );
370 371 372
            return true;
        }

373 374 375 376 377 378 379 380 381
        // get the module of the input involved in this connection
        boost::shared_ptr< WModule > mIn = e->getInput()->getModule();
        boost::shared_ptr< WModule > mOut = e->getOutput()->getModule();

        // NOTE: the following is ugly. We definitely should rethink our GUI

        // at this moment items for each input connector are inside the tree.
        // search all items an find those containing a children which belongs to the connection input
        std::list< WQtTreeItem* > items = findItemsByModule( mOut );
382
        for( std::list< WQtTreeItem* >::const_iterator iter = items.begin(); iter != items.end(); ++iter )
383 384 385
        {
            // each of them can contain a child with the involved input
            std::list< WQtTreeItem* > childs = findItemsByModule( mIn, *iter );
386
            for( std::list< WQtTreeItem* >::const_iterator citer = childs.begin(); citer != childs.end(); ++citer )
387
            {
388
                if( ( *citer )->getHandledInput() == e->getInput()->getName() )
389 390 391 392 393 394 395 396 397 398 399 400 401 402 403
                {
                    ( *iter )->removeChild( *citer );

                    // move it back to the reservoir in m_tiModules
                    m_tiModules->addChild( *citer );
                    ( *citer )->setHidden( true );
                    ( *citer )->setHandledInput( "" );
                    ( *citer )->setHandledOutput( "" );
                }
            }
        }

        // we need to ensure that at least one item for mIn is visible somewhere
        items = findItemsByModule( mIn );
        bool oneVisible = false;
404
        for( std::list< WQtTreeItem* >::const_iterator iter = items.begin(); iter != items.end(); ++iter )
405 406 407
        {
            oneVisible = oneVisible || !( *iter )->isHidden();
        }
408
        if( !oneVisible )
409 410 411
        {
            ( *items.begin() )->setHidden( false );
        }
412
    }
413

414
    // a module tree item should be deleted
415
    if( event->type() == WQT_MODULE_DELETE_EVENT )
416
    {
417
        WModuleDeleteEvent* e = dynamic_cast< WModuleDeleteEvent* >( event );
418
        if( !e )
419
        {
420
            // this should never happen, since the type is set to WQT_MODULE_DELETE_EVENT.
421
            WLogger::getLogger()->addLogMessage( "Event is not an WModuleDeleteEvent although its type claims it. Ignoring event.",
422
                                                 "ControlPanel", LL_WARNING );
423 424 425 426 427
            return true;
        }

        // grab the module reference and print some info
        boost::shared_ptr< WModule > module = e->getTreeItem()->getModule();
428
        WLogger::getLogger()->addLogMessage( "Deleting module \"" + module->getName() + "\" from Tree.",
429
                                             "ControlPanel", LL_DEBUG );
430 431 432 433

        // remove it from the tree and free last ref count
        m_moduleTreeWidget->deleteItem( e->getTreeItem() );

434 435
        // ref count != 1? (only if there are now tree items left)
        bool lastTreeItem = !findItemsByModule( module ).size();
436
        if( lastTreeItem && ( module.use_count() != 1 ) )
437
        {
438
            wlog::error( "ControlPanel" ) << "Removed module has strange usage count: " << module.use_count() << ". Should be 1 here. " <<
439 440 441 442 443 444
                                              "Module reference is held by someone else.";
        }

        return true;
    }

445
    // a module was removed from the container
446
    if( event->type() == WQT_MODULE_REMOVE_EVENT )
447
    {
448
        WModuleRemovedEvent* e = dynamic_cast< WModuleRemovedEvent* >( event );
449
        if( !e )
450
        {
451
            // this should never happen, since the type is set to WQT_MODULE_REMOVE_EVENT.
452
            WLogger::getLogger()->addLogMessage( "Event is not an WModuleRemovedEvent although its type claims it. Ignoring event.",
453
                                                 "ControlPanel", LL_WARNING );
454 455 456 457
            return true;
        }

        // iterate tree items and find proper one
458
        std::list< WQtTreeItem* > items = findItemsByModule( e->getModule() );
459
        for( std::list< WQtTreeItem* >::const_iterator iter = items.begin(); iter != items.end(); ++iter )
460
        {
461
            ( *iter )->gotRemoved();
462 463 464
        }

        // be nice and print some info
465
        WLogger::getLogger()->addLogMessage( "Removing module \"" + e->getModule()->getName() + "\" from Tree.", "ControlPanel", LL_DEBUG );
466 467 468 469

        // stop the module
        e->getModule()->requestStop();
        WLogger::getLogger()->addLogMessage( "Waiting for module \"" + e->getModule()->getName() + "\" to finish before deleting.",
470
                                             "ControlPanel", LL_DEBUG );
471 472 473 474

        return true;
    }

475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495
    // a connector was updated
    if( event->type() == WQT_MODULE_CONNECTOR_EVENT )
    {
        // convert event to ready event
        WModuleConnectorEvent* e1 = dynamic_cast< WModuleConnectorEvent* >( event );     // NOLINT
        if( e1 )
        {
            // iterate tree items and find proper one -> check if selected
            // NOTE: This could return multiple items here. But, the GUI always selects all of the same module or none. So it is enough to check
            // the first item if it is selected to check whether the current module is active.
            std::list< WQtTreeItem* > items = findItemsByModule( e1->getModule() );
            if( !items.empty() && ( *items.begin() )->isSelected() )
            {
                // ok, the module is selected. Now, update the connectables lists (buttons and menu)
                createCompatibleButtons( e1->getModule() );
            }
        }

        return true;
    }

496 497
    return QDockWidget::event( event );
}
498

499
std::list< WQtTreeItem* > WQtControlPanel::findItemsByModule( boost::shared_ptr< WModule > module, QTreeWidgetItem* where )
500 501 502 503
{
    std::list< WQtTreeItem* > l;

    // iterate tree items and find proper one
504
    QTreeWidgetItemIterator it( where );
505
    while( *it )
506
    {
507 508
        WQtTreeItem* item = dynamic_cast< WQtTreeItem* >( *it );
        boost::shared_ptr< WModule > itemModule = boost::shared_ptr< WModule >();
509
        if( item )
510
        {
511
            itemModule = item->getModule();
512 513
        }

514
        // if the pointer is NULL the item was none of the above
515
        if( !itemModule.get() )
516 517
        {
            ++it;
518
            continue;
519
        }
520

521
        // we found it
522
        if( module == itemModule )
523 524 525 526 527
        {
            l.push_back( item );
        }

        ++it;
528
    }
529 530
    return l;
}
531

532
std::list< WQtTreeItem* > WQtControlPanel::findItemsByModule( boost::shared_ptr< WModule > module )
533
{
534 535 536 537
    std::list< WQtTreeItem* > ret = findItemsByModule( module, m_moduleTreeWidget->invisibleRootItem() );
    std::list< WQtTreeItem* > ret2 = findItemsByModule( module, m_moduleTreeWidget->topLevelItem( 0 ) );
    ret.merge( ret2 );
    return ret;
538
}
539

540
WQtDatasetTreeItem* WQtControlPanel::addDataset( boost::shared_ptr< WModule > module, int subjectId )
541
{
schurade's avatar
schurade committed
542
    int c = getFirstSubject();
543
    WQtSubjectTreeItem* subject = static_cast< WQtSubjectTreeItem* >( m_moduleTreeWidget->topLevelItem( subjectId + c ) );
schurade's avatar
schurade committed
544
    subject->setExpanded( true );
545
    WQtDatasetTreeItem* item = subject->addDatasetItem( module );
546
    item->setDisabled( true );
Sebastian Eichelbaum's avatar
[STYLE]  
Sebastian Eichelbaum committed
547
    item->setExpanded( true );
548

549
    return item;
550
}
551

552
WQtModuleTreeItem* WQtControlPanel::addModule( boost::shared_ptr< WModule > module )
553
{
schurade's avatar
schurade committed
554
    m_tiModules->setExpanded( true );
555
    WQtModuleTreeItem* item;
556 557 558 559
    // for each input, create an item
    m_moduleTreeWidget->setCurrentItem( NULL );
    bool firstItem = true;
    WModule::InputConnectorList cons = module->getInputConnectors();
560
    for( WModule::InputConnectorList::const_iterator iter = cons.begin(); iter != cons.end(); ++iter )
561
    {
562 563 564 565 566 567
        // every module gets added to tiModules first. The connection events then move these things to the right parent
        item = m_tiModules->addModuleItem( module );
        item->setDisabled( true );
        item->setExpanded( true );

        // all but the first item get hidden by default. They get visible after a connection event has been fired
568
        if( !firstItem )
569 570 571 572 573
        {
            item->setHidden( true );
        }

        firstItem = false;
574
    }
575 576

    // this module has not inputs. So we simply add it to the tiModules
577
    if( firstItem )
578 579
    {
        item = m_tiModules->addModuleItem( module );
580
        item->setDisabled( true );
581
    }
582

583
    return item;
584 585
}

586
void WQtControlPanel::addRoi( osg::ref_ptr< WROI > roi )
schurade's avatar
schurade committed
587
{
588 589 590 591
    WQtRoiTreeItem* newItem;
    WQtBranchTreeItem* branchItem;

    m_tiRois->setExpanded( true );
592
    bool found = false;
593

594 595
    // go through all branches
    for( int branchID = 0; branchID < m_tiRois->childCount(); ++branchID )
schurade's avatar
schurade committed
596
    {
597 598
        branchItem = dynamic_cast< WQtBranchTreeItem* >( m_tiRois->child( branchID ) );
        // if branch == roi branch
599
        if( branchItem->getBranch() == WKernel::getRunningKernel()->getRoiManager()->getBranch( roi ) )
schurade's avatar
schurade committed
600
        {
601 602
            found = true;
            break;
schurade's avatar
schurade committed
603 604
        }
    }
605

606
    if( !found )
schurade's avatar
schurade committed
607
    {
608
        branchItem = m_tiRois->addBranch( WKernel::getRunningKernel()->getRoiManager()->getBranch( roi ) );
schurade's avatar
schurade committed
609
    }
610 611 612 613 614

    branchItem->setExpanded( true );
    newItem = branchItem->addRoiItem( roi );
    newItem->setDisabled( false );
    newItem->setSelected( true );
615
    WKernel::getRunningKernel()->getRoiManager()->setSelectedRoi( getSelectedRoi() );
schurade's avatar
schurade committed
616 617
}

618
void WQtControlPanel::removeRoi( osg::ref_ptr< WROI > roi )
619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638
{
    for( int branchID = 0; branchID < m_tiRois->childCount(); ++branchID )
    {
        QTreeWidgetItem* branchTreeItem = m_tiRois->child( branchID );
        for( int roiID = 0; roiID < branchTreeItem->childCount(); ++roiID )
        {
            WQtRoiTreeItem* roiTreeItem = dynamic_cast< WQtRoiTreeItem* >( branchTreeItem->child( roiID ) );
            if( roiTreeItem && roiTreeItem->getRoi() == roi )
            {
                delete roiTreeItem;

                if( branchTreeItem->childCount() == 0 )
                {
                    delete branchTreeItem;
                }

                break;
            }
        }
    }
639
    WKernel::getRunningKernel()->getRoiManager()->setSelectedRoi( getSelectedRoi() );
640 641
}

642
boost::shared_ptr< WModule > WQtControlPanel::getSelectedModule()
643
{
644
    if( m_moduleTreeWidget->selectedItems().at( 0 )->type() == 1 )
645
    {
646
        return ( static_cast< WQtDatasetTreeItem* >( m_moduleTreeWidget->selectedItems().at( 0 ) )->getModule() );
647
    }
648
    else if( m_moduleTreeWidget->selectedItems().at( 0 )->type() == 3 )
649
    {
650
        return ( static_cast< WQtModuleTreeItem* >( m_moduleTreeWidget->selectedItems().at( 0 ) )->getModule() );
651 652 653 654
    }

    return boost::shared_ptr< WModule >();
}
655

656 657 658 659 660
void WQtControlPanel::reselectTreeItem()
{
    setActiveModule( getSelectedModule(), true );
}

661
void WQtControlPanel::selectTreeItem()
662
{
663
    if( m_ignoreSelectionChange )
664 665 666 667
    {
        return;
    }

668
    if( m_moduleTreeWidget->selectedItems().size() != 0  )
669
    {
670
        switch( m_moduleTreeWidget->selectedItems().at( 0 )->type() )
schurade's avatar
schurade committed
671
        {
672
            case SUBJECT:
673
            case MODULEHEADER:
674
                {
675 676
                    // deletion of headers and subjects is not allowed
                    deactivateModuleSelection( false );
677
                }
678 679
                break;
            case DATASET:
680
                {
681 682
                    WModule::SPtr module = ( static_cast< WQtDatasetTreeItem* >( m_moduleTreeWidget->selectedItems().at( 0 ) ) )->getModule();
                    setActiveModule( module );
683
                }
schurade's avatar
schurade committed
684
                break;
685
            case MODULE:
686
                {
687 688
                    WModule::SPtr module = ( static_cast< WQtModuleTreeItem* >( m_moduleTreeWidget->selectedItems().at( 0 ) ) )->getModule();
                    setActiveModule( module );
689
                }
690
                break;
691 692 693 694
            case ROIHEADER:
            case ROIBRANCH:
            case ROI:
            default:
695
                deactivateModuleSelection( false );
696 697 698
                break;
        }
    }
699 700 701 702 703
    else
    {
        // clean up if nothing is selected
        setActiveModule( WModule::SPtr() );  // module is NULL at this point
    }
704 705
}

706
void WQtControlPanel::selectRoiTreeItem()
707
{
708
    clearAndDeleteTabs();
709 710 711 712 713 714 715 716 717

    // Make compatibles toolbar empty
    {
        if( m_mainWindow->getCompatiblesToolbar() != 0 )
        {
            m_mainWindow->getCompatiblesToolbar()->makeEmpty();
        }
        else
        {
718
            m_mainWindow->setCompatiblesToolbar( new WQtCombinerToolbar( m_mainWindow ) );
719 720
        }
    }
721 722

    boost::shared_ptr< WModule > module;
723
    boost::shared_ptr< WProperties > props;
724

725
    if( m_roiTreeWidget->selectedItems().size() != 0  )
726
    {