WMainWindow.cpp 41.5 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>
Mathias Goldau's avatar
Mathias Goldau committed
26
#include <map>
27 28
#include <string>
#include <vector>
29

30 31
#include <boost/thread.hpp>

32
#include <QtGui/QApplication>
33
#include <QtGui/QCloseEvent>
wiebel's avatar
wiebel committed
34
#include <QtGui/QDockWidget>
35
#include <QtGui/QFileDialog>
36
#include <QtGui/QIcon>
Mathias Goldau's avatar
Mathias Goldau committed
37 38
#include <QtGui/QMenu>
#include <QtGui/QMenuBar>
39
#include <QtGui/QMessageBox>
40 41
#include <QtGui/QTextEdit>
#include <QtWebKit/QWebView>
42
#include <QtGui/QShortcut>
Mathias Goldau's avatar
Mathias Goldau committed
43
#include <QtGui/QSlider>
44
#include <QtGui/QVBoxLayout>
45
#include <QtGui/QWidget>
46
#include <QtCore/QSettings>
47

48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
#include "core/common/WColor.h"
#include "core/common/WPreferences.h"
#include "core/common/WIOTools.h"
#include "core/common/WProjectFileIO.h"
#include "core/common/WPathHelper.h"
#include "core/dataHandler/WDataSetFibers.h"
#include "core/dataHandler/WDataSetSingle.h"
#include "core/dataHandler/WEEG2.h"
#include "core/graphicsEngine/WGEZoomTrackballManipulator.h"
#include "core/graphicsEngine/WROIBox.h"
#include "core/kernel/modules/data/WMData.h"
#include "core/kernel/WKernel.h"
#include "core/kernel/WModule.h"
#include "core/kernel/WModuleCombiner.h"
#include "core/kernel/WModuleCombinerTypes.h"
#include "core/kernel/WProjectFile.h"
#include "core/kernel/WROIManager.h"
#include "core/kernel/WSelectionManager.h"
66
#include "../icons/WIcons.xpm"
67
#include "controlPanel/WPropertyBoolWidget.h"
68
#include "controlPanel/WQtControlPanel.h"
Mathias Goldau's avatar
Mathias Goldau committed
69 70 71
#include "events/WEventTypes.h"
#include "events/WModuleCrashEvent.h"
#include "events/WModuleReadyEvent.h"
72
#include "events/WModuleRemovedEvent.h"
73
#include "events/WOpenCustomDockWidgetEvent.h"
Sebastian Eichelbaum's avatar
[MERGE]  
Sebastian Eichelbaum committed
74
#include "guiElements/WQtPropertyBoolAction.h"
75
#include "WQtCombinerToolbar.h"
Mathias Goldau's avatar
Mathias Goldau committed
76 77
#include "WQtCustomDockWidget.h"
#include "WQtNavGLWidget.h"
78
#include "WQtGLDockWidget.h"
Mathias Goldau's avatar
Mathias Goldau committed
79 80

#include "WMainWindow.h"
81

82
WMainWindow::WMainWindow() :
83
    QMainWindow(),
84
    m_currentCompatiblesToolbar( NULL ),
85 86
    m_iconManager(),
    m_navSlicesAlreadyLoaded( false )
Sebastian Eichelbaum's avatar
Sebastian Eichelbaum committed
87 88
{
}
89

90 91 92 93 94
WMainWindow::~WMainWindow()
{
    // cleanup
}

