WMainWindow.cpp 38.8 KB
Newer Older
1 2
//---------------------------------------------------------------------------
//
3
// Project: OpenWalnut ( http://www.openwalnut.org )
4
//
5 6
// Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS
// For more information see http://www.openwalnut.org/copying
wiebel's avatar
wiebel committed
7
//
wiebel's avatar
wiebel committed
8
// This file is part of OpenWalnut.
wiebel's avatar
wiebel committed
9
//
wiebel's avatar
wiebel committed
10
// OpenWalnut is free software: you can redistribute it and/or modify
wiebel's avatar
wiebel committed
11 12 13 14
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
wiebel's avatar
wiebel committed
15
// OpenWalnut is distributed in the hope that it will be useful,
wiebel's avatar
wiebel committed
16 17 18 19 20
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
wiebel's avatar
wiebel committed
21
// along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
wiebel's avatar
wiebel committed
22
//
23 24
//---------------------------------------------------------------------------

25
#include <iostream>
Mathias Goldau's avatar
Mathias Goldau committed
26
#include <map>
27 28
#include <string>
#include <vector>
29

30 31
#include <boost/thread.hpp>

32
#include <QtGui/QApplication>
33
#include <QtGui/QCloseEvent>
wiebel's avatar
wiebel committed
34
#include <QtGui/QDockWidget>
35
#include <QtGui/QFileDialog>
36
#include <QtGui/QIcon>
Mathias Goldau's avatar
Mathias Goldau committed
37 38
#include <QtGui/QMenu>
#include <QtGui/QMenuBar>
39
#include <QtGui/QMessageBox>
40 41
#include <QtGui/QTextEdit>
#include <QtWebKit/QWebView>
42
#include <QtGui/QShortcut>
Mathias Goldau's avatar
Mathias Goldau committed
43
#include <QtGui/QSlider>
44
#include <QtGui/QVBoxLayout>
45
#include <QtGui/QWidget>
46
#include <QtCore/QSettings>
47

48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64
#include "core/common/WColor.h"
#include "core/common/WIOTools.h"
#include "core/common/WProjectFileIO.h"
#include "core/common/WPathHelper.h"
#include "core/dataHandler/WDataSetFibers.h"
#include "core/dataHandler/WDataSetSingle.h"
#include "core/dataHandler/WEEG2.h"
#include "core/graphicsEngine/WGEZoomTrackballManipulator.h"
#include "core/graphicsEngine/WROIBox.h"
#include "core/kernel/modules/data/WMData.h"
#include "core/kernel/WKernel.h"
#include "core/kernel/WModule.h"
#include "core/kernel/WModuleCombiner.h"
#include "core/kernel/WModuleCombinerTypes.h"
#include "core/kernel/WProjectFile.h"
#include "core/kernel/WROIManager.h"
#include "core/kernel/WSelectionManager.h"
65
#include "../icons/WIcons.xpm"
66
#include "controlPanel/WPropertyBoolWidget.h"
67
#include "controlPanel/WQtControlPanel.h"
Mathias Goldau's avatar
Mathias Goldau committed
68 69 70
#include "events/WEventTypes.h"
#include "events/WModuleCrashEvent.h"
#include "events/WModuleReadyEvent.h"
71
#include "events/WModuleRemovedEvent.h"
72
#include "events/WOpenCustomDockWidgetEvent.h"
Sebastian Eichelbaum's avatar
[MERGE]  
Sebastian Eichelbaum committed
73
#include "guiElements/WQtPropertyBoolAction.h"
74
#include "WQtCombinerToolbar.h"
Mathias Goldau's avatar
Mathias Goldau committed
75 76
#include "WQtCustomDockWidget.h"
#include "WQtNavGLWidget.h"
77
#include "WQtGLDockWidget.h"
78
#include "WQt4Gui.h"
Mathias Goldau's avatar
Mathias Goldau committed
79 80

