WMainWindow.cpp 28.8 KB
Newer Older
1 2
//---------------------------------------------------------------------------
//
3
// Project: OpenWalnut ( http://www.openwalnut.org )
4
//
5 6
// Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS
// For more information see http://www.openwalnut.org/copying
wiebel's avatar
wiebel committed
7
//
wiebel's avatar
wiebel committed
8
// This file is part of OpenWalnut.
wiebel's avatar
wiebel committed
9
//
wiebel's avatar
wiebel committed
10
// OpenWalnut is free software: you can redistribute it and/or modify
wiebel's avatar
wiebel committed
11 12 13 14
// 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.
//
wiebel's avatar
wiebel committed
15
// OpenWalnut is distributed in the hope that it will be useful,
wiebel's avatar
wiebel committed
16 17 18 19 20
// 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
wiebel's avatar
wiebel committed
21
// along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
wiebel's avatar
wiebel committed
22
//
23 24
//---------------------------------------------------------------------------

25
#include <iostream>
26 27
#include <string>
#include <vector>
28
#include <map>
29

30 31
#include <boost/thread.hpp>

32
#include <QtGui/QApplication>
33
#include <QtGui/QMainWindow>
wiebel's avatar
wiebel committed
34
#include <QtGui/QDockWidget>
35
#include <QtGui/QFileDialog>
36
#include <QtGui/QMessageBox>
37
#include <QtGui/QSlider>
38
#include <QtGui/QShortcut>
39
#include <QtGui/QVBoxLayout>
40 41
#include <QtGui/QMenuBar>
#include <QtGui/QMenu>
42

43
#include "WMainWindow.h"
44
#include "WOpenCustomDockWidgetEvent.h"
45
#include "WQtGLWidget.h"
46
#include "WQtNavGLWidget.h"
47
#include "WQtCustomDockWidget.h"
48
#include "events/WModuleReadyEvent.h"
49
#include "events/WModuleCrashEvent.h"
50 51
#include "events/WEventTypes.h"
#include "datasetbrowser/WPropertyBoolWidget.h"
52 53 54
#include "../../common/WColor.h"
#include "../../common/WPreferences.h"
#include "../../kernel/WKernel.h"
55
#include "../../kernel/WProjectFile.h"
56
#include "../../modules/data/WMData.h"
57
#include "../../modules/navSlices/WMNavSlices.h"
58

59
#include "../../dataHandler/WEEG2.h"
60 61
#include "../../dataHandler/WDataSetSingle.h"
#include "../../dataHandler/WDataSetFibers.h"
wiebel's avatar
wiebel committed
62

schurade's avatar
schurade committed
63 64
#include "../../graphicsEngine/WROIBox.h"

65
#include "../icons/WIcons.h"
66

67
WMainWindow::WMainWindow() :
68
    QMainWindow(),
69 70
    m_iconManager(),
    m_fibLoaded( false )
Sebastian Eichelbaum's avatar
Sebastian Eichelbaum committed
71 72
{
}
73

