WMainWindow.cpp 43.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
#include <QtGui/QInputDialog>
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/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"
79
#include "WQt4Gui.h"
80
#include "WSettingAction.h"
81
#include "WSettingMenu.h"
Mathias Goldau's avatar
Mathias Goldau committed
82 83

#include "WMainWindow.h"
84
#include "WMainWindow.moc"
85

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

94 95 96 97 98
WMainWindow::~WMainWindow()
{
    // cleanup
}

99
void WMainWindow::setupGUI()
100
{
101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133
    /////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // Setting setup
    /////////////////////////////////////////////////////////////////////////////////////////////////////////////////

    WSettingAction* hideMenuAction = new WSettingAction( this, "qt4gui/showMenu",
                                                               "Show Menubar",
                                                               "Allows you to hide the menu. Can be restored using CTRL-M.",
                                                               true,
                                                               false,
                                                               QKeySequence( Qt::CTRL + Qt::Key_M ) );

    WSettingAction* showNavWidgets = new WSettingAction( this, "qt4gui/showNavigationWidgets",
                                                               "Show Navigation Views",
                                                               "Disables the navigation views completely. This can lead to a speed-up and is "
                                                               "recommended for those who do not need them.",
                                                               true,
                                                               true    // this requires a restart
                                                       );
    m_autoDisplaySetting = new WSettingAction( this, "qt4gui/useAutoDisplay",
                                                     "Auto-Display",
                                                     "If enabled, the best matching module is automatically added if some data was loaded.",
                                                     true );

    WSettingAction* mtViews = new WSettingAction( this, "qt4gui/ge/multiThreadedViewer",
                                                        "Multi-threaded Views",
                                                        "If enabled, the graphic windows are rendered in different threads. This can speed-up "
                                                        "rendering on machines with multiple cores.",
                                                        false,
                                                        true // require restart
                                                );
    // NOTE: the multi-threading feature needs to be activated BEFORE the first viewer is created. To ensure this we do it here.
    WGraphicsEngine::getGraphicsEngine()->setMultiThreadedViews( mtViews->get() );

134 135 136 137 138 139 140 141 142 143 144 145 146 147 148
    // set the log-level setting.
    // NOTE: see WQt4Gui which reads the setting.
    QList< QString > logOptions;
    logOptions.push_back( "Debug" );
    logOptions.push_back( "Info" );
    logOptions.push_back( "Warning" );
    logOptions.push_back( "Error" );
    WSettingMenu* logLevels = new WSettingMenu( this, "qt4gui/logLevel",
                                                      "Log-Level",
                                                      "Allows to set the log verbosity.",
                                                      1,    // info is the default
                                                      logOptions
                                              );
    connect( logLevels, SIGNAL( change( unsigned int ) ), this, SLOT( handleLogLevelUpdate( unsigned int ) ) );

149 150 151 152
    /////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // GUI setup
    /////////////////////////////////////////////////////////////////////////////////////////////////////////////////

153
    m_iconManager.addIcon( std::string( "load" ), fileopen_xpm );
154
    m_iconManager.addIcon( std::string( "loadProject" ), projOpen_xpm );
155
    m_iconManager.addIcon( std::string( "saveProject" ), projSave_xpm );
156
    m_iconManager.addIcon( std::string( "logo" ), logoIcon_xpm );
157
    m_iconManager.addIcon( std::string( "help" ), question_xpm );
158
    m_iconManager.addIcon( std::string( "quit" ), quit_xpm );
159 160 161
    m_iconManager.addIcon( std::string( "moduleBusy" ), moduleBusy_xpm );
    m_iconManager.addIcon( std::string( "moduleCrashed" ), moduleCrashed_xpm );
    m_iconManager.addIcon( std::string( "remove" ), remove_xpm );
162
    m_iconManager.addIcon( std::string( "config" ), preferences_system_xpm );
163
    m_iconManager.addIcon( std::string( "view" ), camera_xpm );
164
    m_iconManager.addIcon( std::string( "missingModule" ), QuestionMarks_xpm );
165 166
    m_iconManager.addIcon( std::string( "none" ), empty_xpm );
    m_iconManager.addIcon( std::string( "DefaultModuleIcon" ), moduleDefault_xpm );
167

168
    if( objectName().isEmpty() )
169
    {
170
        setObjectName( QString::fromUtf8( "MainWindow" ) );
171
    }
172
    // TODO(all): what is this?
173 174
    resize( 946, 632 );
    setWindowIcon( m_iconManager.getIcon( "logo" ) );
175
    setWindowTitle( QApplication::translate( "MainWindow", "OpenWalnut (development version)", 0, QApplication::UnicodeUTF8 ) );
176

177 178
    setDockOptions( QMainWindow::AnimatedDocks |  QMainWindow::AllowNestedDocks | QMainWindow::AllowTabbedDocks );

179 180 181
    //network Editor
    m_networkEditor = new WQtNetworkEditor( this );
    m_networkEditor->setFeatures( QDockWidget::AllDockWidgetFeatures );
182

183 184 185 186
    // the control panel instance is needed for the menu
    m_controlPanel = new WQtControlPanel( this );
    m_controlPanel->setFeatures( QDockWidget::AllDockWidgetFeatures );
    m_controlPanel->addSubject( "Default Subject" );
187

188 189 190 191 192
    // add all docks
    addDockWidget( Qt::RightDockWidgetArea, m_controlPanel->getModuleDock() );
    addDockWidget( Qt::RightDockWidgetArea, m_networkEditor );
    tabifyDockWidget( m_networkEditor, m_controlPanel->getModuleDock() );

193
    addDockWidget( Qt::RightDockWidgetArea, m_controlPanel->getColormapperDock() );
194
    addDockWidget( Qt::RightDockWidgetArea, m_controlPanel->getRoiDock() );
195
    tabifyDockWidget( m_controlPanel->getColormapperDock(), m_controlPanel->getRoiDock() );
196 197 198

    addDockWidget( Qt::RightDockWidgetArea, m_controlPanel );

199
    m_glDock = new QMainWindow();
200
    m_glDock->setObjectName( "GLDock" );
201 202 203 204 205 206 207
    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 );