95
void WMainWindow::setupGUI()
96
{
97
    m_iconManager.addIcon( std::string( "load" ), fileopen_xpm );
98
    m_iconManager.addIcon( std::string( "loadProject" ), projOpen_xpm );
99
    m_iconManager.addIcon( std::string( "saveProject" ), projSave_xpm );
100
    m_iconManager.addIcon( std::string( "logo" ), logoIcon_xpm );
101
    m_iconManager.addIcon( std::string( "help" ), question_xpm );
102
    m_iconManager.addIcon( std::string( "quit" ), quit_xpm );
103 104 105
    m_iconManager.addIcon( std::string( "moduleBusy" ), moduleBusy_xpm );
    m_iconManager.addIcon( std::string( "moduleCrashed" ), moduleCrashed_xpm );
    m_iconManager.addIcon( std::string( "remove" ), remove_xpm );
106
    m_iconManager.addIcon( std::string( "config" ), preferences_system_xpm );
107
    m_iconManager.addIcon( std::string( "view" ), camera_xpm );
108

109
    if( objectName().isEmpty() )
110
    {
111
        setObjectName( QString::fromUtf8( "MainWindow" ) );
112
    }
113
    // TODO(all): what is this?
114 115
    resize( 946, 632 );
    setWindowIcon( m_iconManager.getIcon( "logo" ) );
116
    setWindowTitle( QApplication::translate( "MainWindow", "OpenWalnut (development version)", 0, QApplication::UnicodeUTF8 ) );
117

118 119
    setDockOptions( QMainWindow::AnimatedDocks |  QMainWindow::AllowNestedDocks | QMainWindow::AllowTabbedDocks );

120 121 122
    //network Editor
    m_networkEditor = new WQtNetworkEditor( this );
    m_networkEditor->setFeatures( QDockWidget::AllDockWidgetFeatures );
123

124 125 126 127
    // the control panel instance is needed for the menu
    m_controlPanel = new WQtControlPanel( this );
    m_controlPanel->setFeatures( QDockWidget::AllDockWidgetFeatures );
    m_controlPanel->addSubject( "Default Subject" );
128

129 130 131 132 133
    // add all docks
    addDockWidget( Qt::RightDockWidgetArea, m_controlPanel->getModuleDock() );
    addDockWidget( Qt::RightDockWidgetArea, m_networkEditor );
    tabifyDockWidget( m_networkEditor, m_controlPanel->getModuleDock() );

134
    addDockWidget( Qt::RightDockWidgetArea, m_controlPanel->getColormapperDock() );
135
    addDockWidget( Qt::RightDockWidgetArea, m_controlPanel->getRoiDock() );
136
    tabifyDockWidget( m_controlPanel->getColormapperDock(), m_controlPanel->getRoiDock() );
137 138 139

    addDockWidget( Qt::RightDockWidgetArea, m_controlPanel );

140 141 142 143 144 145 146 147
    m_glDock = new QMainWindow();
    m_glDock->setDockOptions( QMainWindow::AnimatedDocks |  QMainWindow::AllowNestedDocks | QMainWindow::AllowTabbedDocks );
    m_glDock->setDocumentMode( true );
    setCentralWidget( m_glDock );
    WQtGLDockWidget* mainGLDock = new WQtGLDockWidget( "main", "3D View", m_glDock );
    mainGLDock->getGLWidget()->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding );
    m_mainGLWidget = mainGLDock->getGLWidget();
    m_glDock->addDockWidget( Qt::RightDockWidgetArea, mainGLDock );
148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178

    m_permanentToolBar = new WQtToolBar( "Permanent Toolbar", this );

    // Set the style of the toolbar
    // NOTE: this only works if the toolbar is used with QActions instead of buttons and other widgets
    m_permanentToolBar->setToolButtonStyle( getToolbarStyle() );

    m_iconManager.addIcon( std::string( "ROI icon" ), box_xpm );
    m_iconManager.addIcon( std::string( "Reset icon" ), o_xpm );
    m_iconManager.addIcon( std::string( "axial icon" ), axial_xpm );
    m_iconManager.addIcon( std::string( "coronal icon" ), cor_xpm );
    m_iconManager.addIcon( std::string( "sagittal icon" ), sag_xpm );

    m_loadButton = new QAction( m_iconManager.getIcon( "load" ), "load", m_permanentToolBar );
    QAction* roiButton = new QAction( m_iconManager.getIcon( "ROI icon" ), "ROI", m_permanentToolBar );
    QAction* resetButton = new QAction( m_iconManager.getIcon( "view" ), "Reset", m_permanentToolBar );
    resetButton->setShortcut( QKeySequence( Qt::Key_Escape ) );
    QAction* projectLoadButton = new QAction( m_iconManager.getIcon( "loadProject" ), "loadProject", m_permanentToolBar );
    QAction* projectSaveButton = new QAction( m_iconManager.getIcon( "saveProject" ), "saveProject", m_permanentToolBar );

    connect( m_loadButton, SIGNAL(  triggered( bool ) ), this, SLOT( openLoadDialog() ) );
    connect( resetButton, SIGNAL(  triggered( bool ) ), m_mainGLWidget.get(), SLOT( reset() ) );
    connect( roiButton, SIGNAL(  triggered( bool ) ), this, SLOT( newRoi() ) );
    connect( projectLoadButton, SIGNAL(  triggered( bool ) ), this, SLOT( projectLoad() ) );
    connect( projectSaveButton, SIGNAL( triggered( bool ) ), this, SLOT( projectSaveAll() ) );

    m_loadButton->setToolTip( "Load Data" );
    resetButton->setToolTip( "Reset main view" );
    roiButton->setToolTip( "Create New ROI" );
    projectLoadButton->setToolTip( "Load a project from file" );
    projectSaveButton->setToolTip( "Save current project to file" );
179 180 181

    // we want the upper most tree item to be selected. This helps to make the always compatible modules
    // show up in the tool bar from the beginning. And ... it doesn't hurt.
182
    m_controlPanel->selectUpperMostEntry();
183

Sebastian Eichelbaum's avatar
Sebastian Eichelbaum committed
184 185 186 187
    // NOTE: Please be aware that not every menu needs a shortcut key. If you add a shortcut, you should use one of the
    // QKeySequence::StandardKey defaults and avoid ambiguities like Ctrl-C for the configure dialog is not the best choice as Ctrl-C, for the
    // most users is the Copy shortcut.

188
    m_menuBar = new QMenuBar( this );
189 190 191 192 193 194

    // hide menu?
    bool hideMenu = false;
    WPreferences::getPreference( "qt4gui.hideMenuBar", &hideMenu );
    m_menuBar->setVisible( !hideMenu );

195
    QMenu* fileMenu = m_menuBar->addMenu( "File" );
196