74
void WMainWindow::setupGUI()
75
{
76
    m_iconManager.addIcon( std::string( "load" ), fileopen_xpm );
77
    m_iconManager.addIcon( std::string( "loadProject" ), projOpen_xpm );
78
    m_iconManager.addIcon( std::string( "saveProject" ), projSave_xpm );
79
    m_iconManager.addIcon( std::string( "logo" ), logoIcon_xpm );
80
    m_iconManager.addIcon( std::string( "help" ), question_xpm );
81
    m_iconManager.addIcon( std::string( "quit" ), quit_xpm );
82 83 84
    m_iconManager.addIcon( std::string( "moduleBusy" ), moduleBusy_xpm );
    m_iconManager.addIcon( std::string( "moduleCrashed" ), moduleCrashed_xpm );
    m_iconManager.addIcon( std::string( "remove" ), remove_xpm );
85

86
    if( objectName().isEmpty() )
87
    {
88
        setObjectName( QString::fromUtf8( "MainWindow" ) );
89
    }
90 91
    resize( 946, 632 );
    setWindowIcon( m_iconManager.getIcon( "logo" ) );
92
    setWindowTitle( QApplication::translate( "MainWindow", "OpenWalnut (development version)", 0, QApplication::UnicodeUTF8 ) );
93

94
    m_menuBar = new QMenuBar( this );
95 96
    QMenu* fileMenu = m_menuBar->addMenu( "File" );
    fileMenu->addAction( m_iconManager.getIcon( "load" ), "Load", this, SLOT( openLoadDialog() ), QKeySequence( "Ctrl+L" ) );
97
    fileMenu->addAction( "Config", this, SLOT( openConfigDialog() ), QKeySequence( "Ctrl+C" ) );
98 99
    fileMenu->addAction( m_iconManager.getIcon( "quit" ), "Quit", this, SLOT( close() ), QKeySequence( "Ctrl+Q" ) );

100 101 102 103 104 105 106 107
    QMenu* viewMenu = m_menuBar->addMenu( "View" );
    viewMenu->addAction( "Left", this, SLOT( openNotImplementedDialog() ), QKeySequence( "L" ) );
    viewMenu->addAction( "Right", this, SLOT( openNotImplementedDialog() ), QKeySequence( "R" ) );
    viewMenu->addAction( "Superior", this, SLOT( openNotImplementedDialog() ), QKeySequence( "S" ) );
    viewMenu->addAction( "Inferior", this, SLOT( openNotImplementedDialog() ), QKeySequence( "I" ) );
    viewMenu->addAction( "Anterior", this, SLOT( openNotImplementedDialog() ), QKeySequence( "A" ) );
    viewMenu->addAction( "Posterior", this, SLOT( openNotImplementedDialog() ), QKeySequence( "P" ) );

108 109
    QMenu* helpMenu = m_menuBar->addMenu( "Help" );
    helpMenu->addAction( m_iconManager.getIcon( "help" ), "About OpenWalnut", this, SLOT( openAboutDialog() ), QKeySequence( "F1" ) );
110

111 112
    setMenuBar( m_menuBar );

113
    m_centralwidget = new QWidget( this );
114
    m_centralwidget->setObjectName( QString::fromUtf8( "centralwidget" ) );
115
    setCentralWidget( m_centralwidget );
116

117
    m_mainGLWidget = boost::shared_ptr< WQtGLWidget >( new WQtGLWidget( "main", this, WGECamera::ORTHOGRAPHIC ) );
118 119
    m_mainGLWidget->initialize();
    setCentralWidget( m_mainGLWidget.get() );
wiebel's avatar
wiebel committed
120

121 122 123 124 125
    // initially 3 navigation views
    {
        bool hideWidget;
        if( !( WPreferences::getPreference( "qt4gui.hideAxial", &hideWidget ) && hideWidget) )
        {
126
            m_navAxial = boost::shared_ptr< WQtNavGLWidget >( new WQtNavGLWidget( "axial", this, "Axial Slice" ) );
127
            m_navAxial->setFeatures( QDockWidget::AllDockWidgetFeatures );
128 129 130 131
            addDockWidget( Qt::LeftDockWidgetArea, m_navAxial.get() );
        }
        if( !( WPreferences::getPreference( "qt4gui.hideCoronal", &hideWidget ) && hideWidget) )
        {
132
            m_navCoronal = boost::shared_ptr< WQtNavGLWidget >( new WQtNavGLWidget( "coronal", this, "Coronal Slice" ) );
133
            m_navCoronal->setFeatures( QDockWidget::AllDockWidgetFeatures );
134 135 136 137
            addDockWidget( Qt::LeftDockWidgetArea, m_navCoronal.get() );
        }
        if( !( WPreferences::getPreference( "qt4gui.hideSagittal", &hideWidget ) && hideWidget) )
        {
138
            m_navSagittal = boost::shared_ptr< WQtNavGLWidget >( new WQtNavGLWidget( "sagittal", this, "Sagittal Slice" ) );
139
            m_navSagittal->setFeatures( QDockWidget::AllDockWidgetFeatures );
140 141 142
            addDockWidget( Qt::LeftDockWidgetArea, m_navSagittal.get() );
        }
    }
143

Mathias Goldau's avatar
[MERGE]  
Mathias Goldau committed
144 145 146 147 148 149 150 151 152
    // we do not need the dummy widget if there are no other widgets.
    if( m_navAxial || m_navCoronal || m_navSagittal )
    {
        m_dummyWidget = new QDockWidget( this );
        m_dummyWidget->setFeatures( QDockWidget::NoDockWidgetFeatures );
        m_dummyWidget->setSizePolicy( QSizePolicy::Preferred, QSizePolicy::Ignored );
        addDockWidget( Qt::LeftDockWidgetArea, m_dummyWidget );
    }

153
    // Default background color from config file
154
    {
155 156 157 158 159 160 161 162 163 164
        WColor bgColor;
        double r;
        double g;
        double b;
        if( WPreferences::getPreference( "ge.bgColor.r", &r )
            && WPreferences::getPreference( "ge.bgColor.g", &g )
            && WPreferences::getPreference( "ge.bgColor.b", &b ) )
        {
            bgColor.setRGB( r, g, b );
            m_mainGLWidget->setBgColor( bgColor );
165 166 167 168 169 170 171 172 173 174 175 176 177

            if ( m_navAxial )
            {
                m_navAxial->getGLWidget()->setBgColor( bgColor );
            }
            if ( m_navCoronal )
            {
                m_navCoronal->getGLWidget()->setBgColor( bgColor );
            }
            if ( m_navSagittal )
            {
                m_navSagittal->getGLWidget()->setBgColor( bgColor );
            }
178
        }
179 180
    }

181
    setupPermanentToolBar();
182

183 184
    setupCompatiblesToolBar();

185
    m_datasetBrowser = new WQtDatasetBrowser( this );
186
    m_datasetBrowser->setFeatures( QDockWidget::AllDockWidgetFeatures );
187
    addDockWidget( Qt::RightDockWidgetArea, m_datasetBrowser );
188
    m_datasetBrowser->addSubject( "Default Subject" );
189
}
190