208

209
    m_permanentToolBar = new WQtToolBar( "Standard Toolbar", this );
210
    addToolBar( Qt::TopToolBarArea, m_permanentToolBar );
211 212 213 214 215 216 217

    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 );

218
    m_loadButton = new QAction( m_iconManager.getIcon( "load" ), "Load", m_permanentToolBar );
219 220 221
    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 ) );
222 223
    QAction* projectLoadButton = new QAction( m_iconManager.getIcon( "loadProject" ), "Load Project", m_permanentToolBar );
    QAction* projectSaveButton = new QAction( m_iconManager.getIcon( "saveProject" ), "Save Project", m_permanentToolBar );
224 225 226 227 228 229 230 231 232 233 234 235

    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" );
236 237 238

    // 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.
239
    m_controlPanel->selectUpperMostEntry();
240

Sebastian Eichelbaum's avatar
Sebastian Eichelbaum committed
241 242 243 244
    // 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.

245
    m_menuBar = new QMenuBar( this );
246 247

    // hide menu?
248 249 250
    m_menuBar->setVisible( hideMenuAction->get() );
    connect( hideMenuAction, SIGNAL( change( bool ) ), m_menuBar, SLOT( setVisible( bool ) ) );
    addAction( hideMenuAction );
251

252
    QMenu* fileMenu = m_menuBar->addMenu( "File" );
253

Sebastian Eichelbaum's avatar
Sebastian Eichelbaum committed
254 255
    fileMenu->addAction( m_iconManager.getIcon( "load" ), "Load Dataset", this, SLOT( openLoadDialog() ), QKeySequence(  QKeySequence::Open ) );
    fileMenu->addSeparator();
256
    fileMenu->addAction( m_iconManager.getIcon( "loadProject" ), "Load Project", this, SLOT( projectLoad() ) );
257 258
    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
259 260 261
    saveMenu->addAction( "Save Modules Only", this, SLOT( projectSaveModuleOnly() ) );
    saveMenu->addAction( "Save Camera Only", this, SLOT( projectSaveCameraOnly() ) );
    saveMenu->addAction( "Save ROIs Only", this, SLOT( projectSaveROIOnly() ) );
