WMainWindow.cpp 43.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
#include <boost/thread.hpp>
31
#include <boost/regex.hpp>
32

33
#include <QtGui/QApplication>
34
#include <QtGui/QCloseEvent>
wiebel's avatar
wiebel committed
35
#include <QtGui/QDockWidget>
36
#include <QtGui/QFileDialog>
37
#include <QtGui/QIcon>
Mathias Goldau's avatar
Mathias Goldau committed
38 39
#include <QtGui/QMenu>
#include <QtGui/QMenuBar>
40
#include <QtGui/QMessageBox>
41
#include <QtGui/QTextEdit>
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
#ifndef QT4GUI_NOWEBKIT
    #include <QtWebKit/QWebView>
#endif

53 54
#include "WVersion.h"   // NOTE: this file is auto-generated by CMAKE

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

#include "WMainWindow.h"
91
#include "WMainWindow.moc"
92

93
WMainWindow::WMainWindow():
94
    QMainWindow(),
95
    m_currentCompatiblesToolbar( NULL ),
96 97
    m_iconManager(),
    m_navSlicesAlreadyLoaded( false )
Sebastian Eichelbaum's avatar
Sebastian Eichelbaum committed
98 99
{
}
100

101 102 103 104 105
WMainWindow::~WMainWindow()
{
    // cleanup
}

106
void WMainWindow::setupGUI()
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 "
134
                                                        "rendering on machines with multiple cores. WARNING: can lead to crashes sometimes.",
135 136 137 138 139 140
                                                        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() );

141 142 143 144 145 146 147 148 149 150 151 152 153 154 155
    // 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 ) ) );

156 157 158 159
    /////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // GUI setup
    /////////////////////////////////////////////////////////////////////////////////////////////////////////////////

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

175
    if( objectName().isEmpty() )
176
    {
177
        setObjectName( QString::fromUtf8( "MainWindow" ) );
178
    }
179 180 181

    // 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 );
182
    setWindowIcon( m_iconManager.getIcon( "logo" ) );
183
    setWindowTitle( QApplication::translate( "MainWindow", "OpenWalnut (development version)", 0, QApplication::UnicodeUTF8 ) );
184

185 186
    setDockOptions( QMainWindow::AnimatedDocks |  QMainWindow::AllowNestedDocks | QMainWindow::AllowTabbedDocks );

187 188 189 190 191
#ifdef OW_QT4GUI_NETWORKEDITOR
    //network Editor
    m_networkEditor = new WQtNetworkEditor( this );
    m_networkEditor->setFeatures( QDockWidget::AllDockWidgetFeatures );
#endif
192

193 194 195 196
    // the control panel instance is needed for the menu
    m_controlPanel = new WQtControlPanel( this );
    m_controlPanel->setFeatures( QDockWidget::AllDockWidgetFeatures );
    m_controlPanel->addSubject( "Default Subject" );
197

198 199
    // add all docks
    addDockWidget( Qt::RightDockWidgetArea, m_controlPanel->getModuleDock() );
200 201 202
#ifdef OW_QT4GUI_NETWORKEDITOR
    addDockWidget( Qt::RightDockWidgetArea, m_networkEditor );
#endif
203

204
    addDockWidget( Qt::RightDockWidgetArea, m_controlPanel->getColormapperDock() );
205
    addDockWidget( Qt::RightDockWidgetArea, m_controlPanel->getRoiDock() );
206 207

    // tabify those panels by default
208 209 210
#ifdef OW_QT4GUI_NETWORKEDITOR
    tabifyDockWidget( m_networkEditor, m_controlPanel->getModuleDock() );
#endif
211
    tabifyDockWidget( m_controlPanel->getModuleDock(), m_controlPanel->getColormapperDock() );
212
    tabifyDockWidget( m_controlPanel->getColormapperDock(), m_controlPanel->getRoiDock() );
213 214

    // by default, the module editor should be in front
215
    m_controlPanel->getModuleDock()->raise();
216 217 218

    addDockWidget( Qt::RightDockWidgetArea, m_controlPanel );

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

231 232 233
    // NOTE: we abuse the gl widgets first frame event to handle startup news.
    connect( m_mainGLWidget.get(), SIGNAL( renderedFirstFrame() ), this, SLOT( handleStartMessages() ) );