Sebastian Eichelbaum's avatar
Sebastian Eichelbaum committed
197 198
    fileMenu->addAction( m_iconManager.getIcon( "load" ), "Load Dataset", this, SLOT( openLoadDialog() ), QKeySequence(  QKeySequence::Open ) );
    fileMenu->addSeparator();
199
    fileMenu->addAction( m_iconManager.getIcon( "loadProject" ), "Load Project", this, SLOT( projectLoad() ) );
200 201
    QMenu* saveMenu = fileMenu->addMenu( m_iconManager.getIcon( "saveProject" ), "Save Project" );
    saveMenu->addAction( "Save Project", this, SLOT( projectSaveAll() ), QKeySequence::Save );
Sebastian Eichelbaum's avatar
Sebastian Eichelbaum committed
202 203 204
    saveMenu->addAction( "Save Modules Only", this, SLOT( projectSaveModuleOnly() ) );
    saveMenu->addAction( "Save Camera Only", this, SLOT( projectSaveCameraOnly() ) );
    saveMenu->addAction( "Save ROIs Only", this, SLOT( projectSaveROIOnly() ) );
205 206
    projectSaveButton->setMenu( saveMenu );

Sebastian Eichelbaum's avatar
Sebastian Eichelbaum committed
207
    fileMenu->addSeparator();
208
    fileMenu->addAction( m_iconManager.getIcon( "config" ), "Config", this, SLOT( openConfigDialog() ) );
Sebastian Eichelbaum's avatar
Sebastian Eichelbaum committed
209
    fileMenu->addSeparator();
210 211 212
    // TODO(all): If all distributions provide a newer QT version we should use QKeySequence::Quit here
    //fileMenu->addAction( m_iconManager.getIcon( "quit" ), "Quit", this, SLOT( close() ), QKeySequence( QKeySequence::Quit ) );
    fileMenu->addAction( m_iconManager.getIcon( "quit" ), "Quit", this, SLOT( close() ),  QKeySequence( Qt::CTRL + Qt::Key_Q ) );
Sebastian Eichelbaum's avatar
Sebastian Eichelbaum committed
213

Sebastian Eichelbaum's avatar
Sebastian Eichelbaum committed
214
    // This QAction stuff is quite ugly and complicated some times ... There is no nice constructor which takes name, slot keysequence and so on
215 216
    // directly -> set shortcuts, and some further properties using QAction's interface
    QMenu* viewMenu = m_menuBar->addMenu( "View" );
217

218 219 220 221 222
    QAction* controlPanelTrigger = m_controlPanel->toggleViewAction();
    QList< QKeySequence > controlPanelShortcut;
    controlPanelShortcut.append( QKeySequence( Qt::Key_F9 ) );
    controlPanelTrigger->setShortcuts( controlPanelShortcut );
    this->addAction( controlPanelTrigger );  // this enables the action even if the menu bar is invisible
223

Sebastian Eichelbaum's avatar
Sebastian Eichelbaum committed
224 225 226
    // NOTE: the shortcuts for these view presets should be chosen carefully. Most keysequences have another meaning in the most applications
    // so the user may get confused. It is also not a good idea to take letters as they might be used by OpenSceneGraph widget ( like "S" for
    // statistics ).
227
    // By additionally adding the action to the main window, we ensure the action can be triggered even if the menu bar is hidden.
228 229
    QAction* tmpAction = viewMenu->addAction( m_iconManager.getIcon( "sagittal icon" ), "Left", this, SLOT( setPresetViewLeft() ),
                                             QKeySequence( Qt::CTRL + Qt::SHIFT + Qt::Key_L ) );
Mathias Goldau's avatar
[MERGE]  
Mathias Goldau committed
230
    tmpAction->setIconVisibleInMenu( true );
231 232 233 234
    this->addAction( tmpAction );

    tmpAction = viewMenu->addAction( m_iconManager.getIcon( "sagittal icon" ), "Right", this, SLOT( setPresetViewRight() ),
                                     QKeySequence( Qt::CTRL + Qt::SHIFT + Qt::Key_R ) );
Mathias Goldau's avatar
[MERGE]  
Mathias Goldau committed
235
    tmpAction->setIconVisibleInMenu( true );
236 237 238 239
    this->addAction( tmpAction );

    tmpAction = viewMenu->addAction( m_iconManager.getIcon( "axial icon" ), "Superior", this, SLOT( setPresetViewSuperior() ),
                                     QKeySequence( Qt::CTRL + Qt::SHIFT + Qt::Key_S ) );
Mathias Goldau's avatar
[MERGE]  
Mathias Goldau committed
240
    tmpAction->setIconVisibleInMenu( true );
241 242 243 244
    this->addAction( tmpAction );

    tmpAction = viewMenu->addAction( m_iconManager.getIcon( "axial icon" ), "Inferior", this, SLOT( setPresetViewInferior() ),
                                     QKeySequence( Qt::CTRL + Qt::SHIFT + Qt::Key_I ) );
Mathias Goldau's avatar
[MERGE]  
Mathias Goldau committed
245
    tmpAction->setIconVisibleInMenu( true );