191
void WMainWindow::setupPermanentToolBar()
192
{
193
    m_permanentToolBar = new WQtToolBar( "Permanent Toolbar", this );
194

195 196 197 198
    m_iconManager.addIcon( std::string( "ROI" ), box_xpm );
    m_iconManager.addIcon( std::string( "axial" ), axial_xpm );
    m_iconManager.addIcon( std::string( "coronal" ), cor_xpm );
    m_iconManager.addIcon( std::string( "sagittal" ), sag_xpm );
199 200


201 202
    WQtPushButton* loadButton = new WQtPushButton( m_iconManager.getIcon( "load" ), "load", m_permanentToolBar );
    WQtPushButton* roiButton = new WQtPushButton( m_iconManager.getIcon( "ROI" ), "ROI", m_permanentToolBar );
203 204
    WQtPushButton* projectLoadButton = new WQtPushButton( m_iconManager.getIcon( "loadProject" ), "loadProject", m_permanentToolBar );
    WQtPushButton* projectSaveButton = new WQtPushButton( m_iconManager.getIcon( "saveProject" ), "saveProject", m_permanentToolBar );
205

206 207 208
    // setup save button
    QMenu* saveMenu = new QMenu( "Save Project", projectSaveButton );
    saveMenu->addAction( "Save Project", this, SLOT( projectSaveAll() ) );
209
    saveMenu->addAction( "Save Modules", this, SLOT( projectSaveModuleOnly() ) );
210 211 212 213 214
    saveMenu->addAction( "Save Camera", this, SLOT( projectSaveCameraOnly() ) );
    saveMenu->addAction( "Save ROIs", this, SLOT( projectSaveROIOnly() ) );
    projectSaveButton->setPopupMode( QToolButton::MenuButtonPopup );
    projectSaveButton->setMenu( saveMenu );

215 216
    connect( loadButton, SIGNAL( pressed() ), this, SLOT( openLoadDialog() ) );
    connect( roiButton, SIGNAL( pressed() ), this, SLOT( newRoi() ) );
217
    connect( projectLoadButton, SIGNAL( pressed() ), this, SLOT( projectLoad() ) );
218
    connect( projectSaveButton, SIGNAL( pressed() ), this, SLOT( projectSaveAll() ) );
219

220 221
    loadButton->setToolTip( "Load Data" );
    roiButton->setToolTip( "Create New ROI" );
222 223
    projectLoadButton->setToolTip( "Load a project from file" );
    projectSaveButton->setToolTip( "Save current project to file" );
224

225
    m_permanentToolBar->addWidget( loadButton );
226
    m_permanentToolBar->addSeparator();
227 228
    m_permanentToolBar->addWidget( projectLoadButton );
    m_permanentToolBar->addWidget( projectSaveButton );
229
    m_permanentToolBar->addSeparator();
230
    m_permanentToolBar->addWidget( roiButton );
231

232
    m_permanentToolBar->addSeparator();
233

234 235
    addToolBar( Qt::TopToolBarArea, m_permanentToolBar );
}
236

