WMainWindow.cpp 41.7 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
#include <QtGui/QTextEdit>
41
#include <QtGui/QShortcut>
Mathias Goldau's avatar
Mathias Goldau committed
42
#include <QtGui/QSlider>
43
#include <QtGui/QVBoxLayout>
44
#include <QtGui/QWidget>
45
#include <QtCore/QSettings>
46
#include <QtGui/QInputDialog>
47

48 49 50 51
#ifndef QT4GUI_NOWEBKIT
    #include <QtWebKit/QWebView>
#endif

52 53 54 55 56 57 58 59 60
#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"
61
#include "core/kernel/WDataModule.h"
62 63 64 65 66 67 68
#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"
69
#include "../icons/WIcons.xpm"
70
#include "controlPanel/WPropertyBoolWidget.h"
71
#include "controlPanel/WQtControlPanel.h"
Mathias Goldau's avatar
Mathias Goldau committed
72 73 74
#include "events/WEventTypes.h"
#include "events/WModuleCrashEvent.h"
#include "events/WModuleReadyEvent.h"
75
#include "events/WModuleRemovedEvent.h"
76
#include "events/WOpenCustomDockWidgetEvent.h"
Sebastian Eichelbaum's avatar
[MERGE]  
Sebastian Eichelbaum committed
77
#include "guiElements/WQtPropertyBoolAction.h"
78
#include "WQtCombinerToolbar.h"
Mathias Goldau's avatar
Mathias Goldau committed
79 80
#include "WQtCustomDockWidget.h"
#include "WQtNavGLWidget.h"
81
#include "WQtGLDockWidget.h"
82
#include "WQt4Gui.h"
83
#include "WSettingAction.h"
84
#include "WSettingMenu.h"
Mathias Goldau's avatar
Mathias Goldau committed
85 86

#include "WMainWindow.h"
87
#include "WMainWindow.moc"
88

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

97 98 99 100 101
WMainWindow::~WMainWindow()
{
    // cleanup
}

102
void WMainWindow::setupGUI()
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 134 135 136
    /////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 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() );

137 138 139 140 141 142 143 144 145 146 147 148 149 150 151
    // 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 ) ) );

152 153 154 155
    /////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // GUI setup
    /////////////////////////////////////////////////////////////////////////////////////////////////////////////////

156
    m_iconManager.addIcon( std::string( "load" ), fileopen_xpm );
157
    m_iconManager.addIcon( std::string( "loadProject" ), projOpen_xpm );
158
    m_iconManager.addIcon( std::string( "saveProject" ), projSave_xpm );
Mathias Goldau's avatar
Mathias Goldau committed
159
    m_iconManager.addIcon( std::string( "logo" ), openwalnut_32x32_xpm );
160
    m_iconManager.addIcon( std::string( "help" ), question_xpm );
161
    m_iconManager.addIcon( std::string( "quit" ), quit_xpm );
162 163 164
    m_iconManager.addIcon( std::string( "moduleBusy" ), moduleBusy_xpm );
    m_iconManager.addIcon( std::string( "moduleCrashed" ), moduleCrashed_xpm );
    m_iconManager.addIcon( std::string( "remove" ), remove_xpm );
165
    m_iconManager.addIcon( std::string( "config" ), preferences_system_xpm );
166
    m_iconManager.addIcon( std::string( "view" ), camera_xpm );
167
    m_iconManager.addIcon( std::string( "missingModule" ), QuestionMarks_xpm );
168 169
    m_iconManager.addIcon( std::string( "none" ), empty_xpm );
    m_iconManager.addIcon( std::string( "DefaultModuleIcon" ), moduleDefault_xpm );
170

171
    if( objectName().isEmpty() )
172
    {
173
        setObjectName( QString::fromUtf8( "MainWindow" ) );
174
    }
175 176 177

    // NOTE: this only is an initial size. The state reloaded from QSettings will set it to the value the user had last session.
    resize( 800, 600 );
178
    setWindowIcon( m_iconManager.getIcon( "logo" ) );
179
    setWindowTitle( QApplication::translate( "MainWindow", "OpenWalnut (development version)", 0, QApplication::UnicodeUTF8 ) );
180

181 182
    setDockOptions( QMainWindow::AnimatedDocks |  QMainWindow::AllowNestedDocks | QMainWindow::AllowTabbedDocks );