246 247 248 249
    this->addAction( tmpAction );

    tmpAction = viewMenu->addAction( m_iconManager.getIcon( "coronal icon" ), "Anterior", this, SLOT( setPresetViewAnterior() ),
                                     QKeySequence( Qt::CTRL + Qt::SHIFT + Qt::Key_A ) );
Mathias Goldau's avatar
[MERGE]  
Mathias Goldau committed
250
    tmpAction->setIconVisibleInMenu( true );
251 252 253 254
    this->addAction( tmpAction );

    tmpAction = viewMenu->addAction( m_iconManager.getIcon( "coronal icon" ), "Posterior", this, SLOT( setPresetViewPosterior() ),
                                     QKeySequence( Qt::CTRL + Qt::SHIFT + Qt::Key_P ) );
Mathias Goldau's avatar
[MERGE]  
Mathias Goldau committed
255
    tmpAction->setIconVisibleInMenu( true );
256 257 258
    this->addAction( tmpAction );

    resetButton->setMenu( viewMenu );
259

260
    QMenu* helpMenu = m_menuBar->addMenu( "Help" );
261
    helpMenu->addAction( m_iconManager.getIcon( "help" ), "OpenWalnut Help", this, SLOT( openOpenWalnutHelpDialog() ),
262 263 264 265
                         QKeySequence( QKeySequence::HelpContents ) );
    helpMenu->addSeparator();
    helpMenu->addAction( m_iconManager.getIcon( "logo" ), "About OpenWalnut", this, SLOT( openAboutDialog() ) );
    helpMenu->addAction( "About Qt", this, SLOT( openAboutQtDialog() ) );
266

267 268
    setMenuBar( m_menuBar );

269 270 271 272 273
    // initially 3 navigation views
    {
        bool hideWidget;
        if( !( WPreferences::getPreference( "qt4gui.hideAxial", &hideWidget ) && hideWidget) )
        {
ledig's avatar
ledig committed
274
#ifndef _MSC_VER
275 276
            m_navAxial = boost::shared_ptr< WQtNavGLWidget >( new WQtNavGLWidget( "Axial View", "Axial View", this, "Axial Slice",
                                                                                  m_mainGLWidget.get() ) );
ledig's avatar
ledig committed
277
#else
278
            m_navAxial = boost::shared_ptr< WQtNavGLWidget >( new WQtNavGLWidget( "Axial View", "Axial View", this, "Axial Slice" ) );
ledig's avatar
ledig committed
279
#endif
280
            m_navAxial->setFeatures( QDockWidget::AllDockWidgetFeatures );
281
            m_glDock->addDockWidget( Qt::LeftDockWidgetArea, m_navAxial.get() );
282 283 284
        }
        if( !( WPreferences::getPreference( "qt4gui.hideCoronal", &hideWidget ) && hideWidget) )
        {
ledig's avatar
ledig committed
285
#ifndef _MSC_VER
286 287
            m_navCoronal = boost::shared_ptr< WQtNavGLWidget >( new WQtNavGLWidget( "Coronal View", "Coronal View", this, "Coronal Slice",
                                                                                    m_mainGLWidget.get() ) );
ledig's avatar
ledig committed
288
#else
289
            m_navCoronal = boost::shared_ptr< WQtNavGLWidget >( new WQtNavGLWidget( "Coronal View", "Coronal View", this, "Coronal Slice" ) );
ledig's avatar
ledig committed
290
#endif
291
            m_navCoronal->setFeatures( QDockWidget::AllDockWidgetFeatures );
292
            m_glDock->addDockWidget( Qt::LeftDockWidgetArea, m_navCoronal.get() );
293 294 295
        }
        if( !( WPreferences::getPreference( "qt4gui.hideSagittal", &hideWidget ) && hideWidget) )
        {
ledig's avatar
ledig committed
296
#ifndef _MSC_VER
297
            m_navSagittal =
298 299
                boost::shared_ptr< WQtNavGLWidget >( new WQtNavGLWidget( "Sagittal View", "Sagittal View", this, "Sagittal Slice",
                                                                         m_mainGLWidget.get() ) );
ledig's avatar
ledig committed
300 301
#else
            m_navSagittal =
302
                boost::shared_ptr< WQtNavGLWidget >( new WQtNavGLWidget( "Sagittal View", "Sagittal View", this, "Sagittal Slice" ) );
ledig's avatar
ledig committed
303
#endif
304
            m_navSagittal->setFeatures( QDockWidget::AllDockWidgetFeatures );
305
            m_glDock->addDockWidget( Qt::LeftDockWidgetArea, m_navSagittal.get() );
306 307
        }
    }
308

309
    // Default background color from config file
310 311 312 313 314 315 316 317 318 319
    WColor bgColor( 1.0, 1.0, 1.0, 1.0 );
    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.set( r, g, b, 1.0 );
        m_mainGLWidget->setBgColor( bgColor );
320

321 322 323
        if( m_navAxial )
        {
            m_navAxial->getGLWidget()->setBgColor( bgColor );
324
        }
325 326 327
        if( m_navCoronal )
        {
            m_navCoronal->getGLWidget()->setBgColor( bgColor );
328
        }