237 238 239 240 241 242 243 244 245 246
void WMainWindow::autoAdd( boost::shared_ptr< WModule > module, std::string proto )
{
    // get the prototype.
    if ( !WKernel::getRunningKernel()->getRootContainer()->applyModule( module, proto, true ) )
    {
        WLogger::getLogger()->addLogMessage( "Auto Display active but module " + proto + " could not be added.",
                                             "GUI", LL_ERROR );
    }
}

247 248
void WMainWindow::moduleSpecificSetup( boost::shared_ptr< WModule > module )
{
249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269
    // Add all special handlings here. This method is called whenever a module is marked "ready". You can set up the gui for special modules,
    // load certain modules for datasets and so on.

    // The Data Modules also play an special role. To have modules being activated when certain data got loaded, we need to hook it up here.
    bool useAutoDisplay = true;
    WPreferences::getPreference( "qt4gui.useAutoDisplay", &useAutoDisplay );
    if ( useAutoDisplay && module->getType() == MODULE_DATA )
    {
        WLogger::getLogger()->addLogMessage( "Auto Display active and Data module added. The proper module will be added.",
                                             "GUI", LL_DEBUG );

        // data modules contain an member denoting the real data type. Currently we only have one data module and a not very modulated data
        // structures.
        boost::shared_ptr< WMData > dataModule = boost::shared_static_cast< WMData >( module );

        // grab data and identify type
        if ( dataModule->getDataSet()->isA< WDataSetSingle >() )
        {
            // it is a dataset single
            // load a nav slice module if a WDataSetSingle is available!?

270
            // if it not already is running: add it
271 272
            if ( !WMNavSlices::isRunning() )
            {
273
                autoAdd( module, "Navigation Slices" );
274
            }
275 276 277 278
        }
        else if ( dataModule->getDataSet()->isA< WDataSetFibers >() )
        {
            // it is a fiber dataset -> add the FiberDisplay module
279 280 281 282 283 284

            // if it not already is running: add it
            if ( !WMFiberDisplay::isRunning() )
            {
                autoAdd( module, "Fiber Display" );
            }
285
        }
286
        else if ( dataModule->getDataSet()->isA< WEEG2 >() )
287
        {
288
            // it is a eeg dataset -> add the eegView module
289 290 291 292
            autoAdd( module, "EEG View" );
        }
    }

293
    // nav slices use separate buttons for slice on/off switching
294
    if ( module->getName() == "Navigation Slices" )
295
    {
296
        boost::shared_ptr< WPropertyBase > prop = module->getProperties()->findProperty( "showAxial" );
297 298 299
        if ( !prop )
        {
               WLogger::getLogger()->
300
                   addLogMessage( "Navigation Slices module does not provide the property \"showAxial\", which is required by the GUI.", "GUI",
301 302 303 304 305 306 307 308 309 310
                                  LL_ERROR );
        }
        else
        {
            WPropertyBoolWidget* button = new WPropertyBoolWidget( prop->toPropBool(), NULL, m_permanentToolBar, true );
            button->setToolTip( "Toggle Axial Slice" );
            button->getButton()->setMaximumSize( 24, 24 );
            button->getButton()->setIcon( m_iconManager.getIcon( "axial" ) );
            m_permanentToolBar->addWidget( button );
        }
311

312
        prop = module->getProperties()->findProperty( "showCoronal" );
313 314 315
        if ( !prop )
        {
               WLogger::getLogger()->
316
                   addLogMessage( "Navigation Slices module does not provide the property \"showCoronal\", which is required by the GUI.", "GUI",
317 318 319 320 321 322 323 324 325 326
                                  LL_ERROR );
        }
        else
        {
            WPropertyBoolWidget* button = new WPropertyBoolWidget( prop->toPropBool(), NULL, m_permanentToolBar, true );
            button->setToolTip( "Toggle Coronal Slice" );
            button->getButton()->setMaximumSize( 24, 24 );
            button->getButton()->setIcon( m_iconManager.getIcon( "coronal" ) );
            m_permanentToolBar->addWidget( button );
        }
327

328
        prop = module->getProperties()->findProperty( "showSagittal" );
329 330 331
        if ( !prop )
        {
               WLogger::getLogger()->
332
                   addLogMessage( "Navigation Slices module does not provide the property \"showSagittal\", which is required by the GUI.", "GUI",
333 334 335 336 337 338 339 340 341 342
                                  LL_ERROR );
        }
        else
        {
            WPropertyBoolWidget* button = new WPropertyBoolWidget( prop->toPropBool(), NULL, m_permanentToolBar, true );
            button->setToolTip( "Toggle Sagittal Slice" );
            button->getButton()->setMaximumSize( 24, 24 );
            button->getButton()->setIcon( m_iconManager.getIcon( "sagittal" ) );
            m_permanentToolBar->addWidget( button );
        }
343 344

        // now setup the nav widget sliders
345
        prop = module->getProperties()->findProperty( "Axial Slice" );
346 347 348
        if ( !prop )
        {
               WLogger::getLogger()->
349
                   addLogMessage( "Navigation Slices module does not provide the property \"Axial Slice\", which is required by the GUI.", "GUI",
350 351 352 353
                                  LL_ERROR );
        }
        else
        {
354 355 356 357
            if( m_navAxial )
            {
                m_navAxial->setSliderProperty( prop->toPropInt() );
            }
358 359
        }

360
        prop = module->getProperties()->findProperty( "Coronal Slice" );
361 362 363
        if ( !prop )
        {
               WLogger::getLogger()->
364
                   addLogMessage( "Navigation Slices module does not provide the property \"Coronal Slice\", which is required by the GUI.", "GUI",
365 366 367 368
                                  LL_ERROR );
        }
        else
        {
369 370 371 372
            if( m_navCoronal )
            {
                m_navCoronal->setSliderProperty( prop->toPropInt() );
            }
373 374
        }

375
        prop = module->getProperties()->findProperty( "Sagittal Slice" );
376 377 378
        if ( !prop )
        {
               WLogger::getLogger()->
379
                   addLogMessage( "Navigation Slices module does not provide the property \"Sagittal Slice\", which is required by the GUI.", "GUI",
380 381 382 383
                                  LL_ERROR );
        }
        else
        {
384 385 386 387
            if( m_navSagittal )
            {
               m_navSagittal->setSliderProperty( prop->toPropInt() );
            }
388
        }
389
    }
wiebel's avatar
wiebel committed
390
}
391