183 184 185 186 187
#ifdef OW_QT4GUI_NETWORKEDITOR
    //network Editor
    m_networkEditor = new WQtNetworkEditor( this );
    m_networkEditor->setFeatures( QDockWidget::AllDockWidgetFeatures );
#endif
188

189 190 191 192
    // the control panel instance is needed for the menu
    m_controlPanel = new WQtControlPanel( this );
    m_controlPanel->setFeatures( QDockWidget::AllDockWidgetFeatures );
    m_controlPanel->addSubject( "Default Subject" );
193

194 195
    // add all docks
    addDockWidget( Qt::RightDockWidgetArea, m_controlPanel->getModuleDock() );
196 197 198
#ifdef OW_QT4GUI_NETWORKEDITOR
    addDockWidget( Qt::RightDockWidgetArea, m_networkEditor );
#endif
199

200
    addDockWidget( Qt::RightDockWidgetArea, m_controlPanel->getColormapperDock() );
201
    addDockWidget( Qt::RightDockWidgetArea, m_controlPanel->getRoiDock() );
202 203

    // tabify those panels by default
204 205 206
#ifdef OW_QT4GUI_NETWORKEDITOR
    tabifyDockWidget( m_networkEditor, m_controlPanel->getModuleDock() );
#endif
207
    tabifyDockWidget( m_controlPanel->getModuleDock(), m_controlPanel->getColormapperDock() );
208
    tabifyDockWidget( m_controlPanel->getColormapperDock(), m_controlPanel->getRoiDock() );
209 210

    // by default, the module editor should be in front
211
    m_controlPanel->getModuleDock()->raise();
212 213 214

    addDockWidget( Qt::RightDockWidgetArea, m_controlPanel );

215
    m_glDock = new QMainWindow();
216
    m_glDock->setObjectName( "GLDock" );
217 218 219 220
    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 );
221
    mainGLDock->setMinimumWidth( 500 );
222 223 224
    mainGLDock->getGLWidget()->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding );
    m_mainGLWidget = mainGLDock->getGLWidget();
    m_glDock->addDockWidget( Qt::RightDockWidgetArea, mainGLDock );
225
    connect( m_mainGLWidget.get(), SIGNAL( renderedFirstFrame() ), this, SLOT( handleGLVendor() ) );
226

227
    m_permanentToolBar = new WQtToolBar( "Standard Toolbar", this );
228
    addToolBar( Qt::TopToolBarArea, m_permanentToolBar );
229 230 231 232 233 234 235

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

236 237
    m_loadButton = new QAction( m_iconManager.getIcon( "load" ), "Load Dataset", m_permanentToolBar );
    m_loadButton->setShortcut( QKeySequence(  QKeySequence::Open ) );
238 239 240
    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 ) );
241 242
    QAction* projectLoadButton = new QAction( m_iconManager.getIcon( "loadProject" ), "Load Project", m_permanentToolBar );
    QAction* projectSaveButton = new QAction( m_iconManager.getIcon( "saveProject" ), "Save Project", m_permanentToolBar );
243
    projectLoadButton->setShortcut( QKeySequence( Qt::CTRL + Qt::SHIFT + Qt::Key_O ) );
244 245 246 247 248 249 250 251 252 253 254 255

    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" );
256 257 258

    // 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.
259
    m_controlPanel->selectUpperMostEntry();
260

Sebastian Eichelbaum's avatar
Sebastian Eichelbaum committed
261 262 263 264
    // 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.

265
    m_menuBar = new QMenuBar( this );
266 267

    // hide menu?
268 269 270
    m_menuBar->setVisible( hideMenuAction->get() );
    connect( hideMenuAction, SIGNAL( change( bool ) ), m_menuBar, SLOT( setVisible( bool ) ) );
    addAction( hideMenuAction );
271

272
    QMenu* fileMenu = m_menuBar->addMenu( "File" );
273

274
    fileMenu->addAction( m_loadButton );
Sebastian Eichelbaum's avatar
Sebastian Eichelbaum committed
275
    fileMenu->addSeparator();
276
    fileMenu->addAction( projectLoadButton );
277 278
    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
279 280 281
    saveMenu->addAction( "Save Modules Only", this, SLOT( projectSaveModuleOnly() ) );
    saveMenu->addAction( "Save Camera Only", this, SLOT( projectSaveCameraOnly() ) );
    saveMenu->addAction( "Save ROIs Only", this, SLOT( projectSaveROIOnly() ) );