329 330 331 332 333 334
        if( m_navSagittal )
        {
            m_navSagittal->getGLWidget()->setBgColor( bgColor );
        }
    }

335 336 337 338 339
    // create command prompt toolbar
    m_commandPrompt = new WQtCommandPromptToolbar( "Command Prompt", this );
    addToolBar( Qt::TopToolBarArea, m_commandPrompt );
    this->addAction( m_commandPrompt->toggleViewAction() );  // this enables the action even if the menu bar is invisible

340
    // setup permanent toolbar
341
    m_permanentToolBar->addAction( m_loadButton );
342
    m_permanentToolBar->addSeparator();
343 344
    m_permanentToolBar->addAction( projectLoadButton );
    m_permanentToolBar->addAction( projectSaveButton );
345
    m_permanentToolBar->addSeparator();
346 347
    m_permanentToolBar->addAction( resetButton );
    m_permanentToolBar->addAction( roiButton );
348
    m_permanentToolBar->addSeparator();
349

350
    addToolBar( Qt::TopToolBarArea, m_permanentToolBar );
351 352 353

    // after creating the GUI, restore its saved state
    restoreSavedState();
354
}
355

356 357 358
void WMainWindow::autoAdd( boost::shared_ptr< WModule > module, std::string proto )
{
    // get the prototype.
Alexander Wiebel's avatar
Alexander Wiebel committed
359
    if( !WKernel::getRunningKernel()->getRootContainer()->applyModule( module, proto, true ) )
360 361 362 363 364 365
    {
        WLogger::getLogger()->addLogMessage( "Auto Display active but module " + proto + " could not be added.",
                                             "GUI", LL_ERROR );
    }
}

366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383
void WMainWindow::moduleSpecificCleanup( boost::shared_ptr< WModule > module )
{
    // nav slices use separate buttons for slice on/off switching
    if( module->getName() == "Navigation Slices" )
    {
        boost::shared_ptr< WPropertyBase > prop;

        prop = module->getProperties()->findProperty( "showAxial" );
        m_permanentToolBar->removeAction( propertyActionMap[prop] );
        propertyActionMap.erase( prop );

        prop = module->getProperties()->findProperty( "showCoronal" );
        m_permanentToolBar->removeAction( propertyActionMap[prop] );
        propertyActionMap.erase( prop );

        prop = module->getProperties()->findProperty( "showSagittal" );
        m_permanentToolBar->removeAction( propertyActionMap[prop] );
        propertyActionMap.erase( prop );
384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402


        prop = module->getProperties()->findProperty( "Axial Slice" );
        if( m_navAxial )
        {
            m_navAxial->removeSliderProperty( prop );
        }

        prop = module->getProperties()->findProperty( "Coronal Slice" );
        if( m_navCoronal )
        {
            m_navCoronal->removeSliderProperty( prop );
        }

        prop = module->getProperties()->findProperty( "Sagittal Slice" );
        if( m_navSagittal )
        {
            m_navSagittal->removeSliderProperty( prop );
        }
403 404 405
    }
}