234
    m_permanentToolBar = new WQtToolBar( "Standard Toolbar", this );
235
    addToolBar( Qt::TopToolBarArea, m_permanentToolBar );
236 237 238 239 240 241 242

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

243 244
    m_loadButton = new QAction( m_iconManager.getIcon( "load" ), "Load Dataset", m_permanentToolBar );
    m_loadButton->setShortcut( QKeySequence(  QKeySequence::Open ) );
245 246 247
    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 ) );
248 249
    QAction* projectLoadButton = new QAction( m_iconManager.getIcon( "loadProject" ), "Load Project", m_permanentToolBar );
    QAction* projectSaveButton = new QAction( m_iconManager.getIcon( "saveProject" ), "Save Project", m_permanentToolBar );
250
    projectLoadButton->setShortcut( QKeySequence( Qt::CTRL + Qt::SHIFT + Qt::Key_O ) );
251 252 253 254 255 256 257 258 259 260 261 262

    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" );
263 264 265

    // 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.
266
    m_controlPanel->selectUpperMostEntry();
267

Sebastian Eichelbaum's avatar
Sebastian Eichelbaum committed
268 269 270 271
    // 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.

272
    m_menuBar = new QMenuBar( this );
273 274

    // hide menu?
275 276 277
    m_menuBar->setVisible( hideMenuAction->get() );
    connect( hideMenuAction, SIGNAL( change( bool ) ), m_menuBar, SLOT( setVisible( bool ) ) );
    addAction( hideMenuAction );
278

279
    QMenu* fileMenu = m_menuBar->addMenu( "File" );
280

281
    fileMenu->addAction( m_loadButton );
Sebastian Eichelbaum's avatar
Sebastian Eichelbaum committed
282
    fileMenu->addSeparator();
283
    fileMenu->addAction( projectLoadButton );
284 285
    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
286 287 288
    saveMenu->addAction( "Save Modules Only", this, SLOT( projectSaveModuleOnly() ) );
    saveMenu->addAction( "Save Camera Only", this, SLOT( projectSaveCameraOnly() ) );
    saveMenu->addAction( "Save ROIs Only", this, SLOT( projectSaveROIOnly() ) );
289 290
    projectSaveButton->setMenu( saveMenu );

291 292 293
    // 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
294

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

    // Camera menu
305 306 307
    QMenu* bgColorMenu = new QMenu( "Background Colors" );
    bgColorMenu->addAction( mainGLDock->getGLWidget()->getBackgroundColorAction() );

308
    QMenu* cameraMenu = m_menuBar->addMenu( "Camera" );
309 310
    cameraMenu->addAction( mainGLDock->getGLWidget()->getThrowingSetting() );
    cameraMenu->addMenu( bgColorMenu );
311 312 313
    cameraMenu->addSeparator();

    QMenu* settingsMenu = m_menuBar->addMenu( "Settings" );
314
    settingsMenu->addAction( m_autoDisplaySetting );
315
    settingsMenu->addAction( m_controlPanel->getModuleExcluder().getConfigureAction() );
316
    settingsMenu->addSeparator();
317
    settingsMenu->addAction( mtViews );
318
    settingsMenu->addSeparator();
319
    settingsMenu->addMenu( logLevels );
320 321 322

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

324 325 326 327 328
    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
329

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

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

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

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

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

359 360
    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
361
    tmpAction->setIconVisibleInMenu( true );
362 363
    this->addAction( tmpAction );

364
    resetButton->setMenu( cameraPresetMenu );
365

366
    QMenu* helpMenu = m_menuBar->addMenu( "Help" );
367
    helpMenu->addAction( m_iconManager.getIcon( "help" ), "OpenWalnut Help", this, SLOT( openOpenWalnutHelpDialog() ),
368 369 370 371
                         QKeySequence( QKeySequence::HelpContents ) );
    helpMenu->addSeparator();
    helpMenu->addAction( m_iconManager.getIcon( "logo" ), "About OpenWalnut", this, SLOT( openAboutDialog() ) );
    helpMenu->addAction( "About Qt", this, SLOT( openAboutQtDialog() ) );
372

373 374
    setMenuBar( m_menuBar );