262 263
    projectSaveButton->setMenu( saveMenu );

264 265 266
    // 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
267

Sebastian Eichelbaum's avatar
Sebastian Eichelbaum committed
268
    // This QAction stuff is quite ugly and complicated some times ... There is no nice constructor which takes name, slot keysequence and so on
269 270
    // directly -> set shortcuts, and some further properties using QAction's interface
    QMenu* viewMenu = m_menuBar->addMenu( "View" );
271
    viewMenu->addAction( hideMenuAction );
272
    viewMenu->addSeparator();
273
    viewMenu->addAction( showNavWidgets );
274 275 276 277
    viewMenu->addSeparator();
    viewMenu->addMenu( m_permanentToolBar->getStyleMenu() );

    // Camera menu
278 279 280
    QMenu* bgColorMenu = new QMenu( "Background Colors" );
    bgColorMenu->addAction( mainGLDock->getGLWidget()->getBackgroundColorAction() );

281
    QMenu* cameraMenu = m_menuBar->addMenu( "Camera" );
282 283
    cameraMenu->addAction( mainGLDock->getGLWidget()->getThrowingSetting() );
    cameraMenu->addMenu( bgColorMenu );
284 285 286
    cameraMenu->addSeparator();

    QMenu* settingsMenu = m_menuBar->addMenu( "Settings" );
287
    settingsMenu->addAction( m_autoDisplaySetting );
288
    settingsMenu->addAction( m_controlPanel->getModuleExcluder().getConfigureAction() );
289
    settingsMenu->addSeparator();
290
    settingsMenu->addAction( mtViews );
291
    settingsMenu->addSeparator();
292
    settingsMenu->addMenu( logLevels );
293 294 295

    // a separate menu for some presets
    QMenu* cameraPresetMenu = cameraMenu->addMenu( "Presets" );
296

297 298 299 300 301
    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
302

Sebastian Eichelbaum's avatar
Sebastian Eichelbaum committed
303 304 305
    // 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 ).
306
    // By additionally adding the action to the main window, we ensure the action can be triggered even if the menu bar is hidden.
307
    QAction* tmpAction = cameraPresetMenu->addAction( m_iconManager.getIcon( "sagittal icon" ), "Left", this, SLOT( setPresetViewLeft() ),
308
                                             QKeySequence( Qt::CTRL + Qt::SHIFT + Qt::Key_L ) );
Mathias Goldau's avatar
[MERGE]  
Mathias Goldau committed
309
    tmpAction->setIconVisibleInMenu( true );
310 311
    this->addAction( tmpAction );

312 313
    tmpAction = cameraPresetMenu->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
314
    tmpAction->setIconVisibleInMenu( true );
315 316
    this->addAction( tmpAction );

317 318
    tmpAction = cameraPresetMenu->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
319
    tmpAction->setIconVisibleInMenu( true );
320 321
    this->addAction( tmpAction );

322 323
    tmpAction = cameraPresetMenu->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
324
    tmpAction->setIconVisibleInMenu( true );
325 326
    this->addAction( tmpAction );

327 328
    tmpAction = cameraPresetMenu->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
329
    tmpAction->setIconVisibleInMenu( true );
330 331
    this->addAction( tmpAction );

332 333
    tmpAction = cameraPresetMenu->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
334
    tmpAction->setIconVisibleInMenu( true );
335 336
    this->addAction( tmpAction );

337
    resetButton->setMenu( cameraPresetMenu );
338

339
    QMenu* helpMenu = m_menuBar->addMenu( "Help" );
340
    helpMenu->addAction( m_iconManager.getIcon( "help" ), "OpenWalnut Help", this, SLOT( openOpenWalnutHelpDialog() ),
341 342 343 344
                         QKeySequence( QKeySequence::HelpContents ) );
    helpMenu->addSeparator();
    helpMenu->addAction( m_iconManager.getIcon( "logo" ), "About OpenWalnut", this, SLOT( openAboutDialog() ) );
    helpMenu->addAction( "About Qt", this, SLOT( openAboutQtDialog() ) );
345

346 347
    setMenuBar( m_menuBar );