406 407
void WMainWindow::moduleSpecificSetup( boost::shared_ptr< WModule > module )
{
408 409 410 411 412 413
    // 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 );
Alexander Wiebel's avatar
Alexander Wiebel committed
414
    if( useAutoDisplay && module->getType() == MODULE_DATA )
415 416 417 418 419 420 421 422 423
    {
        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
Alexander Wiebel's avatar
Alexander Wiebel committed
424
        if( dataModule->getDataSet()->isA< WDataSetSingle >() && dataModule->getDataSet()->isTexture() )
425 426 427
        {
            // it is a dataset single
            // load a nav slice module if a WDataSetSingle is available!?
428
            if ( !m_navSlicesAlreadyLoaded )
429
            {
430
                autoAdd( module, "Navigation Slices" );
431
                m_navSlicesAlreadyLoaded = true;
432
            }
433
        }
Alexander Wiebel's avatar
Alexander Wiebel committed
434
        else if( dataModule->getDataSet()->isA< WDataSetFibers >() )
435 436
        {
            // it is a fiber dataset -> add the FiberDisplay module
437
            autoAdd( module, "Fiber Display" );
438
        }
Alexander Wiebel's avatar
Alexander Wiebel committed
439
        else if( dataModule->getDataSet()->isA< WEEG2 >() )
440
        {
441
            // it is a eeg dataset -> add the eegView module
442 443 444 445
            autoAdd( module, "EEG View" );
        }
    }

446
    // nav slices use separate buttons for slice on/off switching
Alexander Wiebel's avatar
Alexander Wiebel committed
447
    if( module->getName() == "Navigation Slices" )
448
    {
449
        boost::shared_ptr< WPropertyBase > prop = module->getProperties()->findProperty( "Slices/Show Axial" );
Alexander Wiebel's avatar
Alexander Wiebel committed
450
        if( !prop )
451 452
        {
               WLogger::getLogger()->
453
                   addLogMessage( "Navigation Slices module does not provide the property \"Show Axial\", which is required by the GUI.", "GUI",
454 455 456 457
                                  LL_ERROR );
        }
        else
        {
458 459 460
            WQtPropertyBoolAction* a = new WQtPropertyBoolAction( prop->toPropBool(), m_permanentToolBar );
            a->setToolTip( "Toggle Axial Slice" );
            a->setText( "Toggle Axial Slice" );
461
            a->setIcon( m_iconManager.getIcon( "axial icon" ) );
462
            m_permanentToolBar->addAction( a );
463
            propertyActionMap[prop] = a;
464
        }
465

466
        prop = module->getProperties()->findProperty( "Slices/Show Coronal" );
Alexander Wiebel's avatar
Alexander Wiebel committed
467
        if( !prop )
468 469
        {
               WLogger::getLogger()->
470
                   addLogMessage( "Navigation Slices module does not provide the property \"Show Coronal\", which is required by the GUI.", "GUI",
471 472 473 474
                                  LL_ERROR );
        }
        else
        {
475 476 477
            WQtPropertyBoolAction* a = new WQtPropertyBoolAction( prop->toPropBool(), m_permanentToolBar );
            a->setToolTip( "Toggle Coronal Slice" );
            a->setText( "Toggle Coronal Slice" );
478
            a->setIcon( m_iconManager.getIcon( "coronal icon" ) );
479
            m_permanentToolBar->addAction( a );
480
            propertyActionMap[prop] = a;
481
        }
482

483
        prop = module->getProperties()->findProperty( "Slices/Show Sagittal" );
Alexander Wiebel's avatar
Alexander Wiebel committed
484
        if( !prop )
485 486
        {
               WLogger::getLogger()->
487
                   addLogMessage( "Navigation Slices module does not provide the property \"Show Sagittal\", which is required by the GUI.", "GUI",
488 489 490 491
                                  LL_ERROR );
        }
        else
        {
492 493 494
            WQtPropertyBoolAction* a = new WQtPropertyBoolAction( prop->toPropBool(), m_permanentToolBar );
            a->setToolTip( "Toggle Saggital Slice" );
            a->setText( "Toggle Saggital Slice" );
495
            a->setIcon( m_iconManager.getIcon( "sagittal icon" ) );
496
            m_permanentToolBar->addAction( a );
497
            propertyActionMap[prop] = a;
498
        }
499 500

        // now setup the nav widget sliders
501
        prop = module->getProperties()->findProperty( "Slices/Axial Position" );
Alexander Wiebel's avatar
Alexander Wiebel committed
502
        if( !prop )
503 504
        {
               WLogger::getLogger()->
Sebastian Eichelbaum's avatar
[STYLE]  
Sebastian Eichelbaum committed
505
               addLogMessage( "Navigation Slices module does not provide the property \"Axial Position\", which is required by the GUI.", "GUI",
506 507 508 509
                                  LL_ERROR );
        }
        else
        {
510 511
            if( m_navAxial )
            {
512
                //m_navAxial->setSliderProperty( prop );
513
            }
514 515
        }

516
        prop = module->getProperties()->findProperty( "Slices/Coronal Position" );
Alexander Wiebel's avatar
Alexander Wiebel committed
517
        if( !prop )
518 519
        {
               WLogger::getLogger()->
Sebastian Eichelbaum's avatar
[STYLE]  
Sebastian Eichelbaum committed
520
               addLogMessage( "Navigation Slices module does not provide the property \"Coronal Position\", which is required by the GUI.", "GUI",
521 522 523 524
                                  LL_ERROR );
        }
        else
        {
525 526
            if( m_navCoronal )
            {
527
                //m_navCoronal->setSliderProperty( prop );
528
            }
529 530
        }

531
        prop = module->getProperties()->findProperty( "Slices/Sagittal Position" );
Alexander Wiebel's avatar
Alexander Wiebel committed
532
        if( !prop )
533 534
        {
               WLogger::getLogger()->
Sebastian Eichelbaum's avatar
[STYLE]  
Sebastian Eichelbaum committed
535
               addLogMessage( "Navigation Slices module does not provide the property \"Sagittal Position\", which is required by the GUI.", "GUI",
536 537 538 539
                                  LL_ERROR );
        }
        else
        {
540 541
            if( m_navSagittal )
            {
542
               //m_navSagittal->setSliderProperty( prop );
543
            }
544
        }
545
    }
wiebel's avatar
wiebel committed
546
}
547

548 549 550 551 552
Qt::ToolButtonStyle WMainWindow::getToolbarStyle() const
{
    // this sets the toolbar style
    int toolBarStyle = 0;
    WPreferences::getPreference( "qt4gui.toolBarStyle", &toolBarStyle );
Alexander Wiebel's avatar
Alexander Wiebel committed
553
    if( ( toolBarStyle < 0 ) || ( toolBarStyle > 3 ) ) // ensure a valid value
554 555 556 557 558 559 560 561
    {
        toolBarStyle = 0;
    }

    // cast and return
    return static_cast< Qt::ToolButtonStyle >( toolBarStyle );
}