282 283
    projectSaveButton->setMenu( saveMenu );

284 285 286
    // 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
287

Sebastian Eichelbaum's avatar
Sebastian Eichelbaum committed
288
    // This QAction stuff is quite ugly and complicated some times ... There is no nice constructor which takes name, slot keysequence and so on
289 290
    // directly -> set shortcuts, and some further properties using QAction's interface
    QMenu* viewMenu = m_menuBar->addMenu( "View" );
291
    viewMenu->addAction( hideMenuAction );
292
    viewMenu->addSeparator();
293
    viewMenu->addAction( showNavWidgets );
294 295 296 297
    viewMenu->addSeparator();
    viewMenu->addMenu( m_permanentToolBar->getStyleMenu() );

    // Camera menu
298 299 300
    QMenu* bgColorMenu = new QMenu( "Background Colors" );
    bgColorMenu->addAction( mainGLDock->getGLWidget()->getBackgroundColorAction() );

301
    QMenu* cameraMenu = m_menuBar->addMenu( "Camera" );
302 303
    cameraMenu->addAction( mainGLDock->getGLWidget()->getThrowingSetting() );
    cameraMenu->addMenu( bgColorMenu );
304 305 306
    cameraMenu->addSeparator();

    QMenu* settingsMenu = m_menuBar->addMenu( "Settings" );
307
    settingsMenu->addAction( m_autoDisplaySetting );
308
    settingsMenu->addAction( m_controlPanel->getModuleExcluder().getConfigureAction() );
309
    settingsMenu->addSeparator();
310
    settingsMenu->addAction( mtViews );
311
    settingsMenu->addSeparator();
312
    settingsMenu->addMenu( logLevels );
313 314 315

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

317 318 319 320 321
    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
322

Sebastian Eichelbaum's avatar
Sebastian Eichelbaum committed
323 324 325
    // 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 ).
326
    // By additionally adding the action to the main window, we ensure the action can be triggered even if the menu bar is hidden.
327
    QAction* tmpAction = cameraPresetMenu->addAction( m_iconManager.getIcon( "sagittal icon" ), "Left", this, SLOT( setPresetViewLeft() ),
328
                                             QKeySequence( Qt::CTRL + Qt::SHIFT + Qt::Key_L ) );
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( "sagittal icon" ), "Right", this, SLOT( setPresetViewRight() ),
                                       QKeySequence( Qt::CTRL + Qt::SHIFT + Qt::Key_R ) );
Mathias Goldau's avatar
[MERGE]  
Mathias Goldau committed
334
    tmpAction->setIconVisibleInMenu( true );
335 336
    this->addAction( tmpAction );

337 338
    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
339
    tmpAction->setIconVisibleInMenu( true );
340 341
    this->addAction( tmpAction );

342 343
    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
344
    tmpAction->setIconVisibleInMenu( true );
345 346
    this->addAction( tmpAction );

347 348
    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
349
    tmpAction->setIconVisibleInMenu( true );
350 351
    this->addAction( tmpAction );

352 353
    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
354
    tmpAction->setIconVisibleInMenu( true );
355 356
    this->addAction( tmpAction );

357
    resetButton->setMenu( cameraPresetMenu );
358

359
    QMenu* helpMenu = m_menuBar->addMenu( "Help" );
360
    helpMenu->addAction( m_iconManager.getIcon( "help" ), "OpenWalnut Help", this, SLOT( openOpenWalnutHelpDialog() ),
361 362 363 364
                         QKeySequence( QKeySequence::HelpContents ) );
    helpMenu->addSeparator();
    helpMenu->addAction( m_iconManager.getIcon( "logo" ), "About OpenWalnut", this, SLOT( openAboutDialog() ) );
    helpMenu->addAction( "About Qt", this, SLOT( openAboutQtDialog() ) );
365

366 367
    setMenuBar( m_menuBar );