#include "WMainWindow.h"
81
#include "WMainWindow.moc"
82

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

91 92 93 94 95
WMainWindow::~WMainWindow()
{
    // cleanup
}

96
void WMainWindow::setupGUI()
97
{
98
    m_iconManager.addIcon( std::string( "load" ), fileopen_xpm );
99
    m_iconManager.addIcon( std::string( "loadProject" ), projOpen_xpm );
100
    m_iconManager.addIcon( std::string( "saveProject" ), projSave_xpm );
101
    m_iconManager.addIcon( std::string( "logo" ), logoIcon_xpm );
102
    m_iconManager.addIcon( std::string( "help" ), question_xpm );
103
    m_iconManager.addIcon( std::string( "quit" ), quit_xpm );
104 105 106
    m_iconManager.addIcon( std::string( "moduleBusy" ), moduleBusy_xpm );
    m_iconManager.addIcon( std::string( "moduleCrashed" ), moduleCrashed_xpm );
    m_iconManager.addIcon( std::string( "remove" ), remove_xpm );
107
    m_iconManager.addIcon( std::string( "config" ), preferences_system_xpm );
108
    m_iconManager.addIcon( std::string( "view" ), camera_xpm );
109

110
    if( objectName().isEmpty() )
111
    {
112
        setObjectName( QString::fromUtf8( "MainWindow" ) );
113
    }
114
    // TODO(all): what is this?
115 116
    resize( 946, 632 );
    setWindowIcon( m_iconManager.getIcon( "logo" ) );
117
    setWindowTitle( QApplication::translate( "MainWindow", "OpenWalnut (development version)", 0, QApplication::UnicodeUTF8 ) );
118

119 120
    setDockOptions( QMainWindow::AnimatedDocks |  QMainWindow::AllowNestedDocks | QMainWindow::AllowTabbedDocks );

121 122 123
    //network Editor
    m_networkEditor = new WQtNetworkEditor( this );
    m_networkEditor->setFeatures( QDockWidget::AllDockWidgetFeatures );
124

125 126 127 128
    // the control panel instance is needed for the menu
    m_controlPanel = new WQtControlPanel( this );
    m_controlPanel->setFeatures( QDockWidget::AllDockWidgetFeatures );
    m_controlPanel->addSubject( "Default Subject" );
129

130 131 132 133 134
    // add all docks
    addDockWidget( Qt::RightDockWidgetArea, m_controlPanel->getModuleDock() );
    addDockWidget( Qt::RightDockWidgetArea, m_networkEditor );
    tabifyDockWidget( m_networkEditor, m_controlPanel->getModuleDock() );

135
    addDockWidget( Qt::RightDockWidgetArea, m_controlPanel->getColormapperDock() );
136
    addDockWidget( Qt::RightDockWidgetArea, m_controlPanel->getRoiDock() );
137
    tabifyDockWidget( m_controlPanel->getColormapperDock(), m_controlPanel->getRoiDock() );
138 139 140

    addDockWidget( Qt::RightDockWidgetArea, m_controlPanel );

141
    m_glDock = new QMainWindow();
142
    m_glDock->setObjectName( "GLDock" );
143 144 145 146 147 148 149
    m_glDock->setDockOptions( QMainWindow::AnimatedDocks |  QMainWindow::AllowNestedDocks | QMainWindow::AllowTabbedDocks );
    m_glDock->setDocumentMode( true );
    setCentralWidget( m_glDock );
    WQtGLDockWidget* mainGLDock = new WQtGLDockWidget( "main", "3D View", m_glDock );
    mainGLDock->getGLWidget()->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding );
    m_mainGLWidget = mainGLDock->getGLWidget();
    m_glDock->addDockWidget( Qt::RightDockWidgetArea, mainGLDock );
150 151

    m_permanentToolBar = new WQtToolBar( "Permanent Toolbar", this );
152
    addToolBar( Qt::TopToolBarArea, m_permanentToolBar );