562 563
void WMainWindow::setCompatiblesToolbar( WQtCombinerToolbar* toolbar )
{
Alexander Wiebel's avatar
Alexander Wiebel committed
564
    if( m_currentCompatiblesToolbar )
565 566 567 568 569
    {
        delete m_currentCompatiblesToolbar;
    }
    m_currentCompatiblesToolbar = toolbar;

Alexander Wiebel's avatar
Alexander Wiebel committed
570
    if( !toolbar )
571 572 573
    {
        // ok, reset the toolbar
        // So create a dummy to permanently reserve the space
574
        m_currentCompatiblesToolbar = new WQtCombinerToolbar( this );
575 576 577
    }

    // and the position of the toolbar
578
    addToolBar( Qt::TopToolBarArea, m_currentCompatiblesToolbar );
579
}
580

581 582 583 584 585
WQtCombinerToolbar* WMainWindow::getCompatiblesToolbar()
{
    return m_currentCompatiblesToolbar;
}

586
WQtControlPanel* WMainWindow::getControlPanel()
587
{
588
    return m_controlPanel;
589
}
590

591 592 593 594 595
WQtNetworkEditor* WMainWindow::getNetworkEditor()
{
    return m_networkEditor;
}

596
void WMainWindow::projectSave( const std::vector< boost::shared_ptr< WProjectFileIO > >& writer )
597 598 599 600
{
    QFileDialog fd;
    fd.setWindowTitle( "Save Project as" );
    fd.setFileMode( QFileDialog::AnyFile );
601
    fd.setAcceptMode( QFileDialog::AcceptSave );
602 603

    QStringList filters;
604
    filters << "Project File (*.owproj *.owp)";
605 606 607
    fd.setNameFilters( filters );
    fd.setViewMode( QFileDialog::Detail );
    QStringList fileNames;
Alexander Wiebel's avatar
Alexander Wiebel committed
608
    if( fd.exec() )
609 610 611 612 613
    {
        fileNames = fd.selectedFiles();
    }

    QStringList::const_iterator constIterator;
Alexander Wiebel's avatar
Alexander Wiebel committed
614
    for( constIterator = fileNames.constBegin(); constIterator != fileNames.constEnd(); ++constIterator )
615
    {
616 617 618 619 620 621 622
        std::string filename = ( *constIterator ).toStdString();
        // append owp if not existent
        if ( filename.rfind( ".owp" ) == std::string::npos )
        {
            filename += ".owp";
        }

623
        boost::shared_ptr< WProjectFile > proj = boost::shared_ptr< WProjectFile >(
624
                new WProjectFile( filename )
625 626
        );

627 628 629
        try
        {
            // This call is synchronous.
Alexander Wiebel's avatar
Alexander Wiebel committed
630
            if( writer.empty() )
631 632 633 634 635 636 637
            {
                proj->save();
            }
            else
            {
                proj->save( writer );
            }
638 639 640 641 642 643 644 645
        }
        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 );
        }
646 647 648
    }
}

649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669
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 );
}

670 671 672 673 674 675 676
void WMainWindow::projectSaveModuleOnly()
{
    std::vector< boost::shared_ptr< WProjectFileIO > > w;
    w.push_back( WProjectFile::getModuleWriter() );
    projectSave( w );
}

677 678 679 680 681 682
void WMainWindow::projectLoad()
{
    QFileDialog fd;
    fd.setFileMode( QFileDialog::ExistingFiles );

    QStringList filters;
683
    filters << "Simple Project File (*.owproj *.owp)"
684 685 686 687
            << "Any files (*)";
    fd.setNameFilters( filters );
    fd.setViewMode( QFileDialog::Detail );
    QStringList fileNames;
Alexander Wiebel's avatar
Alexander Wiebel committed
688
    if( fd.exec() )
689 690 691 692 693
    {
        fileNames = fd.selectedFiles();
    }

    QStringList::const_iterator constIterator;
Alexander Wiebel's avatar
Alexander Wiebel committed
694
    for( constIterator = fileNames.constBegin(); constIterator != fileNames.constEnd(); ++constIterator )
695
    {
696 697
        boost::shared_ptr< WProjectFile > proj = boost::shared_ptr< WProjectFile >(
                new WProjectFile( ( *constIterator ).toStdString() )
698
        );
699 700

        // This call is asynchronous. It parses the file and the starts a thread to actually do all the stuff
701
        proj->load();
702 703 704
    }
}