368 369
    // initially 3 navigation views
    {
370
        if( showNavWidgets->get() )
371
        {
Sebastian Eichelbaum's avatar
[STYLE]  
Sebastian Eichelbaum committed
372
            m_navAxial = boost::shared_ptr< WQtNavGLWidget >( new WQtNavGLWidget( "Axial View", "Axial View", this, "Axial Slice",
373
                                                                                  m_mainGLWidget.get() ) );
374
            m_navAxial->setFeatures( QDockWidget::AllDockWidgetFeatures );
375
            m_navAxial->setSliderProperty( WKernel::getRunningKernel()->getSelectionManager()->getPropAxialPos() );
376
            m_navAxial->getGLWidget()->setCameraManipulator( WQtGLWidget::NO_OP );
377

378
            m_glDock->addDockWidget( Qt::LeftDockWidgetArea, m_navAxial.get() );
379

380 381
            m_navCoronal = boost::shared_ptr< WQtNavGLWidget >( new WQtNavGLWidget( "Coronal View", "Coronal View", this, "Coronal Slice",
                                                                                    m_mainGLWidget.get() ) );
382
            m_navCoronal->setFeatures( QDockWidget::AllDockWidgetFeatures );
383
            m_navCoronal->setSliderProperty( WKernel::getRunningKernel()->getSelectionManager()->getPropCoronalPos() );
384
            m_navCoronal->getGLWidget()->setCameraManipulator( WQtGLWidget::NO_OP );
385

386
            m_glDock->addDockWidget( Qt::LeftDockWidgetArea, m_navCoronal.get() );
387

ledig's avatar
ledig committed
388
            m_navSagittal =
389 390
                boost::shared_ptr< WQtNavGLWidget >( new WQtNavGLWidget( "Sagittal View", "Sagittal View", this, "Sagittal Slice",
                                                                         m_mainGLWidget.get() ) );
391
            m_navSagittal->setFeatures( QDockWidget::AllDockWidgetFeatures );
392
            m_navSagittal->setSliderProperty( WKernel::getRunningKernel()->getSelectionManager()->getPropSagittalPos() );
393
            m_navSagittal->getGLWidget()->setCameraManipulator( WQtGLWidget::NO_OP );
394

395
            m_glDock->addDockWidget( Qt::LeftDockWidgetArea, m_navSagittal.get() );
396

397 398 399
            bgColorMenu->addAction( m_navAxial->getGLWidget()->getBackgroundColorAction() );
            bgColorMenu->addAction( m_navCoronal->getGLWidget()->getBackgroundColorAction() );
            bgColorMenu->addAction( m_navSagittal->getGLWidget()->getBackgroundColorAction() );
400 401 402
        }
    }

403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421
    // create the show/hide actions using the selection manager's props
    WQtPropertyBoolAction* showAxial = new WQtPropertyBoolAction( WKernel::getRunningKernel()->getSelectionManager()->getPropAxialShow(),
                                                                  m_permanentToolBar );
    showAxial->setToolTip( "Toggle Axial Slice" );
    showAxial->setText( "Toggle Axial Slice" );
    showAxial->setIcon( m_iconManager.getIcon( "axial icon" ) );

    WQtPropertyBoolAction* showCoronal = new WQtPropertyBoolAction( WKernel::getRunningKernel()->getSelectionManager()->getPropCoronalShow(),
                                                                    m_permanentToolBar );
    showCoronal->setToolTip( "Toggle Coronal Slice" );
    showCoronal->setText( "Toggle Coronal Slice" );
    showCoronal->setIcon( m_iconManager.getIcon( "coronal icon" ) );

    WQtPropertyBoolAction* showSagittal = new WQtPropertyBoolAction( WKernel::getRunningKernel()->getSelectionManager()->getPropSagittalShow(),
                                                                     m_permanentToolBar );
    showSagittal->setToolTip( "Toggle Sagittal Slice" );
    showSagittal->setText( "Toggle Sagittal Slice" );
    showSagittal->setIcon( m_iconManager.getIcon( "sagittal icon" ) );

422
    // Temporarily disabled. We need a proper command prompt implementation first.
423
    // create command prompt toolbar
424 425 426
    // 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
427

428
    // setup permanent toolbar
429
    m_permanentToolBar->addAction( m_loadButton );
430
    m_permanentToolBar->addSeparator();
431 432
    m_permanentToolBar->addAction( projectLoadButton );
    m_permanentToolBar->addAction( projectSaveButton );
433
    m_permanentToolBar->addSeparator();
434 435
    m_permanentToolBar->addAction( resetButton );
    m_permanentToolBar->addAction( roiButton );
436
    m_permanentToolBar->addSeparator();