375 376
    // initially 3 navigation views
    {
377
        if( showNavWidgets->get() )
378
        {
Sebastian Eichelbaum's avatar
[STYLE]  
Sebastian Eichelbaum committed
379
            m_navAxial = boost::shared_ptr< WQtNavGLWidget >( new WQtNavGLWidget( "Axial View", "Axial View", this, "Axial Slice",
380
                                                                                  m_mainGLWidget.get() ) );
381
            m_navAxial->setFeatures( QDockWidget::AllDockWidgetFeatures );
382
            m_navAxial->setSliderProperty( WKernel::getRunningKernel()->getSelectionManager()->getPropAxialPos() );
383
            m_navAxial->getGLWidget()->setCameraManipulator( WQtGLWidget::NO_OP );
384

385
            m_glDock->addDockWidget( Qt::LeftDockWidgetArea, m_navAxial.get() );
386

387 388
            m_navCoronal = boost::shared_ptr< WQtNavGLWidget >( new WQtNavGLWidget( "Coronal View", "Coronal View", this, "Coronal Slice",
                                                                                    m_mainGLWidget.get() ) );
389
            m_navCoronal->setFeatures( QDockWidget::AllDockWidgetFeatures );
390
            m_navCoronal->setSliderProperty( WKernel::getRunningKernel()->getSelectionManager()->getPropCoronalPos() );
391
            m_navCoronal->getGLWidget()->setCameraManipulator( WQtGLWidget::NO_OP );
392

393
            m_glDock->addDockWidget( Qt::LeftDockWidgetArea, m_navCoronal.get() );
394

ledig's avatar
ledig committed
395
            m_navSagittal =
396 397
                boost::shared_ptr< WQtNavGLWidget >( new WQtNavGLWidget( "Sagittal View", "Sagittal View", this, "Sagittal Slice",
                                                                         m_mainGLWidget.get() ) );
398
            m_navSagittal->setFeatures( QDockWidget::AllDockWidgetFeatures );
399
            m_navSagittal->setSliderProperty( WKernel::getRunningKernel()->getSelectionManager()->getPropSagittalPos() );
400
            m_navSagittal->getGLWidget()->setCameraManipulator( WQtGLWidget::NO_OP );
401

402
            m_glDock->addDockWidget( Qt::LeftDockWidgetArea, m_navSagittal.get() );
403

404 405 406
            bgColorMenu->addAction( m_navAxial->getGLWidget()->getBackgroundColorAction() );
            bgColorMenu->addAction( m_navCoronal->getGLWidget()->getBackgroundColorAction() );
            bgColorMenu->addAction( m_navSagittal->getGLWidget()->getBackgroundColorAction() );
407 408 409
        }
    }

410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428
    // 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" ) );

429
    // Temporarily disabled. We need a proper command prompt implementation first.
430
    // create command prompt toolbar
431 432 433
    // 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
434

435
    // setup permanent toolbar
436
    m_permanentToolBar->addAction( m_loadButton );
437
    m_permanentToolBar->addSeparator();
438 439
    m_permanentToolBar->addAction( projectLoadButton );
    m_permanentToolBar->addAction( projectSaveButton );
440
    m_permanentToolBar->addSeparator();
441 442
    m_permanentToolBar->addAction( resetButton );
    m_permanentToolBar->addAction( roiButton );
443
    m_permanentToolBar->addSeparator();
444 445 446 447
    m_permanentToolBar->addAction( showAxial );
    m_permanentToolBar->addAction( showCoronal );
    m_permanentToolBar->addAction( showSagittal );
    m_permanentToolBar->addSeparator();
448

449 450
    // after creating the GUI, restore its saved state
    restoreSavedState();
451
}
452

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

463
void WMainWindow::moduleSpecificCleanup( boost::shared_ptr< WModule > /* module */ )
464
{
465
    // called for each removed module. Use this to undo modifications done due to added modules (moduleSpecificSetup)
466 467
}

