WMainWindow.cpp 41 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
#include "WMainWindow.moc"
82

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

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

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

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

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

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

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

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

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

    addDockWidget( Qt::RightDockWidgetArea, m_controlPanel );

141 142 143 144 145 146 147 148
    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 );
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 179

    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" );
180 181 182

    // 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.
183
    m_controlPanel->selectUpperMostEntry();
184

Sebastian Eichelbaum's avatar
Sebastian Eichelbaum committed
185 186 187 188
    // 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.

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

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

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

Sebastian Eichelbaum's avatar
Sebastian Eichelbaum committed
198 199
    fileMenu->addAction( m_iconManager.getIcon( "load" ), "Load Dataset", this, SLOT( openLoadDialog() ), QKeySequence(  QKeySequence::Open ) );
    fileMenu->addSeparator();
200
    fileMenu->addAction( m_iconManager.getIcon( "loadProject" ), "Load Project", this, SLOT( projectLoad() ) );
201 202
    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
203 204 205
    saveMenu->addAction( "Save Modules Only", this, SLOT( projectSaveModuleOnly() ) );
    saveMenu->addAction( "Save Camera Only", this, SLOT( projectSaveCameraOnly() ) );
    saveMenu->addAction( "Save ROIs Only", this, SLOT( projectSaveROIOnly() ) );
206 207
    projectSaveButton->setMenu( saveMenu );

Sebastian Eichelbaum's avatar
Sebastian Eichelbaum committed
208
    fileMenu->addSeparator();
209
    fileMenu->addAction( m_iconManager.getIcon( "config" ), "Config", this, SLOT( openConfigDialog() ) );
Sebastian Eichelbaum's avatar
Sebastian Eichelbaum committed
210
    fileMenu->addSeparator();
211 212 213
    // 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
214

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

219 220 221 222 223
    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
224

Sebastian Eichelbaum's avatar
Sebastian Eichelbaum committed
225 226 227
    // 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 ).
228
    // By additionally adding the action to the main window, we ensure the action can be triggered even if the menu bar is hidden.
229 230
    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
231
    tmpAction->setIconVisibleInMenu( true );
232 233 234 235
    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
236
    tmpAction->setIconVisibleInMenu( true );
237 238 239 240
    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
241
    tmpAction->setIconVisibleInMenu( true );
242 243 244 245
    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
246
    tmpAction->setIconVisibleInMenu( true );
247 248 249 250
    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
251
    tmpAction->setIconVisibleInMenu( true );
252 253 254 255
    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
256
    tmpAction->setIconVisibleInMenu( true );
257 258 259
    this->addAction( tmpAction );

    resetButton->setMenu( viewMenu );
260

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

268 269
    setMenuBar( m_menuBar );

270 271 272 273 274
    // initially 3 navigation views
    {
        bool hideWidget;
        if( !( WPreferences::getPreference( "qt4gui.hideAxial", &hideWidget ) && hideWidget) )
        {
Sebastian Eichelbaum's avatar
[STYLE]  
Sebastian Eichelbaum committed
275
            m_navAxial = boost::shared_ptr< WQtNavGLWidget >( new WQtNavGLWidget( "Axial View", "Axial View", this, "Axial Slice",
276
                                                                                  m_mainGLWidget.get() ) );
277
            m_navAxial->setFeatures( QDockWidget::AllDockWidgetFeatures );
278
            m_glDock->addDockWidget( Qt::LeftDockWidgetArea, m_navAxial.get() );
279 280 281
        }
        if( !( WPreferences::getPreference( "qt4gui.hideCoronal", &hideWidget ) && hideWidget) )
        {
282 283
            m_navCoronal = boost::shared_ptr< WQtNavGLWidget >( new WQtNavGLWidget( "Coronal View", "Coronal View", this, "Coronal Slice",
                                                                                    m_mainGLWidget.get() ) );
284
            m_navCoronal->setFeatures( QDockWidget::AllDockWidgetFeatures );
285
            m_glDock->addDockWidget( Qt::LeftDockWidgetArea, m_navCoronal.get() );
286 287 288
        }
        if( !( WPreferences::getPreference( "qt4gui.hideSagittal", &hideWidget ) && hideWidget) )
        {
289
            m_navSagittal =
290 291
                boost::shared_ptr< WQtNavGLWidget >( new WQtNavGLWidget( "Sagittal View", "Sagittal View", this, "Sagittal Slice",
                                                                         m_mainGLWidget.get() ) );
292
            m_navSagittal->setFeatures( QDockWidget::AllDockWidgetFeatures );
293
            m_glDock->addDockWidget( Qt::LeftDockWidgetArea, m_navSagittal.get() );
294 295
        }
    }