348 349
    // initially 3 navigation views
    {
350
        if( showNavWidgets->get() )
351
        {
Sebastian Eichelbaum's avatar
[STYLE]  
Sebastian Eichelbaum committed
352
            m_navAxial = boost::shared_ptr< WQtNavGLWidget >( new WQtNavGLWidget( "Axial View", "Axial View", this, "Axial Slice",
353
                                                                                  m_mainGLWidget.get() ) );
354
            m_navAxial->setFeatures( QDockWidget::AllDockWidgetFeatures );
355
            m_glDock->addDockWidget( Qt::LeftDockWidgetArea, m_navAxial.get() );
356

357 358
            m_navCoronal = boost::shared_ptr< WQtNavGLWidget >( new WQtNavGLWidget( "Coronal View", "Coronal View", this, "Coronal Slice",
                                                                                    m_mainGLWidget.get() ) );
359
            m_navCoronal->setFeatures( QDockWidget::AllDockWidgetFeatures );
360
            m_glDock->addDockWidget( Qt::LeftDockWidgetArea, m_navCoronal.get() );
361

362
            m_navSagittal =
363 364
                boost::shared_ptr< WQtNavGLWidget >( new WQtNavGLWidget( "Sagittal View", "Sagittal View", this, "Sagittal Slice",
                                                                         m_mainGLWidget.get() ) );
365
            m_navSagittal->setFeatures( QDockWidget::AllDockWidgetFeatures );
366
            m_glDock->addDockWidget( Qt::LeftDockWidgetArea, m_navSagittal.get() );
367 368 369 370

            bgColorMenu->addAction( m_navAxial->getGLWidget()->getBackgroundColorAction() );
            bgColorMenu->addAction( m_navCoronal->getGLWidget()->getBackgroundColorAction() );
            bgColorMenu->addAction( m_navSagittal->getGLWidget()->getBackgroundColorAction() );
371 372
        }
    }
373

374
    // Temporarily disabled. We need a proper command prompt implementation first.
375
    // create command prompt toolbar
376 377 378
    // 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
379

380
    // setup permanent toolbar
381
    m_permanentToolBar->addAction( m_loadButton );
382
    m_permanentToolBar->addSeparator();
383 384
    m_permanentToolBar->addAction( projectLoadButton );
    m_permanentToolBar->addAction( projectSaveButton );
385
    m_permanentToolBar->addSeparator();
386 387
    m_permanentToolBar->addAction( resetButton );
    m_permanentToolBar->addAction( roiButton );
388
    m_permanentToolBar->addSeparator();
389

390 391
    // after creating the GUI, restore its saved state
    restoreSavedState();
392
}
393

394 395 396
void WMainWindow::autoAdd( boost::shared_ptr< WModule > module, std::string proto )
{
    // get the prototype.
Alexander Wiebel's avatar
Alexander Wiebel committed
397
    if( !WKernel::getRunningKernel()->getRootContainer()->applyModule( module, proto, true ) )
398 399 400 401 402 403
    {
        WLogger::getLogger()->addLogMessage( "Auto Display active but module " + proto + " could not be added.",
                                             "GUI", LL_ERROR );
    }
}

404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421
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 );
422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440


        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 );
        }
441 442 443
    }
}