437 438 439 440
    m_permanentToolBar->addAction( showAxial );
    m_permanentToolBar->addAction( showCoronal );
    m_permanentToolBar->addAction( showSagittal );
    m_permanentToolBar->addSeparator();
441

442 443
    // after creating the GUI, restore its saved state
    restoreSavedState();
444
}
445

446 447 448
void WMainWindow::autoAdd( boost::shared_ptr< WModule > module, std::string proto )
{
    // get the prototype.
Alexander Wiebel's avatar
Alexander Wiebel committed
449
    if( !WKernel::getRunningKernel()->getRootContainer()->applyModule( module, proto, true ) )
450 451 452 453 454 455
    {
        WLogger::getLogger()->addLogMessage( "Auto Display active but module " + proto + " could not be added.",
                                             "GUI", LL_ERROR );
    }
}

456
void WMainWindow::moduleSpecificCleanup( boost::shared_ptr< WModule > /* module */ )
457
{
458
    // called for each removed module. Use this to undo modifications done due to added modules (moduleSpecificSetup)
459 460
}

461 462
void WMainWindow::moduleSpecificSetup( boost::shared_ptr< WModule > module )
{
463 464 465 466
    // 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.
467
    bool useAutoDisplay = m_autoDisplaySetting->get();
Alexander Wiebel's avatar
Alexander Wiebel committed
468
    if( useAutoDisplay && module->getType() == MODULE_DATA )
469 470 471 472 473 474
    {
        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.
475
        boost::shared_ptr< WDataModule > dataModule = boost::shared_static_cast< WDataModule >( module );
476 477

        // grab data and identify type
Alexander Wiebel's avatar
Alexander Wiebel committed
478
        if( dataModule->getDataSet()->isA< WDataSetSingle >() && dataModule->getDataSet()->isTexture() )
479 480 481
        {
            // it is a dataset single
            // load a nav slice module if a WDataSetSingle is available!?
482
            if( !m_navSlicesAlreadyLoaded )
483
            {
484
                autoAdd( module, "Navigation Slices" );
485
                m_navSlicesAlreadyLoaded = true;
486
            }
487
        }
Alexander Wiebel's avatar
Alexander Wiebel committed
488
        else if( dataModule->getDataSet()->isA< WDataSetFibers >() )
489 490
        {
            // it is a fiber dataset -> add the FiberDisplay module
491
            autoAdd( module, "Fiber Display" );
492
        }
Alexander Wiebel's avatar
Alexander Wiebel committed
493
        else if( dataModule->getDataSet()->isA< WEEG2 >() )
494
        {
495
            // it is a eeg dataset -> add the eegView module
496 497 498
            autoAdd( module, "EEG View" );
        }
    }
wiebel's avatar
wiebel committed
499
}
500

501 502
void WMainWindow::setCompatiblesToolbar( WQtCombinerToolbar* toolbar )
{
Alexander Wiebel's avatar
Alexander Wiebel committed
503
    if( m_currentCompatiblesToolbar )
504 505 506 507 508
    {
        delete m_currentCompatiblesToolbar;
    }
    m_currentCompatiblesToolbar = toolbar;

Alexander Wiebel's avatar
Alexander Wiebel committed
509
    if( !toolbar )
510 511 512
    {
        // ok, reset the toolbar
        // So create a dummy to permanently reserve the space
513
        m_currentCompatiblesToolbar = new WQtCombinerToolbar( this );
514 515
    }

516 517 518 519 520
    // 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 ) ) );

521
    // and the position of the toolbar
522
    addToolBar( Qt::TopToolBarArea, m_currentCompatiblesToolbar );
523
}
524

525 526 527 528 529
WQtCombinerToolbar* WMainWindow::getCompatiblesToolbar()
{
    return m_currentCompatiblesToolbar;
}

530
WQtControlPanel* WMainWindow::getControlPanel()
531
{
532
    return m_controlPanel;
533
}
534

535 536 537 538 539
WQtNetworkEditor* WMainWindow::getNetworkEditor()
{
    return m_networkEditor;
}