296

297
    // Default background color from config file
298 299 300 301 302 303 304 305 306 307
    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 );
308

309 310 311
        if( m_navAxial )
        {
            m_navAxial->getGLWidget()->setBgColor( bgColor );
312
        }
313 314 315
        if( m_navCoronal )
        {
            m_navCoronal->getGLWidget()->setBgColor( bgColor );
316
        }
317 318 319 320 321 322
        if( m_navSagittal )
        {
            m_navSagittal->getGLWidget()->setBgColor( bgColor );
        }
    }

323 324 325 326 327
    // 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

328
    // setup permanent toolbar
329
    m_permanentToolBar->addAction( m_loadButton );
330
    m_permanentToolBar->addSeparator();
331 332
    m_permanentToolBar->addAction( projectLoadButton );
    m_permanentToolBar->addAction( projectSaveButton );
333
    m_permanentToolBar->addSeparator();
334 335
    m_permanentToolBar->addAction( resetButton );
    m_permanentToolBar->addAction( roiButton );
336
    m_permanentToolBar->addSeparator();
337

338
    addToolBar( Qt::TopToolBarArea, m_permanentToolBar );
339 340 341

    // after creating the GUI, restore its saved state
    restoreSavedState();
342
}
343

344 345 346
void WMainWindow::autoAdd( boost::shared_ptr< WModule > module, std::string proto )
{
    // get the prototype.
Alexander Wiebel's avatar
Alexander Wiebel committed
347
    if( !WKernel::getRunningKernel()->getRootContainer()->applyModule( module, proto, true ) )
348 349 350 351 352 353
    {
        WLogger::getLogger()->addLogMessage( "Auto Display active but module " + proto + " could not be added.",
                                             "GUI", LL_ERROR );
    }
}

354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371
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 );
372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390


        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 );
        }
391 392 393
    }
}

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

434
    // nav slices use separate buttons for slice on/off switching
Alexander Wiebel's avatar
Alexander Wiebel committed
435
    if( module->getName() == "Navigation Slices" )