153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177

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

    m_loadButton = new QAction( m_iconManager.getIcon( "load" ), "load", m_permanentToolBar );
    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 ) );
    QAction* projectLoadButton = new QAction( m_iconManager.getIcon( "loadProject" ), "loadProject", m_permanentToolBar );
    QAction* projectSaveButton = new QAction( m_iconManager.getIcon( "saveProject" ), "saveProject", m_permanentToolBar );

    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" );
178 179 180

    // 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.
181
    m_controlPanel->selectUpperMostEntry();
182

Sebastian Eichelbaum's avatar
Sebastian Eichelbaum committed
183 184 185 186
    // 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.

187
    m_menuBar = new QMenuBar( this );
188 189

    // hide menu?
190
    bool hideMenu = WQt4Gui::getSettings().value( "qt4gui/hideMenu", false ).toBool();
191 192
    m_menuBar->setVisible( !hideMenu );

193
    QMenu* fileMenu = m_menuBar->addMenu( "File" );
194

Sebastian Eichelbaum's avatar
Sebastian Eichelbaum committed
195 196
    fileMenu->addAction( m_iconManager.getIcon( "load" ), "Load Dataset", this, SLOT( openLoadDialog() ), QKeySequence(  QKeySequence::Open ) );
    fileMenu->addSeparator();
197
    fileMenu->addAction( m_iconManager.getIcon( "loadProject" ), "Load Project", this, SLOT( projectLoad() ) );
198 199
    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
200 201 202
    saveMenu->addAction( "Save Modules Only", this, SLOT( projectSaveModuleOnly() ) );
    saveMenu->addAction( "Save Camera Only", this, SLOT( projectSaveCameraOnly() ) );
    saveMenu->addAction( "Save ROIs Only", this, SLOT( projectSaveROIOnly() ) );
203 204
    projectSaveButton->setMenu( saveMenu );

205 206 207
    // 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
208

Sebastian Eichelbaum's avatar
Sebastian Eichelbaum committed
209
    // This QAction stuff is quite ugly and complicated some times ... There is no nice constructor which takes name, slot keysequence and so on
210 211
    // directly -> set shortcuts, and some further properties using QAction's interface
    QMenu* viewMenu = m_menuBar->addMenu( "View" );
212
    viewMenu->addAction( "Show Menubar", this, SLOT( showMenuBar() ), QKeySequence( Qt::CTRL + Qt::Key_M ) );
213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229
    viewMenu->addAction( "Show Statusbar", this, SLOT( showStatusBar() ) );
    viewMenu->addSeparator();
    viewMenu->addAction( "Show Navigation Views", this, SLOT( showNavViews() ) );
    viewMenu->addSeparator();
    viewMenu->addMenu( m_permanentToolBar->getStyleMenu() );

    // Camera menu
    QMenu* cameraMenu = m_menuBar->addMenu( "Camera" );
    cameraMenu->addAction( "Set Background Color", this, SLOT( setBGColor() ) );
    cameraMenu->addAction( "Allow Camera Throwing", this, SLOT( setAllowThrow() ) );
    cameraMenu->addSeparator();

    QMenu* settingsMenu = m_menuBar->addMenu( "Settings" );
    settingsMenu->addAction( "Enable Auto-Display", this, SLOT( setAutoDisplay() ) );

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

231 232 233 234 235
    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
236

Sebastian Eichelbaum's avatar
Sebastian Eichelbaum committed
237 238 239
    // 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 ).
240
    // By additionally adding the action to the main window, we ensure the action can be triggered even if the menu bar is hidden.
241
    QAction* tmpAction = cameraPresetMenu->addAction( m_iconManager.getIcon( "sagittal icon" ), "Left", this, SLOT( setPresetViewLeft() ),
242
                                             QKeySequence( Qt::CTRL + Qt::SHIFT + Qt::Key_L ) );