444 445
void WMainWindow::moduleSpecificSetup( boost::shared_ptr< WModule > module )
{
446 447 448 449
    // 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.
450
    bool useAutoDisplay = m_autoDisplaySetting->get();
Alexander Wiebel's avatar
Alexander Wiebel committed
451
    if( useAutoDisplay && module->getType() == MODULE_DATA )
452 453 454 455 456 457 458 459 460
    {
        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
461
        if( dataModule->getDataSet()->isA< WDataSetSingle >() && dataModule->getDataSet()->isTexture() )
462 463 464
        {
            // it is a dataset single
            // load a nav slice module if a WDataSetSingle is available!?
465
            if( !m_navSlicesAlreadyLoaded )
466
            {
467
                autoAdd( module, "Navigation Slices" );
468
                m_navSlicesAlreadyLoaded = true;
469
            }
470
        }
Alexander Wiebel's avatar
Alexander Wiebel committed
471
        else if( dataModule->getDataSet()->isA< WDataSetFibers >() )
472 473
        {
            // it is a fiber dataset -> add the FiberDisplay module
474
            autoAdd( module, "Fiber Display" );
475
        }
Alexander Wiebel's avatar
Alexander Wiebel committed
476
        else if( dataModule->getDataSet()->isA< WEEG2 >() )
477
        {
478
            // it is a eeg dataset -> add the eegView module
479 480 481 482
            autoAdd( module, "EEG View" );
        }
    }

483
    // nav slices use separate buttons for slice on/off switching
Alexander Wiebel's avatar
Alexander Wiebel committed
484
    if( module->getName() == "Navigation Slices" )
485
    {
486
        boost::shared_ptr< WPropertyBase > prop = module->getProperties()->findProperty( "Slices/Show Axial" );
Alexander Wiebel's avatar
Alexander Wiebel committed
487
        if( !prop )
488 489
        {
               WLogger::getLogger()->
490
                   addLogMessage( "Navigation Slices module does not provide the property \"Show Axial\", which is required by the GUI.", "GUI",
491 492 493 494
                                  LL_ERROR );
        }
        else
        {
495 496 497
            WQtPropertyBoolAction* a = new WQtPropertyBoolAction( prop->toPropBool(), m_permanentToolBar );
            a->setToolTip( "Toggle Axial Slice" );
            a->setText( "Toggle Axial Slice" );
498
            a->setIcon( m_iconManager.getIcon( "axial icon" ) );
499
            m_permanentToolBar->addAction( a );
500
            propertyActionMap[prop] = a;
501
        }
502

503
        prop = module->getProperties()->findProperty( "Slices/Show Coronal" );
Alexander Wiebel's avatar
Alexander Wiebel committed
504
        if( !prop )
505 506
        {
               WLogger::getLogger()->
507
                   addLogMessage( "Navigation Slices module does not provide the property \"Show Coronal\", which is required by the GUI.", "GUI",
508 509 510 511
                                  LL_ERROR );
        }
        else
        {
512 513 514
            WQtPropertyBoolAction* a = new WQtPropertyBoolAction( prop->toPropBool(), m_permanentToolBar );
            a->setToolTip( "Toggle Coronal Slice" );
            a->setText( "Toggle Coronal Slice" );
515
            a->setIcon( m_iconManager.getIcon( "coronal icon" ) );
516
            m_permanentToolBar->addAction( a );
517
            propertyActionMap[prop] = a;
518
        }
519

520
        prop = module->getProperties()->findProperty( "Slices/Show Sagittal" );
Alexander Wiebel's avatar
Alexander Wiebel committed
521
        if( !prop )
522 523
        {
               WLogger::getLogger()->
524
                   addLogMessage( "Navigation Slices module does not provide the property \"Show Sagittal\", which is required by the GUI.", "GUI",
525 526 527 528
                                  LL_ERROR );
        }
        else
        {
529 530 531
            WQtPropertyBoolAction* a = new WQtPropertyBoolAction( prop->toPropBool(), m_permanentToolBar );
            a->setToolTip( "Toggle Saggital Slice" );
            a->setText( "Toggle Saggital Slice" );
532
            a->setIcon( m_iconManager.getIcon( "sagittal icon" ) );
533
            m_permanentToolBar->addAction( a );
534
            propertyActionMap[prop] = a;
535
        }
536 537

        // now setup the nav widget sliders
538
        prop = module->getProperties()->findProperty( "Slices/Axial Position" );
Alexander Wiebel's avatar
Alexander Wiebel committed
539
        if( !prop )
540 541
        {
               WLogger::getLogger()->
Sebastian Eichelbaum's avatar
[STYLE]  
Sebastian Eichelbaum committed
542
               addLogMessage( "Navigation Slices module does not provide the property \"Axial Position\", which is required by the GUI.", "GUI",
543 544 545 546
                                  LL_ERROR );
        }
        else
        {
547 548
            if( m_navAxial )
            {
549
                //m_navAxial->setSliderProperty( prop );
550
            }
551 552
        }

553
        prop = module->getProperties()->findProperty( "Slices/Coronal Position" );
Alexander Wiebel's avatar
Alexander Wiebel committed
554
        if( !prop )
555 556
        {
               WLogger::getLogger()->
Sebastian Eichelbaum's avatar
[STYLE]  
Sebastian Eichelbaum committed
557
               addLogMessage( "Navigation Slices module does not provide the property \"Coronal Position\", which is required by the GUI.", "GUI",
558 559 560 561
                                  LL_ERROR );
        }
        else
        {
562 563
            if( m_navCoronal )
            {
564
                //m_navCoronal->setSliderProperty( prop );
565
            }
566 567
        }

568
        prop = module->getProperties()->findProperty( "Slices/Sagittal Position" );
Alexander Wiebel's avatar
Alexander Wiebel committed
569
        if( !prop )
570 571
        {
               WLogger::getLogger()->
Sebastian Eichelbaum's avatar
[STYLE]  
Sebastian Eichelbaum committed
572
               addLogMessage( "Navigation Slices module does not provide the property \"Sagittal Position\", which is required by the GUI.", "GUI",
573 574 575 576
                                  LL_ERROR );
        }
        else
        {
577 578
            if( m_navSagittal )
            {
579
               //m_navSagittal->setSliderProperty( prop );
580
            }
581
        }
582
    }
wiebel's avatar
wiebel committed
583
}
584

