WMainWindow.cpp 41.4 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

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

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

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

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

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

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

264
    m_menuBar = new QMenuBar( this );
265 266

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

356
    resetButton->setMenu( cameraPresetMenu );
357

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

365 366
    setMenuBar( m_menuBar );

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

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

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

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

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

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

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

402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420
    // 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" ) );

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

687
    m_loaderSignal( stdFileNames );
688
}
689

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

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

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

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

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

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

    window->show();

    QWebView *view = new QWebView( this );
719
    QString location( QString( "file://" ) + WPathHelper::getDocPath().file_string().c_str() + "/openwalnut-qt4/" );
720
    view->setHtml( content.c_str(), QUrl( location  ) );
721 722
    view->show();
    layout->addWidget( view );
723 724 725 726
#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
727 728
}

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

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

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

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

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

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

783 784 785 786 787 788 789
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
790
boost::signals2::signal1< void, std::vector< std::string > >* WMainWindow::getLoaderSignal()
791 792 793 794
{
    return &m_loaderSignal;
}

795 796 797
WIconManager*  WMainWindow::getIconManager()
{
    return &m_iconManager;