436
    {
437
        boost::shared_ptr< WPropertyBase > prop = module->getProperties()->findProperty( "Slices/Show Axial" );
Alexander Wiebel's avatar
Alexander Wiebel committed
438
        if( !prop )
439 440
        {
               WLogger::getLogger()->
441
                   addLogMessage( "Navigation Slices module does not provide the property \"Show Axial\", which is required by the GUI.", "GUI",
442 443 444 445
                                  LL_ERROR );
        }
        else
        {
446 447 448
            WQtPropertyBoolAction* a = new WQtPropertyBoolAction( prop->toPropBool(), m_permanentToolBar );
            a->setToolTip( "Toggle Axial Slice" );
            a->setText( "Toggle Axial Slice" );
449
            a->setIcon( m_iconManager.getIcon( "axial icon" ) );
450
            m_permanentToolBar->addAction( a );
451
            propertyActionMap[prop] = a;
452
        }
453

454
        prop = module->getProperties()->findProperty( "Slices/Show Coronal" );
Alexander Wiebel's avatar
Alexander Wiebel committed
455
        if( !prop )
456 457
        {
               WLogger::getLogger()->
458
                   addLogMessage( "Navigation Slices module does not provide the property \"Show Coronal\", which is required by the GUI.", "GUI",
459 460 461 462
                                  LL_ERROR );
        }
        else
        {
463 464 465
            WQtPropertyBoolAction* a = new WQtPropertyBoolAction( prop->toPropBool(), m_permanentToolBar );
            a->setToolTip( "Toggle Coronal Slice" );
            a->setText( "Toggle Coronal Slice" );
466
            a->setIcon( m_iconManager.getIcon( "coronal icon" ) );
467
            m_permanentToolBar->addAction( a );
468
            propertyActionMap[prop] = a;
469
        }
470

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

        // now setup the nav widget sliders
489
        prop = module->getProperties()->findProperty( "Slices/Axial Position" );
Alexander Wiebel's avatar
Alexander Wiebel committed
490
        if( !prop )
491 492
        {
               WLogger::getLogger()->
Sebastian Eichelbaum's avatar
[STYLE]  
Sebastian Eichelbaum committed
493
               addLogMessage( "Navigation Slices module does not provide the property \"Axial Position\", which is required by the GUI.", "GUI",
494 495 496 497
                                  LL_ERROR );
        }
        else
        {
498 499
            if( m_navAxial )
            {
500
                //m_navAxial->setSliderProperty( prop );
501
            }
502 503
        }

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

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

536 537 538 539 540
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
541
    if( ( toolBarStyle < 0 ) || ( toolBarStyle > 3 ) ) // ensure a valid value
542 543 544 545 546 547 548 549
    {
        toolBarStyle = 0;
    }

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

550 551
void WMainWindow::setCompatiblesToolbar( WQtCombinerToolbar* toolbar )
{
Alexander Wiebel's avatar
Alexander Wiebel committed
552
    if( m_currentCompatiblesToolbar )
553 554 555 556 557
    {
        delete m_currentCompatiblesToolbar;
    }
    m_currentCompatiblesToolbar = toolbar;

Alexander Wiebel's avatar
Alexander Wiebel committed
558
    if( !toolbar )
559 560 561
    {
        // ok, reset the toolbar
        // So create a dummy to permanently reserve the space
562
        m_currentCompatiblesToolbar = new WQtCombinerToolbar( this );
563 564 565
    }

    // and the position of the toolbar
566
    addToolBar( Qt::TopToolBarArea, m_currentCompatiblesToolbar );
567
}
568

569 570 571 572 573
WQtCombinerToolbar* WMainWindow::getCompatiblesToolbar()
{
    return m_currentCompatiblesToolbar;
}

574
WQtControlPanel* WMainWindow::getControlPanel()
575
{
576
    return m_controlPanel;
577
}
578

579 580 581 582 583
WQtNetworkEditor* WMainWindow::getNetworkEditor()
{
    return m_networkEditor;
}

584
void WMainWindow::projectSave( const std::vector< boost::shared_ptr< WProjectFileIO > >& writer )
585 586 587 588
{
    QFileDialog fd;
    fd.setWindowTitle( "Save Project as" );
    fd.setFileMode( QFileDialog::AnyFile );
589
    fd.setAcceptMode( QFileDialog::AcceptSave );
590 591

    QStringList filters;
592
    filters << "Project File (*.owproj *.owp)";
593 594 595
    fd.setNameFilters( filters );
    fd.setViewMode( QFileDialog::Detail );
    QStringList fileNames;
Alexander Wiebel's avatar
Alexander Wiebel committed
596
    if( fd.exec() )
597 598 599 600 601
    {
        fileNames = fd.selectedFiles();
    }

    QStringList::const_iterator constIterator;
Alexander Wiebel's avatar
Alexander Wiebel committed
602
    for( constIterator = fileNames.constBegin(); constIterator != fileNames.constEnd(); ++constIterator )
603
    {
604 605
        std::string filename = ( *constIterator ).toStdString();
        // append owp if not existent
606
        if( filename.rfind( ".owp" ) == std::string::npos )
607 608 609 610
        {
            filename += ".owp";
        }

611
        boost::shared_ptr< WProjectFile > proj = boost::shared_ptr< WProjectFile >(
612
                new WProjectFile( filename )
613 614
        );

615 616 617
        try
        {
            // This call is synchronous.
Alexander Wiebel's avatar
Alexander Wiebel committed
618
            if( writer.empty() )
619 620 621 622 623 624 625
            {
                proj->save();
            }
            else
            {
                proj->save( writer );
            }
626 627 628 629 630 631 632 633
        }
        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 );
        }
634 635 636
    }
}

637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657
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 );
}

658 659 660 661 662 663 664
void WMainWindow::projectSaveModuleOnly()
{
    std::vector< boost::shared_ptr< WProjectFileIO > > w;
    w.push_back( WProjectFile::getModuleWriter() );
    projectSave( w );
}

665 666 667 668 669 670
void WMainWindow::projectLoad()
{
    QFileDialog fd;
    fd.setFileMode( QFileDialog::ExistingFiles );

    QStringList filters;
671
    filters << "Simple Project File (*.owproj *.owp)"
672 673 674 675
            << "Any files (*)";
    fd.setNameFilters( filters );
    fd.setViewMode( QFileDialog::Detail );
    QStringList fileNames;
Alexander Wiebel's avatar
Alexander Wiebel committed
676
    if( fd.exec() )
677 678 679 680 681
    {
        fileNames = fd.selectedFiles();
    }

    QStringList::const_iterator constIterator;
Alexander Wiebel's avatar
Alexander Wiebel committed
682
    for( constIterator = fileNames.constBegin(); constIterator != fileNames.constEnd(); ++constIterator )
683
    {
684 685
        boost::shared_ptr< WProjectFile > proj = boost::shared_ptr< WProjectFile >(
                new WProjectFile( ( *constIterator ).toStdString() )
686
        );
687 688

        // This call is asynchronous. It parses the file and the starts a thread to actually do all the stuff
689
        proj->load();
690 691 692
    }
}

