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 134 135 136 137 138 139 140
    /////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 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() );

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, 0., 0., 0.707107 );
    cm->setRotation( q );