585 586
void WMainWindow::setCompatiblesToolbar( WQtCombinerToolbar* toolbar )
{
Alexander Wiebel's avatar
Alexander Wiebel committed
587
    if( m_currentCompatiblesToolbar )
588 589 590 591 592
    {
        delete m_currentCompatiblesToolbar;
    }
    m_currentCompatiblesToolbar = toolbar;

Alexander Wiebel's avatar
Alexander Wiebel committed
593
    if( !toolbar )
594 595 596
    {
        // ok, reset the toolbar
        // So create a dummy to permanently reserve the space
597
        m_currentCompatiblesToolbar = new WQtCombinerToolbar( this );
598 599
    }

600 601 602 603 604
    // we want to keep the tool-button styles in sync
    m_currentCompatiblesToolbar->setToolButtonStyle( m_permanentToolBar->toolButtonStyle() );
    connect( m_permanentToolBar, SIGNAL( toolButtonStyleChanged( Qt::ToolButtonStyle ) ),
             m_currentCompatiblesToolbar, SLOT( setToolButtonStyle( Qt::ToolButtonStyle ) ) );

605
    // and the position of the toolbar
606
    addToolBar( Qt::TopToolBarArea, m_currentCompatiblesToolbar );
607
}
608

609 610 611 612 613
WQtCombinerToolbar* WMainWindow::getCompatiblesToolbar()
{
    return m_currentCompatiblesToolbar;
}

614
WQtControlPanel* WMainWindow::getControlPanel()
615
{
616
    return m_controlPanel;
617
}
618

619 620 621 622 623
WQtNetworkEditor* WMainWindow::getNetworkEditor()
{
    return m_networkEditor;
}

624
void WMainWindow::projectSave( const std::vector< boost::shared_ptr< WProjectFileIO > >& writer )
625 626 627 628
{
    QFileDialog fd;
    fd.setWindowTitle( "Save Project as" );
    fd.setFileMode( QFileDialog::AnyFile );
629
    fd.setAcceptMode( QFileDialog::AcceptSave );
630 631

    QStringList filters;
632
    filters << "Project File (*.owproj *.owp)";
633 634 635
    fd.setNameFilters( filters );
    fd.setViewMode( QFileDialog::Detail );
    QStringList fileNames;
Alexander Wiebel's avatar
Alexander Wiebel committed
636
    if( fd.exec() )
637 638 639 640 641
    {
        fileNames = fd.selectedFiles();
    }

    QStringList::const_iterator constIterator;
Alexander Wiebel's avatar
Alexander Wiebel committed
642
    for( constIterator = fileNames.constBegin(); constIterator != fileNames.constEnd(); ++constIterator )
643
    {
644 645
        std::string filename = ( *constIterator ).toStdString();
        // append owp if not existent
646
        if( filename.rfind( ".owp" ) == std::string::npos )
647 648 649 650
        {
            filename += ".owp";
        }

651
        boost::shared_ptr< WProjectFile > proj = boost::shared_ptr< WProjectFile >(
652
                new WProjectFile( filename )
653 654
        );

655 656 657
        try
        {
            // This call is synchronous.
Alexander Wiebel's avatar
Alexander Wiebel committed
658
            if( writer.empty() )
659 660 661 662 663 664 665
            {
                proj->save();
            }
            else
            {
                proj->save( writer );
            }
666 667 668 669 670 671 672 673
        }
        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 );
        }