468 469
void WMainWindow::moduleSpecificSetup( boost::shared_ptr< WModule > module )
{
470 471 472 473
    // 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.
474
    bool useAutoDisplay = m_autoDisplaySetting->get();
Alexander Wiebel's avatar
Alexander Wiebel committed
475
    if( useAutoDisplay && module->getType() == MODULE_DATA )
476 477 478 479 480 481
    {
        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.
482
        boost::shared_ptr< WDataModule > dataModule = boost::shared_static_cast< WDataModule >( module );
483 484

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

508 509
void WMainWindow::setCompatiblesToolbar( WQtCombinerToolbar* toolbar )
{
Alexander Wiebel's avatar
Alexander Wiebel committed
510
    if( m_currentCompatiblesToolbar )
511 512 513 514 515
    {
        delete m_currentCompatiblesToolbar;
    }
    m_currentCompatiblesToolbar = toolbar;

Alexander Wiebel's avatar
Alexander Wiebel committed
516
    if( !toolbar )
517 518 519
    {
        // ok, reset the toolbar
        // So create a dummy to permanently reserve the space
520
        m_currentCompatiblesToolbar = new WQtCombinerToolbar( this );
521 522
    }

523 524 525 526 527
    // 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 ) ) );

528
    // and the position of the toolbar
529
    addToolBar( Qt::TopToolBarArea, m_currentCompatiblesToolbar );
530
}
531

532 533 534 535 536
WQtCombinerToolbar* WMainWindow::getCompatiblesToolbar()
{
    return m_currentCompatiblesToolbar;
}

537
WQtControlPanel* WMainWindow::getControlPanel()
538
{
539
    return m_controlPanel;
540
}
541

542 543 544 545 546
WQtNetworkEditor* WMainWindow::getNetworkEditor()
{
    return m_networkEditor;
}

547
void WMainWindow::projectSave( const std::vector< boost::shared_ptr< WProjectFileIO > >& writer )
548 549 550 551
{
    QFileDialog fd;
    fd.setWindowTitle( "Save Project as" );
    fd.setFileMode( QFileDialog::AnyFile );
552
    fd.setAcceptMode( QFileDialog::AcceptSave );
553 554

    QStringList filters;
555
    filters << "Project File (*.owproj *.owp)";
556 557 558
    fd.setNameFilters( filters );
    fd.setViewMode( QFileDialog::Detail );
    QStringList fileNames;
Alexander Wiebel's avatar
Alexander Wiebel committed
559
    if( fd.exec() )
560 561 562 563 564
    {
        fileNames = fd.selectedFiles();
    }

    QStringList::const_iterator constIterator;
Alexander Wiebel's avatar
Alexander Wiebel committed
565
    for( constIterator = fileNames.constBegin(); constIterator != fileNames.constEnd(); ++constIterator )
566
    {
567 568
        std::string filename = ( *constIterator ).toStdString();
        // append owp if not existent
569
        if( filename.rfind( ".owp" ) == std::string::npos )
570 571 572 573
        {
            filename += ".owp";
        }

574
        boost::shared_ptr< WProjectFile > proj = boost::shared_ptr< WProjectFile >(
575
                new WProjectFile( filename )
576 577
        );

578 579 580
        try
        {
            // This call is synchronous.
Alexander Wiebel's avatar
Alexander Wiebel committed
581
            if( writer.empty() )
582 583 584 585 586 587 588
            {
                proj->save();
            }
            else
            {
                proj->save( writer );
            }
589 590 591 592 593 594 595 596
        }
        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 );
        }
597 598 599
    }
}

600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620
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 );
}

621 622 623 624 625 626 627
void WMainWindow::projectSaveModuleOnly()
{
    std::vector< boost::shared_ptr< WProjectFileIO > > w;
    w.push_back( WProjectFile::getModuleWriter() );
    projectSave( w );
}

628 629 630 631 632 633
void WMainWindow::projectLoad()
{
    QFileDialog fd;
    fd.setFileMode( QFileDialog::ExistingFiles );

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

    QStringList::const_iterator constIterator;
Alexander Wiebel's avatar
Alexander Wiebel committed
645
    for( constIterator = fileNames.constBegin(); constIterator != fileNames.constEnd(); ++constIterator )
646
    {
647 648
        boost::shared_ptr< WProjectFile > proj = boost::shared_ptr< WProjectFile >(
                new WProjectFile( ( *constIterator ).toStdString() )
649
        );
650 651

        // This call is asynchronous. It parses the file and the starts a thread to actually do all the stuff
652
        proj->load();
653 654 655
    }
}