540
void WMainWindow::projectSave( const std::vector< boost::shared_ptr< WProjectFileIO > >& writer )
541 542 543 544
{
    QFileDialog fd;
    fd.setWindowTitle( "Save Project as" );
    fd.setFileMode( QFileDialog::AnyFile );
545
    fd.setAcceptMode( QFileDialog::AcceptSave );
546 547

    QStringList filters;
548
    filters << "Project File (*.owproj *.owp)";
549 550 551
    fd.setNameFilters( filters );
    fd.setViewMode( QFileDialog::Detail );
    QStringList fileNames;
Alexander Wiebel's avatar
Alexander Wiebel committed
552
    if( fd.exec() )
553 554 555 556 557
    {
        fileNames = fd.selectedFiles();
    }

    QStringList::const_iterator constIterator;
Alexander Wiebel's avatar
Alexander Wiebel committed
558
    for( constIterator = fileNames.constBegin(); constIterator != fileNames.constEnd(); ++constIterator )
559
    {
560 561
        std::string filename = ( *constIterator ).toStdString();
        // append owp if not existent
562
        if( filename.rfind( ".owp" ) == std::string::npos )
563 564 565 566
        {
            filename += ".owp";
        }

567
        boost::shared_ptr< WProjectFile > proj = boost::shared_ptr< WProjectFile >(
568
                new WProjectFile( filename )
569 570
        );

571 572 573
        try
        {
            // This call is synchronous.
Alexander Wiebel's avatar
Alexander Wiebel committed
574
            if( writer.empty() )
575 576 577 578 579 580 581
            {
                proj->save();
            }
            else
            {
                proj->save( writer );
            }
582 583 584 585 586 587 588 589
        }
        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 );
        }
590 591 592
    }
}

593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613
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 );
}

614 615 616 617 618 619 620
void WMainWindow::projectSaveModuleOnly()
{
    std::vector< boost::shared_ptr< WProjectFileIO > > w;
    w.push_back( WProjectFile::getModuleWriter() );
    projectSave( w );
}

621 622 623 624 625 626
void WMainWindow::projectLoad()
{
    QFileDialog fd;
    fd.setFileMode( QFileDialog::ExistingFiles );

    QStringList filters;
627
    filters << "Simple Project File (*.owproj *.owp)"
628 629 630 631
            << "Any files (*)";
    fd.setNameFilters( filters );
    fd.setViewMode( QFileDialog::Detail );
    QStringList fileNames;
Alexander Wiebel's avatar
Alexander Wiebel committed
632
    if( fd.exec() )
633 634 635 636 637
    {
        fileNames = fd.selectedFiles();
    }

    QStringList::const_iterator constIterator;
Alexander Wiebel's avatar
Alexander Wiebel committed
638
    for( constIterator = fileNames.constBegin(); constIterator != fileNames.constEnd(); ++constIterator )
639
    {
640 641
        boost::shared_ptr< WProjectFile > proj = boost::shared_ptr< WProjectFile >(
                new WProjectFile( ( *constIterator ).toStdString() )
642
        );
643 644

        // This call is asynchronous. It parses the file and the starts a thread to actually do all the stuff
645
        proj->load();
646 647 648
    }
}

649
void WMainWindow::openLoadDialog()
650
{
651 652 653 654 655 656 657 658 659 660 661
#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
662 663
    QFileDialog fd;
    fd.setFileMode( QFileDialog::ExistingFiles );
wiebel's avatar
wiebel committed
664 665

    QStringList filters;
666 667
    filters << "Known file types (*.cnt *.edf *.asc *.nii *.nii.gz *.fib)"
            << "EEG files (*.cnt *.edf *.asc)"
wiebel's avatar
wiebel committed
668
            << "NIfTI (*.nii *.nii.gz)"
669 670
            << "Fibers (*.fib)"
            << "Any files (*)";
wiebel's avatar
wiebel committed
671
    fd.setNameFilters( filters );
672 673
    fd.setViewMode( QFileDialog::Detail );
    QStringList fileNames;
Alexander Wiebel's avatar
Alexander Wiebel committed
674
    if( fd.exec() )
675 676 677
    {
        fileNames = fd.selectedFiles();
    }
678
#endif
679

680
    std::vector< std::string > stdFileNames;
681 682

    QStringList::const_iterator constIterator;
Alexander Wiebel's avatar
Alexander Wiebel committed
683
    for( constIterator = fileNames.constBegin(); constIterator != fileNames.constEnd(); ++constIterator )
684 685 686
    {
        stdFileNames.push_back( ( *constIterator ).toLocal8Bit().constData() );
    }
687

688
    m_loaderSignal( stdFileNames );
689
}
690