705
void WMainWindow::openLoadDialog()
706
{
707 708 709 710 711 712 713 714 715 716 717
#ifdef _MSC_VER
    QStringList fileNames;
    QString filters;
    filters = QString::fromStdString( std::string( "Known file types (*.cnt *.edf *.asc *.nii *.nii.gz *.fib);;" )
        + std::string( "EEG files (*.cnt *.edf *.asc);;" )
        + std::string( "NIfTI (*.nii *.nii.gz);;" )
        + std::string( "Fibers (*.fib);;" )
        + std::string( "Any files (*)" ) );

    fileNames = QFileDialog::getOpenFileNames( this, "Open", "", filters  );
#else
718 719
    QFileDialog fd;
    fd.setFileMode( QFileDialog::ExistingFiles );
wiebel's avatar
wiebel committed
720 721

    QStringList filters;
722 723
    filters << "Known file types (*.cnt *.edf *.asc *.nii *.nii.gz *.fib)"
            << "EEG files (*.cnt *.edf *.asc)"
wiebel's avatar
wiebel committed
724
            << "NIfTI (*.nii *.nii.gz)"
725 726
            << "Fibers (*.fib)"
            << "Any files (*)";
wiebel's avatar
wiebel committed
727
    fd.setNameFilters( filters );
728 729
    fd.setViewMode( QFileDialog::Detail );
    QStringList fileNames;
Alexander Wiebel's avatar
Alexander Wiebel committed
730
    if( fd.exec() )
731 732 733
    {
        fileNames = fd.selectedFiles();
    }
734
#endif
735

736
    std::vector< std::string > stdFileNames;
737 738

    QStringList::const_iterator constIterator;
Alexander Wiebel's avatar
Alexander Wiebel committed
739
    for( constIterator = fileNames.constBegin(); constIterator != fileNames.constEnd(); ++constIterator )
740 741 742
    {
        stdFileNames.push_back( ( *constIterator ).toLocal8Bit().constData() );
    }
743

744
    m_loaderSignal( stdFileNames );
745
}
746

747 748 749 750
void WMainWindow::openAboutQtDialog()
{
    QMessageBox::aboutQt( this, "About Qt" );
}
751

752 753
void WMainWindow::openAboutDialog()
{
754
    std::string filename( WPathHelper::getAppPath().file_string() + "/../share/OpenWalnut/OpenWalnutAbout.html" );
755
    std::string content = readFileIntoString( filename );
756
    QMessageBox::about( this, "About OpenWalnut", content.c_str() );
757 758
}

759
void WMainWindow::openOpenWalnutHelpDialog()
760
{
761
    std::string filename( WPathHelper::getAppPath().file_string() + "/../share/OpenWalnut/OpenWalnutHelp.html" );
762
    std::string content = readFileIntoString( filename );
763 764

    QWidget* window = new QWidget( this, Qt::Window );
765

766 767
    // specify intial layout
    QVBoxLayout *layout = new QVBoxLayout( window );
768
    window->setLayout( layout );
769 770 771 772 773
    window->resize( 500, 500 );

    window->show();

    QWebView *view = new QWebView( this );
774 775
    QString location( QString( "file://" ) + WPathHelper::getAppPath().file_string().c_str() + "/../share/OpenWalnut/" );
    view->setHtml( content.c_str(), QUrl( location  ) );
776 777
    view->show();
    layout->addWidget( view );
778 779
}

780 781 782 783
void WMainWindow::setPresetViewLeft()
{
    boost::shared_ptr< WGEViewer > viewer;
    viewer = WKernel::getRunningKernel()->getGraphicsEngine()->getViewerByName( "main" );
schurade's avatar
schurade committed
784 785 786
    osg::ref_ptr<osgGA::TrackballManipulator>  cm = osg::dynamic_pointer_cast<osgGA::TrackballManipulator>( viewer->getCameraManipulator() );
    osg::Quat q( 0.5, -0.5, -0.5, 0.5 );
    cm->setRotation( q );
787 788 789 790 791 792
}

void WMainWindow::setPresetViewRight()
{
    boost::shared_ptr< WGEViewer > viewer;
    viewer = WKernel::getRunningKernel()->getGraphicsEngine()->getViewerByName( "main" );
schurade's avatar
schurade committed
793 794 795
    osg::ref_ptr<osgGA::TrackballManipulator>  cm = osg::dynamic_pointer_cast<osgGA::TrackballManipulator>( viewer->getCameraManipulator() );
    osg::Quat q( -0.5, -0.5, -0.5, -0.5 );
    cm->setRotation( q );
796 797 798 799 800 801
}

void WMainWindow::setPresetViewSuperior()
{
    boost::shared_ptr< WGEViewer > viewer;
    viewer = WKernel::getRunningKernel()->getGraphicsEngine()->getViewerByName( "main" );
schurade's avatar
schurade committed
802 803 804
    osg::ref_ptr<osgGA::TrackballManipulator>  cm = osg::dynamic_pointer_cast<osgGA::TrackballManipulator>( viewer->getCameraManipulator() );
    osg::Quat q( 0., 0., 0., 1 );
    cm->setRotation( q );
805 806 807 808 809 810
}

void WMainWindow::setPresetViewInferior()
{
    boost::shared_ptr< WGEViewer > viewer;
    viewer = WKernel::getRunningKernel()->getGraphicsEngine()->getViewerByName( "main" );
schurade's avatar
schurade committed
811 812 813
    osg::ref_ptr<osgGA::TrackballManipulator>  cm = osg::dynamic_pointer_cast<osgGA::TrackballManipulator>( viewer->getCameraManipulator() );
    osg::Quat q( 0., -1., 0., 0. );
    cm->setRotation( q );
814 815 816 817 818 819
}

void WMainWindow::setPresetViewAnterior()
{
    boost::shared_ptr< WGEViewer > viewer;
    viewer = WKernel::getRunningKernel()->getGraphicsEngine()->getViewerByName( "main" );