Mathias Goldau's avatar
[MERGE]  
Mathias Goldau committed
243
    tmpAction->setIconVisibleInMenu( true );
244 245
    this->addAction( tmpAction );

246 247
    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
248
    tmpAction->setIconVisibleInMenu( true );
249 250
    this->addAction( tmpAction );

251 252
    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
253
    tmpAction->setIconVisibleInMenu( true );
254 255
    this->addAction( tmpAction );

256 257
    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
258
    tmpAction->setIconVisibleInMenu( true );
259 260
    this->addAction( tmpAction );

261 262
    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
263
    tmpAction->setIconVisibleInMenu( true );
264 265
    this->addAction( tmpAction );

266 267
    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
268
    tmpAction->setIconVisibleInMenu( true );
269 270
    this->addAction( tmpAction );

271
    resetButton->setMenu( cameraPresetMenu );
272

273
    QMenu* helpMenu = m_menuBar->addMenu( "Help" );
274
    helpMenu->addAction( m_iconManager.getIcon( "help" ), "OpenWalnut Help", this, SLOT( openOpenWalnutHelpDialog() ),
275 276 277 278
                         QKeySequence( QKeySequence::HelpContents ) );
    helpMenu->addSeparator();
    helpMenu->addAction( m_iconManager.getIcon( "logo" ), "About OpenWalnut", this, SLOT( openAboutDialog() ) );
    helpMenu->addAction( "About Qt", this, SLOT( openAboutQtDialog() ) );
279

280 281
    setMenuBar( m_menuBar );

282 283
    // initially 3 navigation views
    {
284
        bool hideNavWidget = WQt4Gui::getSettings().value( "qt4gui/hideNavigationWidgets", false ).toBool();
285
        if( !hideNavWidget )
286
        {
Sebastian Eichelbaum's avatar
[STYLE]  
Sebastian Eichelbaum committed
287
            m_navAxial = boost::shared_ptr< WQtNavGLWidget >( new WQtNavGLWidget( "Axial View", "Axial View", this, "Axial Slice",
288
                                                                                  m_mainGLWidget.get() ) );
289
            m_navAxial->setFeatures( QDockWidget::AllDockWidgetFeatures );
290
            m_glDock->addDockWidget( Qt::LeftDockWidgetArea, m_navAxial.get() );
291

292 293
            m_navCoronal = boost::shared_ptr< WQtNavGLWidget >( new WQtNavGLWidget( "Coronal View", "Coronal View", this, "Coronal Slice",
                                                                                    m_mainGLWidget.get() ) );
294
            m_navCoronal->setFeatures( QDockWidget::AllDockWidgetFeatures );
295
            m_glDock->addDockWidget( Qt::LeftDockWidgetArea, m_navCoronal.get() );
296

297
            m_navSagittal =
298 299
                boost::shared_ptr< WQtNavGLWidget >( new WQtNavGLWidget( "Sagittal View", "Sagittal View", this, "Sagittal Slice",
                                                                         m_mainGLWidget.get() ) );
300
            m_navSagittal->setFeatures( QDockWidget::AllDockWidgetFeatures );
301
            m_glDock->addDockWidget( Qt::LeftDockWidgetArea, m_navSagittal.get() );
302 303
        }
    }
304

305
    // Temporarily disabled. We need a proper command prompt implementation first.
306
    // create command prompt toolbar
307 308 309
    // 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
310

311
    // setup permanent toolbar
312
    m_permanentToolBar->addAction( m_loadButton );
313
    m_permanentToolBar->addSeparator();
314 315
    m_permanentToolBar->addAction( projectLoadButton );
    m_permanentToolBar->addAction( projectSaveButton );
316
    m_permanentToolBar->addSeparator();
317 318
    m_permanentToolBar->addAction( resetButton );
    m_permanentToolBar->addAction( roiButton );
319
    m_permanentToolBar->addSeparator();
320

321 322
    // after creating the GUI, restore its saved state
    restoreSavedState();