691 692 693 694
void WMainWindow::openAboutQtDialog()
{
    QMessageBox::aboutQt( this, "About Qt" );
}
695

696 697
void WMainWindow::openAboutDialog()
{
698
    std::string filename( WPathHelper::getDocPath().file_string() + "/openwalnut-qt4/OpenWalnutAbout.html" );
699
    std::string content = readFileIntoString( filename );
700
    QMessageBox::about( this, "About OpenWalnut", content.c_str() );
701 702
}

703
void WMainWindow::openOpenWalnutHelpDialog()
704
{
705
    std::string filename( WPathHelper::getDocPath().file_string() + "/openwalnut-qt4/OpenWalnutHelp.html" );
706 707

#ifndef QT4GUI_NOWEBKIT
708
    std::string content = readFileIntoString( filename );
709 710

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

712 713
    // specify intial layout
    QVBoxLayout *layout = new QVBoxLayout( window );
714
    window->setLayout( layout );
715 716 717 718 719
    window->resize( 500, 500 );

    window->show();

    QWebView *view = new QWebView( this );
720
    QString location( QString( "file://" ) + WPathHelper::getDocPath().file_string().c_str() + "/openwalnut-qt4/" );
721
    view->setHtml( content.c_str(), QUrl( location  ) );
722 723
    view->show();
    layout->addWidget( view );
724 725 726 727
#else
    QMessageBox::information( this, "Help", QString::fromStdString( "Sorry! Your version of OpenWalnut was not compiled with embedded help. "
                                                                    "To open the help pages, use this link: <a href="+filename+">Help</a>." ) );
#endif
728 729
}

730 731 732 733
void WMainWindow::setPresetViewLeft()
{
    boost::shared_ptr< WGEViewer > viewer;
    viewer = WKernel::getRunningKernel()->getGraphicsEngine()->getViewerByName( "main" );
schurade's avatar
schurade committed
734 735 736
    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 );
737 738 739 740 741 742
}

void WMainWindow::setPresetViewRight()
{
    boost::shared_ptr< WGEViewer > viewer;
    viewer = WKernel::getRunningKernel()->getGraphicsEngine()->getViewerByName( "main" );
schurade's avatar
schurade committed
743 744 745
    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 );
746 747 748 749 750 751
}

void WMainWindow::setPresetViewSuperior()
{
    boost::shared_ptr< WGEViewer > viewer;
    viewer = WKernel::getRunningKernel()->getGraphicsEngine()->getViewerByName( "main" );
schurade's avatar
schurade committed
752 753 754
    osg::ref_ptr<osgGA::TrackballManipulator>  cm = osg::dynamic_pointer_cast<osgGA::TrackballManipulator>( viewer->getCameraManipulator() );
    osg::Quat q( 0., 0., 0., 1 );
    cm->setRotation( q );
755 756 757 758 759 760
}

void WMainWindow::setPresetViewInferior()
{
    boost::shared_ptr< WGEViewer > viewer;
    viewer = WKernel::getRunningKernel()->getGraphicsEngine()->getViewerByName( "main" );
schurade's avatar
schurade committed
761 762 763
    osg::ref_ptr<osgGA::TrackballManipulator>  cm = osg::dynamic_pointer_cast<osgGA::TrackballManipulator>( viewer->getCameraManipulator() );
    osg::Quat q( 0., -1., 0., 0. );
    cm->setRotation( q );
764 765 766 767 768 769
}

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

void WMainWindow::setPresetViewPosterior()
{
    boost::shared_ptr< WGEViewer > viewer;
    viewer = WKernel::getRunningKernel()->getGraphicsEngine()->getViewerByName( "main" );
schurade's avatar
schurade committed
779 780 781
    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 );
782 783
}

784 785 786 787 788 789 790
void WMainWindow::openNotImplementedDialog()
{
    QMessageBox::information( this, "Not yet implemented!",
                              "This functionality is planned for future versions of OpenWalnut. "
                              "It is not yet implemented." );
}

schurade's avatar
schurade committed
791
boost::signals2::signal1< void, std::vector< std::string > >* WMainWindow::getLoaderSignal()
792 793 794 795
{
    return &m_loaderSignal;
}

796 797 798
WIconManager*  WMainWindow::getIconManager()
{
    return &m_iconManager;
schurade's avatar