WQtControlPanel.cpp 46.8 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
    m_moduleDock->setHidden( true );
157

158 159
    m_roiDock = new QDockWidget( "ROIs", m_mainWindow );
    m_roiDock->setObjectName( "ROI Dock" );
160
    m_roiTreeWidget = new WQtTreeWidget();
161
    m_roiTreeWidget->setToolTip( "Regions of intrest (ROIs) for selecting fiber  clusters. Branches are combined using logic <b>or</b>, "
162
                                 "inside the branches the ROIs are combined using logic <b>and</b>." );
163 164 165 166 167 168
    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 );
169
    m_roiDock->setWidget( m_roiTreeWidget );
170
    m_roiTreeWidget->setSelectionMode( QAbstractItemView::SingleSelection );
171

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

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

179
    m_tiModules = new WQtModuleHeaderTreeItem( m_moduleTreeWidget );
180 181
    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." );
182
    m_tiRois = new WQtRoiHeaderTreeItem( m_roiTreeWidget );
Alexander Wiebel's avatar
Alexander Wiebel committed
183
    m_tiRois->setText( 0, QString( "ROIs" ) );
184

185
    connectSlots();
186

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

200
WQtControlPanel::~WQtControlPanel()
201 202 203
{
}

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

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

223
WQtSubjectTreeItem* WQtControlPanel::addSubject( std::string name )
224
{
225
    WQtSubjectTreeItem* subject = new WQtSubjectTreeItem( m_moduleTreeWidget );
226 227 228
    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 + "\"." ) );
229 230 231 232

    return subject;
}

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

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

        return true;
    }

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

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

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

            return true;
304 305
        }

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

312
        setActiveModule( e->getModule() );
313

314 315
        return true;
    }
316

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

329 330 331 332
        // 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();

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

335 336 337
        // 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 );
338
        for( std::list< WQtTreeItem* >::const_iterator iter = items.begin(); iter != items.end(); ++iter )
339 340 341 342 343 344 345
        {
            ( *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 );
346
            for( std::list< WQtTreeItem* >::const_iterator parIter = possibleParents.begin(); parIter != possibleParents.end(); ++parIter )
347 348 349
            {
                // remove child from tiModules
                m_tiModules->removeChild( *iter );
350
                if( !( *parIter )->isHidden() )
351 352 353 354 355
                {
                    ( *parIter )->addChild( *iter );
                    ( *parIter )->setExpanded( true );
                    break;
                }
356 357 358 359 360
            }

            // job done.
            break;
        }
361 362 363
    }

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

375 376 377 378 379 380 381 382 383
        // 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 );
384
        for( std::list< WQtTreeItem* >::const_iterator iter = items.begin(); iter != items.end(); ++iter )
385 386 387
        {
            // each of them can contain a child with the involved input
            std::list< WQtTreeItem* > childs = findItemsByModule( mIn, *iter );
388
            for( std::list< WQtTreeItem* >::const_iterator citer = childs.begin(); citer != childs.end(); ++citer )
389
            {
390
                if( ( *citer )->getHandledInput() == e->getInput()->getName() )
391 392 393 394 395 396 397 398 399 400 401 402 403 404 405
                {
                    ( *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;
406
        for( std::list< WQtTreeItem* >::const_iterator iter = items.begin(); iter != items.end(); ++iter )
407 408 409
        {
            oneVisible = oneVisible || !( *iter )->isHidden();
        }
410
        if( !oneVisible )
411 412 413
        {
            ( *items.begin() )->setHidden( false );
        }
414
    }
415

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

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

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

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

        return true;
    }

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

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

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

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

        return true;
    }

477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497
    // 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;
    }

498 499
    return QDockWidget::event( event );
}
500

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

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

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

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

        ++it;
530
    }
531 532
    return l;
}
533

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

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

551
    return item;
552
}
553

554
WQtModuleTreeItem* WQtControlPanel::addModule( boost::shared_ptr< WModule > module )
555
{
schurade's avatar
schurade committed
556
    m_tiModules->setExpanded( true );
557
    WQtModuleTreeItem* item;
558 559 560 561
    // for each input, create an item
    m_moduleTreeWidget->setCurrentItem( NULL );
    bool firstItem = true;
    WModule::InputConnectorList cons = module->getInputConnectors();
562
    for( WModule::InputConnectorList::const_iterator iter = cons.begin(); iter != cons.end(); ++iter )
563
    {
564 565 566 567 568 569
        // 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
570
        if( !firstItem )
571 572 573 574 575
        {
            item->setHidden( true );
        }

        firstItem = false;
576
    }
577 578

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

585
    return item;
586 587
}

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

    m_tiRois->setExpanded( true );
594
    bool found = false;
595

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

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

    branchItem->setExpanded( true );
    newItem = branchItem->addRoiItem( roi );
    newItem->setDisabled( false );
616
    m_roiTreeWidget->setCurrentItem( newItem );
617
    WKernel::getRunningKernel()->getRoiManager()->setSelectedRoi( getSelectedRoi() );
618
    selectRoiTreeItem( newItem );
schurade's avatar
schurade committed
619 620
}

621
void WQtControlPanel::removeRoi( osg::ref_ptr< WROI > roi )
622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641
{
    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;
            }
        }
    }
642
    WKernel::getRunningKernel()->getRoiManager()->setSelectedRoi( getSelectedRoi() );
643 644
}

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

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

659 660 661 662 663
void WQtControlPanel::reselectTreeItem()
{
    setActiveModule( getSelectedModule(), true );
}

664
void WQtControlPanel::selectTreeItem()
665
{
666
    if( m_ignoreSelectionChange )
667 668 669 670
    {
        return;
    }

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

709
void WQtControlPanel::selectRoiTreeItem( QTreeWidgetItem* item )
710
{
711
    clearAndDeleteTabs();
712 713

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