323
}
324

325 326 327
void WMainWindow::autoAdd( boost::shared_ptr< WModule > module, std::string proto )
{
    // get the prototype.
Alexander Wiebel's avatar
Alexander Wiebel committed
328
    if( !WKernel::getRunningKernel()->getRootContainer()->applyModule( module, proto, true ) )
329 330 331 332 333 334
    {
        WLogger::getLogger()->addLogMessage( "Auto Display active but module " + proto + " could not be added.",
                                             "GUI", LL_ERROR );
    }
}

335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352
void WMainWindow::moduleSpecificCleanup( boost::shared_ptr< WModule > module )
{
    // nav slices use separate buttons for slice on/off switching
    if( module->getName() == "Navigation Slices" )
    {
        boost::shared_ptr< WPropertyBase > prop;

        prop = module->getProperties()->findProperty( "showAxial" );
        m_permanentToolBar->removeAction( propertyActionMap[prop] );
        propertyActionMap.erase( prop );

        prop = module->getProperties()->findProperty( "showCoronal" );
        m_permanentToolBar->removeAction( propertyActionMap[prop] );
        propertyActionMap.erase( prop );

        prop = module->getProperties()->findProperty( "showSagittal" );
        m_permanentToolBar->removeAction( propertyActionMap[prop] );
        propertyActionMap.erase( prop );
353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371


        prop = module->getProperties()->findProperty( "Axial Slice" );
        if( m_navAxial )
        {
            m_navAxial->removeSliderProperty( prop );
        }

        prop = module->getProperties()->findProperty( "Coronal Slice" );
        if( m_navCoronal )
        {
            m_navCoronal->removeSliderProperty( prop );
        }

        prop = module->getProperties()->findProperty( "Sagittal Slice" );
        if( m_navSagittal )
        {
            m_navSagittal->removeSliderProperty( prop );
        }
372 373 374
    }
}