392 393
void WMainWindow::setupCompatiblesToolBar()
{
394 395
    m_iconManager.addIcon( std::string( "o" ), o_xpm ); // duumy icon for modules

396
    m_compatiblesToolBar = new WQtToolBar( "Compatible Modules Toolbar", this );
397 398 399 400 401 402 403

    // optional toolbar break
    {
        bool useToolBarBreak = true;
        WPreferences::getPreference( "qt4gui.useToolBarBreak", &useToolBarBreak );
        if( useToolBarBreak )
        {
404 405 406 407
            // Blank toolbar for nicer layout in case of toolbar break
            // This can be done nicer very probably.
            WQtToolBar* blankToolBar = new WQtToolBar( "Blank Toolbar", this );
            addToolBar( Qt::TopToolBarArea, blankToolBar );
408 409 410 411
            addToolBarBreak( Qt::TopToolBarArea );
        }
    }

412 413
    addToolBar( Qt::TopToolBarArea, m_compatiblesToolBar );
}
414

415
WQtDatasetBrowser* WMainWindow::getDatasetBrowser()
416
{
417
    return m_datasetBrowser;
418
}
419

420
WQtToolBar* WMainWindow::getCompatiblesToolBar()
421 422 423 424
{
    return m_compatiblesToolBar;
}

425
void WMainWindow::projectSave( const std::vector< boost::shared_ptr< WProjectFileIO > >& writer )
426 427 428 429
{
    QFileDialog fd;
    fd.setWindowTitle( "Save Project as" );
    fd.setFileMode( QFileDialog::AnyFile );
430
    fd.setAcceptMode( QFileDialog::AcceptSave );
431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449

    QStringList filters;
    filters << "Project File (*.owproj)"
            << "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() )
        );