656
void WMainWindow::openLoadDialog()
657
{
658 659 660 661 662 663 664 665 666 667 668
#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
669 670
    QFileDialog fd;
    fd.setFileMode( QFileDialog::ExistingFiles );
wiebel's avatar
wiebel committed
671 672

    QStringList filters;
673 674
    filters << "Known file types (*.cnt *.edf *.asc *.nii *.nii.gz *.fib)"
            << "EEG files (*.cnt *.edf *.asc)"
wiebel's avatar
wiebel committed
675
            << "NIfTI (*.nii *.nii.gz)"
676 677
            << "Fibers (*.fib)"
            << "Any files (*)";
wiebel's avatar
wiebel committed
678
    fd.setNameFilters( filters );
679 680
    fd.setViewMode( QFileDialog::Detail );
    QStringList fileNames;
Alexander Wiebel's avatar
Alexander Wiebel committed
681
    if( fd.exec() )
682 683 684
    {
        fileNames = fd.selectedFiles();
    }
685
#endif
686

687
    std::vector< std::string > stdFileNames;
688 689

    QStringList::const_iterator constIterator;
Alexander Wiebel's avatar
Alexander Wiebel committed
690
    for( constIterator = fileNames.constBegin(); constIterator != fileNames.constEnd(); ++constIterator )
691 692 693
    {
        stdFileNames.push_back( ( *constIterator ).toLocal8Bit().constData() );
    }
694

695
    m_loaderSignal( stdFileNames );
696
}
697

698 699 700 701
void WMainWindow::openAboutQtDialog()
{
    QMessageBox::aboutQt( this, "About Qt" );
}
702

703 704
void WMainWindow::openAboutDialog()
{
705
    std::string filename( WPathHelper::getDocPath().file_string() + "/openwalnut-qt4/OpenWalnutAbout.html" );
706
    std::string content = readFileIntoString( filename );
707
    QMessageBox::about( this, "About OpenWalnut", content.c_str() );
708 709
}

710
void WMainWindow::openOpenWalnutHelpDialog()
711
{
712
    std::string filename( WPathHelper::getDocPath().file_string() + "/openwalnut-qt4/OpenWalnutHelp.html" );
713 714

#ifndef QT4GUI_NOWEBKIT
715
    std::string content = readFileIntoString( filename );
716 717

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

719 720
    // specify intial layout
    QVBoxLayout *layout = new QVBoxLayout( window );
721
    window->setLayout( layout );
722 723 724 725 726
    window->resize( 500, 500 );

    window->show();

    QWebView *view = new QWebView( this );
727
    QString location( QString( "file://" ) + WPathHelper::getDocPath().file_string().c_str() + "/openwalnut-qt4/" );
728
    view->setHtml( content.c_str(), QUrl( location  ) );
729 730
    view->show();
    layout->addWidget( view );
731 732 733 734
#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
735 736
}

737 738 739 740
void WMainWindow::setPresetViewLeft()
{
    boost::shared_ptr< WGEViewer > viewer;
    viewer = WKernel::getRunningKernel()->getGraphicsEngine()->getViewerByName( "main" );
schurade's avatar
schurade committed
741 742 743
    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 );
744 745 746 747 748 749
}

void WMainWindow::setPresetViewRight()
{
    boost::shared_ptr< WGEViewer > viewer;
    viewer = WKernel::getRunningKernel()->getGraphicsEngine()->getViewerByName( "main" );
schurade's avatar
schurade committed
750 751 752
    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 );
753 754 755 756 757 758
}

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

void WMainWindow::setPresetViewInferior()
{
    boost::shared_ptr< WGEViewer > viewer;
    viewer = WKernel::getRunningKernel()->getGraphicsEngine()->getViewerByName( "main" );
schurade's avatar
schurade committed
768 769 770
    osg::ref_ptr<osgGA::TrackballManipulator>  cm = osg::dynamic_pointer_cast<osgGA::TrackballManipulator>( viewer->getCameraManipulator() );
    osg::Quat q( 0., -1., 0., 0. );
    cm->setRotation( q );
771 772 773 774 775 776
}

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

void WMainWindow::setPresetViewPosterior()
{
    boost::shared_ptr< WGEViewer > viewer;
    viewer = WKernel::getRunningKernel()->getGraphicsEngine()->getViewerByName( "main" );
schurade's avatar
schurade committed
786 787 788
    osg::ref_ptr<osgGA::TrackballManipulator>  cm = osg::dynamic_pointer_cast<osgGA::TrackballManipulator>( viewer->getCameraManipulator() );
    osg::Quat q( 0.707107,