693
void WMainWindow::openLoadDialog()
694
{
695 696 697 698 699 700 701 702 703 704 705
#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
706 707
    QFileDialog fd;
    fd.setFileMode( QFileDialog::ExistingFiles );
wiebel's avatar
wiebel committed
708 709

    QStringList filters;
710 711
    filters << "Known file types (*.cnt *.edf *.asc *.nii *.nii.gz *.fib)"
            << "EEG files (*.cnt *.edf *.asc)"
wiebel's avatar
wiebel committed
712
            << "NIfTI (*.nii *.nii.gz)"
713 714
            << "Fibers (*.fib)"
            << "Any files (*)";
wiebel's avatar
wiebel committed
715
    fd.setNameFilters( filters );
716 717
    fd.setViewMode( QFileDialog::Detail );
    QStringList fileNames;
Alexander Wiebel's avatar
Alexander Wiebel committed
718
    if( fd.exec() )
719 720 721
    {
        fileNames = fd.selectedFiles();
    }
722
#endif
723

724
    std::vector< std::string > stdFileNames;
725 726

    QStringList::const_iterator constIterator;
Alexander Wiebel's avatar
Alexander Wiebel committed
727
    for( constIterator = fileNames.constBegin(); constIterator != fileNames.constEnd(); ++constIterator )
728 729 730
    {
        stdFileNames.push_back( ( *constIterator ).toLocal8Bit().constData() );
    }
731

732
    m_loaderSignal( stdFileNames );
733
}
734

735 736 737 738
void WMainWindow::openAboutQtDialog()
{
    QMessageBox::aboutQt( this, "About Qt" );
}
739

740 741
void WMainWindow::openAboutDialog()
{
742
    std::string filename( WPathHelper::getDocPath().file_string() + "/qt4gui/OpenWalnutAbout.html" );
743
    std::string content = readFileIntoString( filename );
744
    QMessageBox::about( this, "About OpenWalnut", content.c_str() );
745 746
}

747
void WMainWindow::openOpenWalnutHelpDialog()
748
{
749
    std::string filename( WPathHelper::getDocPath().file_string() + "/qt4gui/OpenWalnutHelp.html" );
750
    std::string content = readFileIntoString( filename );
751 752

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

754 755
    // specify intial layout
    QVBoxLayout *layout = new QVBoxLayout( window );
756
    window->setLayout( layout );
757 758 759 760 761
    window->resize( 500, 500 );

    window->show();

    QWebView *view = new QWebView( this );
762
    QString location( QString( "file://" ) + WPathHelper::getDocPath().file_string().c_str() + "/qt4gui/" );
763
    view->setHtml( content.c_str(), QUrl( location  ) );
764 765
    view->show();
    layout->addWidget( view );
766 767
}

768 769 770 771
void WMainWindow::setPresetViewLeft()
{
    boost::shared_ptr< WGEViewer > viewer;
    viewer = WKernel::getRunningKernel()->getGraphicsEngine()->getViewerByName( "main" );
schurade's avatar
schurade committed
772 773 774
    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 );
775 776 777 778 779 780
}

void WMainWindow::setPresetViewRight()
{
    boost::shared_ptr< WGEViewer > viewer;
    viewer = WKernel::getRunningKernel()->getGraphicsEngine()->getViewerByName( "main" );
schurade's avatar
schurade committed
781 782 783
    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 );
784 785 786 787 788 789
}

void WMainWindow::setPresetViewSuperior()
{
    boost::shared_ptr< WGEViewer > viewer;
    viewer = WKernel::getRunningKernel()->getGraphicsEngine()->getViewerByName( "main" );
schurade's avatar
schurade committed
790 791 792
    osg::ref_ptr<osgGA::TrackballManipulator>  cm = osg::dynamic_pointer_cast<osgGA::TrackballManipulator>( viewer->getCameraManipulator() );
    osg::Quat q( 0., 0., 0., 1 );
    cm->setRotation( q );
793 794 795 796 797 798
}

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

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

void WMainWindow::setPresetViewPosterior()
{
    boost::shared_ptr< WGEViewer > viewer;
    viewer = WKernel::getRunningKernel()->getGraphicsEngine()->getViewerByName( "main" );
schurade's avatar
schurade committed
817 818 819
    osg::ref_ptr<osgGA::TrackballManipulator>  cm = osg::dynamic_pointer_cast<osgGA::TrackballManipulator>( viewer->getCameraManipulator() );
    osg::Quat q( 0.707107, 0., 0., 0.707107 );
    cm->setRotation( q );
820 821
}

822 823 824 825