450 451 452
        try
        {
            // This call is synchronous.
453 454 455 456 457 458 459 460
            if ( writer.empty() )
            {
                proj->save();
            }
            else
            {
                proj->save( writer );
            }
461 462 463 464 465 466 467 468
        }
        catch( const std::exception& e )
        {
            QString title = "Problem while saving project file.";
            QString message = "<b>Problem while saving project file.</b><br/><br/><b>File:  </b>" + ( *constIterator ) +
                              "<br/><b>Message:  </b>" + QString::fromStdString( e.what() );
            QMessageBox::critical( this, title, message );
        }
469 470 471
    }
}

472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492
void WMainWindow::projectSaveAll()
{
    std::vector< boost::shared_ptr< WProjectFileIO > > w;
    // an empty list equals "all"
    projectSave( w );
}

void WMainWindow::projectSaveCameraOnly()
{
    std::vector< boost::shared_ptr< WProjectFileIO > > w;
    w.push_back( WProjectFile::getCameraWriter() );
    projectSave( w );
}

void WMainWindow::projectSaveROIOnly()
{
    std::vector< boost::shared_ptr< WProjectFileIO > > w;
    w.push_back( WProjectFile::getROIWriter() );
    projectSave( w );
}

493 494 495 496 497 498 499
void WMainWindow::projectSaveModuleOnly()
{
    std::vector< boost::shared_ptr< WProjectFileIO > > w;
    w.push_back( WProjectFile::getModuleWriter() );
    projectSave( w );
}

500 501 502 503 504 505
void WMainWindow::projectLoad()
{
    QFileDialog fd;
    fd.setFileMode( QFileDialog::ExistingFiles );

    QStringList filters;
506
    filters << "Simple Project File (*.owproj)"
507 508 509 510 511 512 513 514 515 516 517 518
            << "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 )
    {
519 520
        boost::shared_ptr< WProjectFile > proj = boost::shared_ptr< WProjectFile >(
                new WProjectFile( ( *constIterator ).toStdString() )
521
        );
522 523

        // This call is asynchronous. It parses the file and the starts a thread to actually do all the stuff
524
        proj->load();
525 526 527
    }
}

528
void WMainWindow::openLoadDialog()
529
{
530 531
    QFileDialog fd;
    fd.setFileMode( QFileDialog::ExistingFiles );
wiebel's avatar
wiebel committed
532 533

    QStringList filters;
534 535
    filters << "Known file types (*.cnt *.edf *.asc *.nii *.nii.gz *.fib)"
            << "EEG files (*.cnt *.edf *.asc)"
wiebel's avatar
wiebel committed
536
            << "NIfTI (*.nii *.nii.gz)"
537 538
            << "Fibers (*.fib)"
            << "Any files (*)";
wiebel's avatar
wiebel committed
539
    fd.setNameFilters( filters );
540 541 542 543 544 545 546
    fd.setViewMode( QFileDialog::Detail );
    QStringList fileNames;
    if ( fd.exec() )
    {
        fileNames = fd.selectedFiles();
    }

547
    std::vector< std::string > stdFileNames;
548 549 550 551 552 553

    QStringList::const_iterator constIterator;
    for ( constIterator = fileNames.constBegin(); constIterator != fileNames.constEnd(); ++constIterator )
    {
        stdFileNames.push_back( ( *constIterator ).toLocal8Bit().constData() );
    }
554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581

    //
    // WE KNOW THAT THIS IS KIND OF A HACK. Iis is only provided to prevent naive users from having trouble.
    //
    bool allowOnlyOneFiberDataSet = false;
    bool doubleFibersFound = false; // have we detected the multiple loading of fibers?
    if( WPreferences::getPreference( "general.allowOnlyOneFiberDataSet", &allowOnlyOneFiberDataSet ) && allowOnlyOneFiberDataSet )
    {
        for( std::vector< std::string >::iterator it = stdFileNames.begin(); it != stdFileNames.end(); ++it )
        {
            using wiotools::getSuffix;
            std::string suffix = getSuffix( *it );
            bool isFib = ( suffix == ".fib" );
            if( m_fibLoaded && isFib )
            {
                QCoreApplication::postEvent( this, new WModuleCrashEvent(
                                                 WModuleFactory::getModuleFactory()->getPrototypeByName( "Data Module" ),
                                                 std::string( "Tried to load two fiber data sets. This is not allowed by your preferences." ) ) );
                doubleFibersFound = true;
            }
            m_fibLoaded |= isFib;
        }
    }

    if( !doubleFibersFound )
    {
        m_loaderSignal( stdFileNames );
    }
582
}
583