375 376
void WMainWindow::moduleSpecificSetup( boost::shared_ptr< WModule > module )
{
377 378 379 380
    // 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.
381
    bool useAutoDisplay = WQt4Gui::getSettings().value( "qt4gui/useAutoDisplay", true ).toBool();
Alexander Wiebel's avatar
Alexander Wiebel committed
382
    if( useAutoDisplay && module->getType() == MODULE_DATA )
383 384 385 386 387 388 389 390 391
    {
        WLogger::getLogger()->addLogMessage( "Auto Display active and Data module added. The proper module will be added.",
                                             "GUI", LL_DEBUG );

        // data modules contain an member denoting the real data type. Currently we only have one data module and a not very modulated data
        // structures.
        boost::shared_ptr< WMData > dataModule = boost::shared_static_cast< WMData >( module );

        // grab data and identify type
Alexander Wiebel's avatar
Alexander Wiebel committed
392
        if( dataModule->getDataSet()->isA< WDataSetSingle >() && dataModule->getDataSet()->isTexture() )
393 394 395
        {
            // it is a dataset single
            // load a nav slice module if a WDataSetSingle is available!?
396
            if( !m_navSlicesAlreadyLoaded )
397
            {
398
                autoAdd( module, "Navigation Slices" );
399
                m_navSlicesAlreadyLoaded = true;
400
            }
401
        }
Alexander Wiebel's avatar
Alexander Wiebel committed
402
        else if( dataModule->getDataSet()->isA< WDataSetFibers >() )
403 404
        {
            // it is a fiber dataset -> add the FiberDisplay module
405
            autoAdd( module, "Fiber Display" );
406
        }
Alexander Wiebel's avatar
Alexander Wiebel committed
407
        else if( dataModule->getDataSet()->isA< WEEG2 >() )
408
        {
409
            // it is a eeg dataset -> add the eegView module
410 411 412 413
            autoAdd( module, "EEG View" );
        }
    }

414
    // nav slices use separate buttons for slice on/off switching
Alexander Wiebel's avatar
Alexander Wiebel committed
415
    if( module->getName() == "Navigation Slices" )
416
    {
417
        boost::shared_ptr< WPropertyBase > prop = module->getProperties()->findProperty( "Slices/Show Axial" );
Alexander Wiebel's avatar
Alexander Wiebel committed
418
        if( !prop )
419 420
        {
               WLogger::getLogger()->
421
                   addLogMessage( "Navigation Slices module does not provide the property \"Show Axial\", which is required by the GUI.", "GUI",
422 423 424 425
                                  LL_ERROR );
        }
        else
        {
426 427 428
            WQtPropertyBoolAction* a = new WQtPropertyBoolAction( prop->toPropBool(), m_permanentToolBar );
            a->setToolTip( "Toggle Axial Slice" );
            a->setText( "Toggle Axial Slice" );
429
            a->setIcon( m_iconManager.getIcon( "axial icon" ) );
430
            m_permanentToolBar->addAction( a );
431
            propertyActionMap[prop] = a;
432
        }
433

434
        prop = module->getProperties()->findProperty( "Slices/Show Coronal" );
Alexander Wiebel's avatar
Alexander Wiebel committed
435
        if( !prop )
436 437
        {
               WLogger::getLogger()->
438
                   addLogMessage( "Navigation Slices module does not provide the property \"Show Coronal\", which is required by the GUI.", "GUI",
439 440 441 442
                                  LL_ERROR );
        }
        else
        {
443 444 445
            WQtPropertyBoolAction* a = new WQtPropertyBoolAction( prop->toPropBool(), m_permanentToolBar );
            a->setToolTip( "Toggle Coronal Slice" );
            a->setText( "Toggle Coronal Slice" );
446
            a->setIcon( m_iconManager.getIcon( "coronal icon" ) );
447
            m_permanentToolBar->addAction( a );
448
            propertyActionMap[prop] = a;
449
        }
450

451
        prop = module->getProperties()->findProperty( "Slices/Show Sagittal" );
Alexander Wiebel's avatar
Alexander Wiebel committed
452
        if( !prop )
453 454
        {
               WLogger::getLogger()->
455
                   addLogMessage( "Navigation Slices module does not provide the property \"Show Sagittal\", which is required by the GUI.", "GUI",
456 457 458 459
                                  LL_ERROR );
        }
        else
        {
460 461 462
            WQtPropertyBoolAction* a = new WQtPropertyBoolAction( prop->toPropBool(), m_permanentToolBar );
            a->setToolTip( "Toggle Saggital Slice" );
            a->setText( "Toggle Saggital Slice" );
463
            a->setIcon( m_iconManager.getIcon( "sagittal icon" ) );
464
            m_permanentToolBar->addAction( a );
465
            propertyActionMap[prop] = a;
466
        }
467 468

        // now setup the nav widget sliders
469
        prop = module->getProperties()->findProperty( "Slices/Axial Position" );
Alexander Wiebel's avatar
Alexander Wiebel committed
470
        if( !prop )
471 472
        {
               WLogger::getLogger()->
Sebastian Eichelbaum's avatar
[STYLE]  
Sebastian Eichelbaum committed
473
               addLogMessage( "Navigation Slices module does not provide the property \"Axial Position\", which is required by the GUI.", "GUI",
474 475 476 477
                                  LL_ERROR );
        }
        else
        {
478 479
            if( m_navAxial )
            {
480
                //m_navAxial->setSliderProperty( prop );
481
            }
482 483
        }

484
        prop = module->getProperties()->findProperty( "Slices/Coronal Position" );
Alexander Wiebel's avatar
Alexander Wiebel committed
485
        if( !prop )
486 487
        {
               WLogger::getLogger()->
Sebastian Eichelbaum's avatar
[STYLE]  
Sebastian Eichelbaum committed
488
               addLogMessage( "Navigation Slices module does not provide the property \"Coronal Position\", which is required by the GUI.", "GUI",
489 490 491 492
                                  LL_ERROR );
        }
        else
        {
493 494
            if( m_navCoronal )
            {
495
                //m_navCoronal->setSliderProperty( prop );
496
            }
497 498
        }

499
        prop = module->getProperties()->findProperty( "Slices/Sagittal Position" );
Alexander Wiebel's avatar
Alexander Wiebel committed
500
        if( !prop )
501 502
        {
               WLogger::getLogger()->
Sebastian Eichelbaum's avatar
[STYLE]  
Sebastian Eichelbaum committed
503
               addLogMessage( "Navigation Slices module does not provide the property \"Sagittal Position\", which is required by the GUI.", "GUI",
504 505 506 507
                                  LL_ERROR );
        }
        else
        {
508 509
            if( m_navSagittal )
            {
510
               //m_navSagittal->setSliderProperty( prop );
511
            }
512
        }
513
    }
wiebel's avatar
wiebel committed
514
}
515