674 675 676
    }
}

677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697
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 );
}

698 699 700 701 702 703 704
void WMainWindow::projectSaveModuleOnly()
{
    std::vector< boost::shared_ptr< WProjectFileIO > > w;
    w.push_back( WProjectFile::getModuleWriter() );
    projectSave( w );
}

705 706 707 708 709 710
void WMainWindow::projectLoad()
{
    QFileDialog fd;
    fd.setFileMode( QFileDialog::ExistingFiles );

    QStringList filters;
711
    filters << "Simple Project File (*.owproj *.owp)"
712 713 714 715
            << "Any files (*)";
    fd.setNameFilters( filters );
    fd.setViewMode( QFileDialog::Detail );
    QStringList fileNames;
Alexander Wiebel's avatar
Alexander Wiebel committed
716
    if( fd.exec() )
717 718 719 720 721
    {
        fileNames = fd.selectedFiles();
    }

    QStringList::const_iterator constIterator;
Alexander Wiebel's avatar
Alexander Wiebel committed
722
    for( constIterator = fileNames.constBegin(); constIterator != fileNames.constEnd(); ++constIterator )
723
    {
724 725
        boost::shared_ptr< WProjectFile > proj = boost::shared_ptr< WProjectFile >(
                new WProjectFile( ( *constIterator ).toStdString() )
726
        );
727 728

        // This call is asynchronous. It parses the file and the starts a thread to actually do all the stuff
729
        proj->load();
730 731 732
    }
}

733
void WMainWindow::openLoadDialog()
734
{
735 736 737 738 739 740 741 742 743 744 745
#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
746 747
    QFileDialog fd;
    fd.setFileMode( QFileDialog::ExistingFiles );
wiebel's avatar
wiebel committed
748 749

    QStringList filters;
750 751
    filters << "Known file types (*.cnt *.edf *.asc *.nii *.nii.gz *.fib)"
            << "EEG files (*.cnt *.edf *.asc)"
wiebel's avatar
wiebel committed
752
            << "NIfTI (*.nii *.nii.gz)"
753 754
            << "Fibers (*.fib)"
            << "Any files (*)";
wiebel's avatar
wiebel committed
755
    fd.setNameFilters( filters );
756 757
    fd.setViewMode( QFileDialog::Detail );
    QStringList fileNames;
Alexander Wiebel's avatar
Alexander Wiebel committed
758
    if( fd.exec() )
759 760 761
    {
        fileNames = fd.selectedFiles();
    }
762
#endif
763

764
    std::vector< std::string > stdFileNames;
765 766

    QStringList::const_iterator constIterator;
Alexander Wiebel's avatar
Alexander Wiebel committed
767
    for( constIterator = fileNames.constBegin(); constIterator != fileNames.constEnd(); ++constIterator )
768 769 770
    {
        stdFileNames.push_back( ( *constIterator ).toLocal8Bit().constData() );
    }
771

772
    m_loaderSignal( stdFileNames );
773
}
774

775 776 777 778
void WMainWindow::openAboutQtDialog()
{
    QMessageBox::aboutQt( this, "About Qt" );
}
779

780 781
void WMainWindow::openAboutDialog()
{
782
    std::string filename( WPathHelper::getDocPath().file_string() + "/qt4gui/OpenWalnutAbout.html" );
783
    std::string content = readFileIntoString( filename );
784
    QMessageBox::about( this, "About OpenWalnut", content.c_str() );
785 786
}

787
void WMainWindow::openOpenWalnutHelpDialog()
788
{
789
    std::string filename( WPathHelper::getDocPath().file_string() + "/qt4gui/OpenWalnutHelp.html" );
Mathias Goldau's avatar