584 585 586 587 588 589 590 591 592 593 594 595 596 597 598
void WMainWindow::openAboutDialog()
{
    QMessageBox::about( this, "About OpenWalnut",
                        "OpenWalnut ( http://www.openwalnut.org )\n\n"
                        "Copyright (C) 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS. "
                        "For more information see http://www.openwalnut.org/copying.\n\n"
                        "This program comes with ABSOLUTELY NO WARRANTY. "
                        "This is free software, and you are welcome to redistribute it "
                        "under the terms of the GNU Lesser General Public License. "
                        "You should have received a copy of the GNU Lesser General Public License "
                        "along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.\n"
                        "\n"
                        "Thank you for using OpenWalnut." );
}

599 600 601 602 603 604 605
void WMainWindow::openNotImplementedDialog()
{
    QMessageBox::information( this, "Not yet implemented!",
                              "This functionality is planned for future versions of OpenWalnut. "
                              "It is not yet implemented." );
}

schurade's avatar
schurade committed
606
boost::signals2::signal1< void, std::vector< std::string > >* WMainWindow::getLoaderSignal()
607 608 609 610
{
    return &m_loaderSignal;
}

611 612 613
WIconManager*  WMainWindow::getIconManager()
{
    return &m_iconManager;
614
}
615 616 617 618 619 620 621 622 623 624

void WMainWindow::closeEvent( QCloseEvent* e )
{
    // use some "Really Close?" Dialog here
    bool reallyClose = true;


    // handle close event
    if ( reallyClose )
    {
625 626
        // signal everybody to shut down properly.
        WKernel::getRunningKernel()->finalize();
627 628 629 630

        // now nobody acesses the osg anymore
        // clean up gl widgets
        m_mainGLWidget->close();
631 632 633 634 635 636 637 638 639 640 641 642
        if( m_navAxial )
        {
            m_navAxial->close();
        }
        if( m_navCoronal )
        {
            m_navCoronal->close();
        }
        if( m_navSagittal )
        {
            m_navSagittal->close();
        }
643

644 645 646 647 648 649 650
        // delete CustomDockWidgets
        boost::mutex::scoped_lock lock( m_customDockWidgetsLock );
        for( std::map< std::string, boost::shared_ptr< WQtCustomDockWidget > >::iterator it = m_customDockWidgets.begin();
             it != m_customDockWidgets.end(); ++it )
        {
            it->second->close();
        }
651
        //m_customDockWidgetsLock.unlock();
652

653 654 655 656 657 658 659 660 661
        // finally close
        e->accept();
    }
    else
    {
        e->ignore();
    }
}

662 663
void WMainWindow::customEvent( QEvent* event )
{
664
    if( event->type() == WOpenCustomDockWidgetEvent::CUSTOM_TYPE )
665
    {
666 667 668 669 670
        // OpenCustomDockWidgetEvent
        WOpenCustomDockWidgetEvent* ocdwEvent = static_cast< WOpenCustomDockWidgetEvent* >( event );
        std::string title = ocdwEvent->getTitle();

        boost::shared_ptr< WQtCustomDockWidget > widget;
671 672

        boost::mutex::scoped_lock lock( m_customDockWidgetsLock );
673 674
        if( m_customDockWidgets.count( title ) == 0 )
        {
675 676 677
            // create new custom dock widget
            widget = boost::shared_ptr< WQtCustomDockWidget >(
                new WQtCustomDockWidget( title, this, ocdwEvent->getProjectionMode() ) );
678 679 680 681 682 683 684
            addDockWidget( Qt::BottomDockWidgetArea, widget.get() );

            // store it in CustomDockWidget list
            m_customDockWidgets.insert( make_pair( title, widget ) );
        }
        else
        {
685 686
            widget = m_customDockWidgets[title];
            widget->increaseUseCount();
687
        }
688
        //m_customDockWidgetsLock.unlock();
689 690

        ocdwEvent->getFlag()->set( widget );
691 692 693 694 695 696 697 698
    }
    else
    {
        // other event
        QMainWindow::customEvent( event );
    }
}