516 517
void WMainWindow::setCompatiblesToolbar( WQtCombinerToolbar* toolbar )
{
Alexander Wiebel's avatar
Alexander Wiebel committed
518
    if( m_currentCompatiblesToolbar )
519 520 521 522 523
    {
        delete m_currentCompatiblesToolbar;
    }
    m_currentCompatiblesToolbar = toolbar;

Alexander Wiebel's avatar
Alexander Wiebel committed
524
    if( !toolbar )
525 526 527
    {
        // ok, reset the toolbar
        // So create a dummy to permanently reserve the space
528
        m_currentCompatiblesToolbar = new WQtCombinerToolbar( this );
529 530 531
    }

    // and the position of the toolbar
532
    addToolBar( Qt::TopToolBarArea, m_currentCompatiblesToolbar );
533
}
534

535 536 537 538 539
WQtCombinerToolbar* WMainWindow::getCompatiblesToolbar()
{
    return m_currentCompatiblesToolbar;
}

540
WQtControlPanel* WMainWindow::getControlPanel()
541
{
542
    return m_controlPanel;
543
}
544

545 546 547 548 549
WQtNetworkEditor* WMainWindow::getNetworkEditor()
{
    return m_networkEditor;
}

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

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

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

577
        boost::shared_ptr< WProjectFile > proj = boost::shared_ptr< WProjectFile >(
578
                new WProjectFile( filename )
579 580
        );

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

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

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

631 632 633 634 635 636
void WMainWindow::projectLoad()
{
    QFileDialog fd;
    fd.setFileMode( QFileDialog::ExistingFiles );

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

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

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

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

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

690
    std::vector< std::string > stdFileNames;
691 692

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

698
    m_loaderSignal( stdFileNames );
699
}
700

701 702 703 704
void WMainWindow::openAboutQtDialog()
{
    QMessageBox::aboutQt( this, "About Qt" );
}
705

706 707
void WMainWindow::openAboutDialog()
{
708
    std::string filename( WPathHelper::getDocPath().file_string() + "/qt4gui/OpenWalnutAbout.html" );
709
    std::string content = readFileIntoString( filename );
710
    QMessageBox::about( this, "About OpenWalnut", content.c_str() );
711 712
}

713
void WMainWindow::openOpenWalnutHelpDialog()
714
{
715
    std::string filename( WPathHelper::getDocPath().file_string() + "/qt4gui/OpenWalnutHelp.html" );
716
    std::string content = readFileIntoString( filename );
717 718

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

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

    window->show();

    QWebView *view = new QWebView( this );
728
    QString location( QString( "file://" ) + WPathHelper::getDocPath().file_string().c_str() + "/qt4gui/" );
729
    view->setHtml( content.c_str(), QUrl( location  ) );
730 731
    view->show();
    layout->addWidget( view );
732 733
}

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

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

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

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

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

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

788 789 790 791 792 793 794
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