699 700 701 702 703 704 705 706 707 708 709 710 711
bool WMainWindow::event( QEvent* event )
{
    // a module got associated with the root container -> add it to the list
    if ( event->type() == WQT_READY_EVENT )
    {
        // convert event to ready event
        WModuleReadyEvent* e1 = dynamic_cast< WModuleReadyEvent* >( event );     // NOLINT
        if ( e1 )
        {
            moduleSpecificSetup( e1->getModule() );
        }
    }

712 713 714 715 716 717
    if ( event->type() == WQT_CRASH_EVENT )
    {
        // convert event to ready event
        WModuleCrashEvent* e1 = dynamic_cast< WModuleCrashEvent* >( event );     // NOLINT
        if ( e1 )
        {
718
            QString title = "Problem in module: " + QString::fromStdString( e1->getModule()->getName() );
719 720 721 722 723 724 725 726
            QString description = "<b>Module Problem</b><br/><br/><b>Module:  </b>" + QString::fromStdString( e1->getModule()->getName() );

            QString message = QString::fromStdString( e1->getMessage() );
            QMessageBox msgBox;
            msgBox.setText( description );
            msgBox.setInformativeText( message  );
            msgBox.setStandardButtons( QMessageBox::Ok );
            msgBox.exec();
727 728 729
        }
    }

730 731 732
    return QMainWindow::event( event );
}

733 734 735 736 737 738
boost::shared_ptr< WQtCustomDockWidget > WMainWindow::getCustomDockWidget( std::string title )
{
    boost::mutex::scoped_lock lock( m_customDockWidgetsLock );
    boost::shared_ptr< WQtCustomDockWidget > out = m_customDockWidgets.count( title ) > 0 ?
        m_customDockWidgets[title] :
        boost::shared_ptr< WQtCustomDockWidget >();
739
    //m_customDockWidgetsLock.unlock();
740 741 742 743
    return out;
}


744 745 746
void WMainWindow::closeCustomDockWidget( std::string title )
{
    boost::mutex::scoped_lock lock( m_customDockWidgetsLock );
747
    if( m_customDockWidgets.count( title ) > 0 )
748
    {
749 750 751 752 753
        if( m_customDockWidgets[title]->decreaseUseCount() )
        {
            // custom dock widget should be deleted
            m_customDockWidgets.erase( title );
        }
754
    }
755
    //m_customDockWidgetsLock.unlock();
756 757
}

schurade's avatar
schurade committed
758 759
void WMainWindow::newRoi()
{
Mathias Goldau's avatar
[MERGE]  
Mathias Goldau committed
760
    // do nothing if we can not get
761
    if( !WKernel::getRunningKernel()->getRoiManager()->getBitField() )
Mathias Goldau's avatar
[MERGE]  
Mathias Goldau committed
762
    {
763
        wlog::warn( "WMainWindow" ) << "Refused to add ROI, as ROIManager does not have computed its bitfield yet.";
Mathias Goldau's avatar
[MERGE]  
Mathias Goldau committed
764 765 766
        return;
    }

767 768 769 770
    wmath::WPosition crossHairPos = WKernel::getRunningKernel()->getSelectionManager()->getCrosshair()->getPosition();
    wmath::WPosition minROIPos = crossHairPos - wmath::WPosition( 10., 10., 10. );
    wmath::WPosition maxROIPos = crossHairPos + wmath::WPosition( 10., 10., 10. );

schurade's avatar
schurade committed
771
    if ( m_datasetBrowser->getFirstRoiInSelectedBranch().get() == NULL )
schurade's avatar
schurade committed
772
    {
773
        osg::ref_ptr< WROIBox > newRoi = osg::ref_ptr< WROIBox >( new WROIBox( minROIPos, maxROIPos ) );
schurade's avatar
schurade committed
774 775 776 777
        WKernel::getRunningKernel()->getRoiManager()->addRoi( newRoi );
    }
    else
    {
778
        osg::ref_ptr< WROIBox > newRoi = osg::ref_ptr< WROIBox >( new WROIBox( minROIPos, maxROIPos ) );
schurade's avatar
schurade committed
779
        WKernel::getRunningKernel()->getRoiManager()->addRoi( newRoi, m_datasetBrowser->getFirstRoiInSelectedBranch()->getROI() );
schurade's avatar
schurade committed
780 781
    }
}
782 783 784 785 786

void WMainWindow::setFibersLoaded()
{
    m_fibLoaded = true;
}
787 788 789 790 791 792 793

void WMainWindow::openConfigDialog()
{
    m_configWidget = boost::shared_ptr< WQtConfigWidget >( new WQtConfigWidget );

    m_configWidget->initAndShow();
}