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

46 47
#include "../../common/WColor.h"
#include "../../common/WPreferences.h"
48
#include "../../common/WProjectFileIO.h"
49 50
#include "../../common/WPathHelper.h"
#include "../../common/exceptions/WFileNotFound.h"
Mathias Goldau's avatar
Mathias Goldau committed
51 52 53
#include "../../dataHandler/WDataSetFibers.h"
#include "../../dataHandler/WDataSetSingle.h"
#include "../../dataHandler/WEEG2.h"
schurade's avatar
schurade committed
54
#include "../../graphicsEngine/WGEZoomTrackballManipulator.h"
55 56 57
#include "../../graphicsEngine/WROIBox.h"
#include "../../kernel/modules/data/WMData.h"
#include "../../kernel/modules/navSlices/WMNavSlices.h"
58
#include "../../kernel/WKernel.h"
59 60 61
#include "../../kernel/WModule.h"
#include "../../kernel/WModuleCombiner.h"
#include "../../kernel/WModuleCombinerTypes.h"
62
#include "../../kernel/WProjectFile.h"
63 64
#include "../../kernel/WROIManager.h"
#include "../../kernel/WSelectionManager.h"
65
#include "../icons/WIcons.h"
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 77 78
#include "WQtCustomDockWidget.h"
#include "WQtNavGLWidget.h"

#include "WMainWindow.h"
79

80
WMainWindow::WMainWindow() :
81
    QMainWindow(),
82
    m_currentCompatiblesToolbar( NULL ),
83
    m_iconManager()
Sebastian Eichelbaum's avatar
Sebastian Eichelbaum committed
84 85
{
}
86

87 88 89 90 91
WMainWindow::~WMainWindow()
{
    // cleanup
}

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

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

114 115
    setDockOptions( QMainWindow::AnimatedDocks |  QMainWindow::AllowNestedDocks | QMainWindow::AllowTabbedDocks );

116 117 118
    //network Editor
    m_networkEditor = new WQtNetworkEditor( this );
    m_networkEditor->setFeatures( QDockWidget::AllDockWidgetFeatures );
119

120 121 122 123
    // the control panel instance is needed for the menu
    m_controlPanel = new WQtControlPanel( this );
    m_controlPanel->setFeatures( QDockWidget::AllDockWidgetFeatures );
    m_controlPanel->addSubject( "Default Subject" );
124

125 126 127 128 129 130 131 132 133 134 135
    // add all docks
    addDockWidget( Qt::RightDockWidgetArea, m_controlPanel->getModuleDock() );
    addDockWidget( Qt::RightDockWidgetArea, m_networkEditor );
    tabifyDockWidget( m_networkEditor, m_controlPanel->getModuleDock() );

    addDockWidget( Qt::RightDockWidgetArea, m_controlPanel->getTextureSorterDock() );
    addDockWidget( Qt::RightDockWidgetArea, m_controlPanel->getRoiDock() );
    tabifyDockWidget( m_controlPanel->getTextureSorterDock(), m_controlPanel->getRoiDock() );

    addDockWidget( Qt::RightDockWidgetArea, m_controlPanel );

136 137 138 139
    setupPermanentToolBar();

    // 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.
140
    m_controlPanel->selectUpperMostEntry();
141

Sebastian Eichelbaum's avatar
Sebastian Eichelbaum committed
142 143 144 145
    // 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.

146
    m_menuBar = new QMenuBar( this );
147 148 149 150 151 152

    // hide menu?
    bool hideMenu = false;
    WPreferences::getPreference( "qt4gui.hideMenuBar", &hideMenu );
    m_menuBar->setVisible( !hideMenu );

153
    QMenu* fileMenu = m_menuBar->addMenu( "File" );
154

Sebastian Eichelbaum's avatar
Sebastian Eichelbaum committed
155 156
    fileMenu->addAction( m_iconManager.getIcon( "load" ), "Load Dataset", this, SLOT( openLoadDialog() ), QKeySequence(  QKeySequence::Open ) );
    fileMenu->addSeparator();
157
    fileMenu->addAction( m_iconManager.getIcon( "loadProject" ), "Load Project", this, SLOT( projectLoad() ) );
158 159
    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
160 161 162 163
    saveMenu->addAction( "Save Modules Only", this, SLOT( projectSaveModuleOnly() ) );
    saveMenu->addAction( "Save Camera Only", this, SLOT( projectSaveCameraOnly() ) );
    saveMenu->addAction( "Save ROIs Only", this, SLOT( projectSaveROIOnly() ) );
    fileMenu->addSeparator();
164
    fileMenu->addAction( m_iconManager.getIcon( "config" ), "Config", this, SLOT( openConfigDialog() ) );
Sebastian Eichelbaum's avatar
Sebastian Eichelbaum committed
165
    fileMenu->addSeparator();
166 167 168
    // 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
169

Sebastian Eichelbaum's avatar
Sebastian Eichelbaum committed
170
    // This QAction stuff is quite ugly and complicated some times ... There is no nice constructor which takes name, slot keysequence and so on
171 172
    // directly -> set shortcuts, and some further properties using QAction's interface
    QMenu* viewMenu = m_menuBar->addMenu( "View" );
173

174 175 176 177 178
    QAction* controlPanelTrigger = m_controlPanel->toggleViewAction();
    QList< QKeySequence > controlPanelShortcut;
    controlPanelShortcut.append( QKeySequence( Qt::Key_F9 ) );
    controlPanelTrigger->setShortcuts( controlPanelShortcut );
    viewMenu->addAction( controlPanelTrigger );
179
    viewMenu->addSeparator();
180
    this->addAction( controlPanelTrigger );  // this enables the action even if the menu bar is invisible
181

Sebastian Eichelbaum's avatar
Sebastian Eichelbaum committed
182 183 184
    // 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 ).
185 186 187 188 189 190 191
    // By additionally adding the action to the main window, we ensure the action can be triggered even if the menu bar is hidden.
    this->addAction( viewMenu->addAction( "Left", this, SLOT( setPresetViewLeft() ),           QKeySequence( Qt::CTRL + Qt::SHIFT + Qt::Key_L ) ) );
    this->addAction( viewMenu->addAction( "Right", this, SLOT( setPresetViewRight() ),         QKeySequence( Qt::CTRL + Qt::SHIFT + Qt::Key_R ) ) );
    this->addAction( viewMenu->addAction( "Superior", this, SLOT( setPresetViewSuperior() ),   QKeySequence( Qt::CTRL + Qt::SHIFT + Qt::Key_S ) ) );
    this->addAction( viewMenu->addAction( "Inferior", this, SLOT( setPresetViewInferior() ),   QKeySequence( Qt::CTRL + Qt::SHIFT + Qt::Key_I ) ) );
    this->addAction( viewMenu->addAction( "Anterior", this, SLOT( setPresetViewAnterior() ),   QKeySequence( Qt::CTRL + Qt::SHIFT + Qt::Key_A ) ) );
    this->addAction( viewMenu->addAction( "Posterior", this, SLOT( setPresetViewPosterior() ), QKeySequence( Qt::CTRL + Qt::SHIFT + Qt::Key_P ) ) );
192

193
    QMenu* helpMenu = m_menuBar->addMenu( "Help" );
194
    helpMenu->addAction( m_iconManager.getIcon( "help" ), "OpenWalnut Help", this, SLOT( openOpenWalnutHelpDialog() ),
195 196 197 198
                         QKeySequence( QKeySequence::HelpContents ) );
    helpMenu->addSeparator();
    helpMenu->addAction( m_iconManager.getIcon( "logo" ), "About OpenWalnut", this, SLOT( openAboutDialog() ) );
    helpMenu->addAction( "About Qt", this, SLOT( openAboutQtDialog() ) );
199

200 201
    setMenuBar( m_menuBar );

202 203 204 205 206
    // initially 3 navigation views
    {
        bool hideWidget;
        if( !( WPreferences::getPreference( "qt4gui.hideAxial", &hideWidget ) && hideWidget) )
        {
ledig's avatar
ledig committed
207
#ifndef _MSC_VER
208
            m_navAxial = boost::shared_ptr< WQtNavGLWidget >( new WQtNavGLWidget( "Axial View", this, "Axial Slice", m_mainGLWidget.get() ) );
ledig's avatar
ledig committed
209 210 211
#else
            m_navAxial = boost::shared_ptr< WQtNavGLWidget >( new WQtNavGLWidget( "Axial View", this, "Axial Slice" ) );
#endif
212
            m_navAxial->setFeatures( QDockWidget::AllDockWidgetFeatures );
213 214 215 216
            addDockWidget( Qt::LeftDockWidgetArea, m_navAxial.get() );
        }
        if( !( WPreferences::getPreference( "qt4gui.hideCoronal", &hideWidget ) && hideWidget) )
        {
ledig's avatar
ledig committed
217
#ifndef _MSC_VER
218
            m_navCoronal = boost::shared_ptr< WQtNavGLWidget >( new WQtNavGLWidget( "Coronal View", this, "Coronal Slice", m_mainGLWidget.get() ) );
ledig's avatar
ledig committed
219 220 221
#else
            m_navCoronal = boost::shared_ptr< WQtNavGLWidget >( new WQtNavGLWidget( "Coronal View", this, "Coronal Slice" ) );
#endif
222
            m_navCoronal->setFeatures( QDockWidget::AllDockWidgetFeatures );
223 224 225 226
            addDockWidget( Qt::LeftDockWidgetArea, m_navCoronal.get() );
        }
        if( !( WPreferences::getPreference( "qt4gui.hideSagittal", &hideWidget ) && hideWidget) )
        {
ledig's avatar
ledig committed
227
#ifndef _MSC_VER
228 229
            m_navSagittal =
                boost::shared_ptr< WQtNavGLWidget >( new WQtNavGLWidget( "Sagittal View", this, "Sagittal Slice", m_mainGLWidget.get() ) );
ledig's avatar
ledig committed
230 231 232 233
#else
            m_navSagittal =
                boost::shared_ptr< WQtNavGLWidget >( new WQtNavGLWidget( "Sagittal View", this, "Sagittal Slice" ) );
#endif
234
            m_navSagittal->setFeatures( QDockWidget::AllDockWidgetFeatures );
235 236 237
            addDockWidget( Qt::LeftDockWidgetArea, m_navSagittal.get() );
        }
    }
238

239
    // Default background color from config file
240 241 242 243 244 245 246 247 248 249
    WColor bgColor( 1.0, 1.0, 1.0, 1.0 );
    double r;
    double g;
    double b;
    if( WPreferences::getPreference( "ge.bgColor.r", &r )
        && WPreferences::getPreference( "ge.bgColor.g", &g )
        && WPreferences::getPreference( "ge.bgColor.b", &b ) )
    {
        bgColor.set( r, g, b, 1.0 );
        m_mainGLWidget->setBgColor( bgColor );
250

251 252 253
        if( m_navAxial )
        {
            m_navAxial->getGLWidget()->setBgColor( bgColor );
254
        }
255 256 257
        if( m_navCoronal )
        {
            m_navCoronal->getGLWidget()->setBgColor( bgColor );
258
        }
259 260 261 262 263 264
        if( m_navSagittal )
        {
            m_navSagittal->getGLWidget()->setBgColor( bgColor );
        }
    }

265 266 267 268 269
    // create command prompt toolbar
    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

270
    // after creating the GUI, restore its saved state
271
    restoreSavedState();
272
}
273

274
void WMainWindow::setupPermanentToolBar()
275
{
276 277 278
    m_mainGLWidget = boost::shared_ptr< WQtGLWidget >( new WQtGLWidget( "main", this, WGECamera::ORTHOGRAPHIC ) );
    setCentralWidget( m_mainGLWidget.get() );

279
    m_permanentToolBar = new WQtToolBar( "Permanent Toolbar", this );
280

281 282 283 284
    // Set the style of the toolbar
    // NOTE: this only works if the toolbar is used with QActions instead of buttons and other widgets
    m_permanentToolBar->setToolButtonStyle( getToolbarStyle() );

285
    m_iconManager.addIcon( std::string( "ROI icon" ), box_xpm );
286
    m_iconManager.addIcon( std::string( "Reset icon" ), o_xpm );
287 288 289
    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 );
290

291 292 293
    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( "Reset icon" ), "Reset", m_permanentToolBar );
294
    resetButton->setShortcut( QKeySequence( Qt::Key_Escape ) );
295 296
    QAction* projectLoadButton = new QAction( m_iconManager.getIcon( "loadProject" ), "loadProject", m_permanentToolBar );
    QAction* projectSaveButton = new QAction( m_iconManager.getIcon( "saveProject" ), "saveProject", m_permanentToolBar );
297

298
    // setup save button
299
    QMenu* saveMenu = new QMenu( "Save Project" );
300
    saveMenu->addAction( "Save Project", this, SLOT( projectSaveAll() ) );
301
    saveMenu->addAction( "Save Modules", this, SLOT( projectSaveModuleOnly() ) );
302 303 304 305
    saveMenu->addAction( "Save Camera", this, SLOT( projectSaveCameraOnly() ) );
    saveMenu->addAction( "Save ROIs", this, SLOT( projectSaveROIOnly() ) );
    projectSaveButton->setMenu( saveMenu );

306 307 308 309 310
    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() ) );
311

312
    m_loadButton->setToolTip( "Load Data" );
313
    resetButton->setToolTip( "Reset main view" );
314
    roiButton->setToolTip( "Create New ROI" );
315 316
    projectLoadButton->setToolTip( "Load a project from file" );
    projectSaveButton->setToolTip( "Save current project to file" );
317

318
    m_permanentToolBar->addAction( m_loadButton );
319
    m_permanentToolBar->addSeparator();
320 321
    m_permanentToolBar->addAction( projectLoadButton );
    m_permanentToolBar->addAction( projectSaveButton );
322
    m_permanentToolBar->addSeparator();
323 324
    m_permanentToolBar->addAction( resetButton );
    m_permanentToolBar->addAction( roiButton );
325
    m_permanentToolBar->addSeparator();
326

327
    addToolBar( Qt::TopToolBarArea, m_permanentToolBar );
328
}
329

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

340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357
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 );
358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376


        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 );
        }
377 378 379
    }
}

380 381
void WMainWindow::moduleSpecificSetup( boost::shared_ptr< WModule > module )
{
382 383 384 385 386 387
    // 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.
    bool useAutoDisplay = true;
    WPreferences::getPreference( "qt4gui.useAutoDisplay", &useAutoDisplay );
Alexander Wiebel's avatar
Alexander Wiebel committed
388
    if( useAutoDisplay && module->getType() == MODULE_DATA )
389 390 391 392 393 394 395 396 397
    {
        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
398
        if( dataModule->getDataSet()->isA< WDataSetSingle >() && dataModule->getDataSet()->isTexture() )
399 400 401 402
        {
            // it is a dataset single
            // load a nav slice module if a WDataSetSingle is available!?

403
            // if it not already is running: add it
Alexander Wiebel's avatar
Alexander Wiebel committed
404
            if( !WMNavSlices::isRunning() )
405
            {
406
                autoAdd( module, "Navigation Slices" );
407
            }
408
        }
Alexander Wiebel's avatar
Alexander Wiebel committed
409
        else if( dataModule->getDataSet()->isA< WDataSetFibers >() )
410 411
        {
            // it is a fiber dataset -> add the FiberDisplay module
412
            autoAdd( module, "Fiber Display" );
413
        }
Alexander Wiebel's avatar
Alexander Wiebel committed
414
        else if( dataModule->getDataSet()->isA< WEEG2 >() )
415
        {
416
            // it is a eeg dataset -> add the eegView module
417 418 419 420
            autoAdd( module, "EEG View" );
        }
    }

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

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

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

        // now setup the nav widget sliders
476
        prop = module->getProperties()->findProperty( "Axial Slice" );
Alexander Wiebel's avatar
Alexander Wiebel committed
477
        if( !prop )
478 479
        {
               WLogger::getLogger()->
480
                   addLogMessage( "Navigation Slices module does not provide the property \"Axial Slice\", which is required by the GUI.", "GUI",
481 482 483 484
                                  LL_ERROR );
        }
        else
        {
485 486
            if( m_navAxial )
            {
487
                m_navAxial->setSliderProperty( prop );
488
            }
489 490
        }

491
        prop = module->getProperties()->findProperty( "Coronal Slice" );
Alexander Wiebel's avatar
Alexander Wiebel committed
492
        if( !prop )
493 494
        {
               WLogger::getLogger()->
495
                   addLogMessage( "Navigation Slices module does not provide the property \"Coronal Slice\", which is required by the GUI.", "GUI",
496 497 498 499
                                  LL_ERROR );
        }
        else
        {
500 501
            if( m_navCoronal )
            {
502
                m_navCoronal->setSliderProperty( prop );
503
            }
504 505
        }

506
        prop = module->getProperties()->findProperty( "Sagittal Slice" );
Alexander Wiebel's avatar
Alexander Wiebel committed
507
        if( !prop )
508 509
        {
               WLogger::getLogger()->
510
                   addLogMessage( "Navigation Slices module does not provide the property \"Sagittal Slice\", which is required by the GUI.", "GUI",
511 512 513 514
                                  LL_ERROR );
        }
        else
        {
515 516
            if( m_navSagittal )
            {
517
               m_navSagittal->setSliderProperty( prop );
518
            }
519
        }
520
    }
wiebel's avatar
wiebel committed
521
}
522

523 524 525 526 527
Qt::ToolButtonStyle WMainWindow::getToolbarStyle() const
{
    // this sets the toolbar style
    int toolBarStyle = 0;
    WPreferences::getPreference( "qt4gui.toolBarStyle", &toolBarStyle );
Alexander Wiebel's avatar
Alexander Wiebel committed
528
    if( ( toolBarStyle < 0 ) || ( toolBarStyle > 3 ) ) // ensure a valid value
529 530 531 532 533 534 535 536
    {
        toolBarStyle = 0;
    }

    // cast and return
    return static_cast< Qt::ToolButtonStyle >( toolBarStyle );
}

537 538
void WMainWindow::setCompatiblesToolbar( WQtCombinerToolbar* toolbar )
{
Alexander Wiebel's avatar
Alexander Wiebel committed
539
    if( m_currentCompatiblesToolbar )
540 541 542 543 544
    {
        delete m_currentCompatiblesToolbar;
    }
    m_currentCompatiblesToolbar = toolbar;

Alexander Wiebel's avatar
Alexander Wiebel committed
545
    if( !toolbar )
546 547 548
    {
        // ok, reset the toolbar
        // So create a dummy to permanently reserve the space
549
        m_currentCompatiblesToolbar = new WQtCombinerToolbar( this );
550 551 552
    }

    // and the position of the toolbar
553
    addToolBar( Qt::TopToolBarArea, m_currentCompatiblesToolbar );
554
}
555

556 557 558 559 560
WQtCombinerToolbar* WMainWindow::getCompatiblesToolbar()
{
    return m_currentCompatiblesToolbar;
}

561
WQtControlPanel* WMainWindow::getControlPanel()
562
{
563
    return m_controlPanel;
564
}
565

566 567 568 569 570
WQtNetworkEditor* WMainWindow::getNetworkEditor()
{
    return m_networkEditor;
}

571
void WMainWindow::projectSave( const std::vector< boost::shared_ptr< WProjectFileIO > >& writer )
572 573 574 575
{
    QFileDialog fd;
    fd.setWindowTitle( "Save Project as" );
    fd.setFileMode( QFileDialog::AnyFile );
576
    fd.setAcceptMode( QFileDialog::AcceptSave );
577 578

    QStringList filters;
579
    filters << "Project File (*.owproj *.owp)";
580 581 582
    fd.setNameFilters( filters );
    fd.setViewMode( QFileDialog::Detail );
    QStringList fileNames;
Alexander Wiebel's avatar
Alexander Wiebel committed
583
    if( fd.exec() )
584 585 586 587 588
    {
        fileNames = fd.selectedFiles();
    }

    QStringList::const_iterator constIterator;
Alexander Wiebel's avatar
Alexander Wiebel committed
589
    for( constIterator = fileNames.constBegin(); constIterator != fileNames.constEnd(); ++constIterator )
590
    {
591 592 593 594 595 596 597
        std::string filename = ( *constIterator ).toStdString();
        // append owp if not existent
        if ( filename.rfind( ".owp" ) == std::string::npos )
        {
            filename += ".owp";
        }

598
        boost::shared_ptr< WProjectFile > proj = boost::shared_ptr< WProjectFile >(
599
                new WProjectFile( filename )
600 601
        );

602 603 604
        try
        {
            // This call is synchronous.
Alexander Wiebel's avatar
Alexander Wiebel committed
605
            if( writer.empty() )
606 607 608 609 610 611 612
            {
                proj->save();
            }
            else
            {
                proj->save( writer );
            }
613 614 615 616 617 618 619 620
        }
        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 );
        }
621 622 623
    }
}

624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644
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 );
}

645 646 647 648 649 650 651
void WMainWindow::projectSaveModuleOnly()
{
    std::vector< boost::shared_ptr< WProjectFileIO > > w;
    w.push_back( WProjectFile::getModuleWriter() );
    projectSave( w );
}

652 653 654 655 656 657
void WMainWindow::projectLoad()
{
    QFileDialog fd;
    fd.setFileMode( QFileDialog::ExistingFiles );

    QStringList filters;
658
    filters << "Simple Project File (*.owproj *.owp)"
659 660 661 662
            << "Any files (*)";
    fd.setNameFilters( filters );
    fd.setViewMode( QFileDialog::Detail );
    QStringList fileNames;
Alexander Wiebel's avatar
Alexander Wiebel committed
663
    if( fd.exec() )
664 665 666 667 668
    {
        fileNames = fd.selectedFiles();
    }

    QStringList::const_iterator constIterator;
Alexander Wiebel's avatar
Alexander Wiebel committed
669
    for( constIterator = fileNames.constBegin(); constIterator != fileNames.constEnd(); ++constIterator )
670
    {
671 672
        boost::shared_ptr< WProjectFile > proj = boost::shared_ptr< WProjectFile >(
                new WProjectFile( ( *constIterator ).toStdString() )
673
        );
674 675

        // This call is asynchronous. It parses the file and the starts a thread to actually do all the stuff
676
        proj->load();
677 678 679
    }
}

680
void WMainWindow::openLoadDialog()
681
{
682 683 684 685 686 687 688 689 690 691 692
#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
693 694
    QFileDialog fd;
    fd.setFileMode( QFileDialog::ExistingFiles );
wiebel's avatar
wiebel committed
695 696

    QStringList filters;
697 698
    filters << "Known file types (*.cnt *.edf *.asc *.nii *.nii.gz *.fib)"
            << "EEG files (*.cnt *.edf *.asc)"
wiebel's avatar
wiebel committed
699
            << "NIfTI (*.nii *.nii.gz)"
700 701
            << "Fibers (*.fib)"
            << "Any files (*)";
wiebel's avatar
wiebel committed
702
    fd.setNameFilters( filters );
703 704
    fd.setViewMode( QFileDialog::Detail );
    QStringList fileNames;
Alexander Wiebel's avatar
Alexander Wiebel committed
705
    if( fd.exec() )
706 707 708
    {
        fileNames = fd.selectedFiles();
    }
709
#endif
710

711
    std::vector< std::string > stdFileNames;
712 713

    QStringList::const_iterator constIterator;
Alexander Wiebel's avatar
Alexander Wiebel committed
714
    for( constIterator = fileNames.constBegin(); constIterator != fileNames.constEnd(); ++constIterator )
715 716 717
    {
        stdFileNames.push_back( ( *constIterator ).toLocal8Bit().constData() );
    }
718

719
    m_loaderSignal( stdFileNames );
720
}
721

722 723 724 725
void WMainWindow::openAboutQtDialog()
{
    QMessageBox::aboutQt( this, "About Qt" );
}
726 727 728 729
void WMainWindow::openAboutDialog()
{
    QMessageBox::about( this, "About OpenWalnut",
                        "OpenWalnut ( http://www.openwalnut.org )\n\n"
730
                        "Copyright 2009-2010 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS. "
731 732 733 734 735 736 737 738 739 740
                        "For more information see http://www.openwalnut.org/copying.\n\n"
                        "This program comes with ABSOLUTELY NO WARRANTY. "
                        "This is free software, and you are welcome to redistribute it "
                        "under the terms of the GNU Lesser General Public License. "
                        "You should have received a copy of the GNU Lesser General Public License "
                        "along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.\n"
                        "\n"
                        "Thank you for using OpenWalnut." );
}

741
void WMainWindow::openOpenWalnutHelpDialog()
742
{
743 744 745 746 747 748
    std::string filename( WPathHelper::getAppPath().file_string() + "/../share/OpenWalnut/OpenWalnutHelp.html" );
    std::ifstream input( filename.c_str() );
    if ( !input.is_open() )
    {
        throw WFileNotFound( std::string( "The project file \"" ) + filename +
            std::string( "\" does not exist." ) );
749 750 751 752 753 754 755 756
    }

    std::string buf;
    std::string line;
    while( std::getline( input, line ) )
    {
        buf += line;
    }
757 758

    QMessageBox::information( this, "OpenWalnut Help", buf.c_str() );
759 760
}

761 762 763 764
void WMainWindow::setPresetViewLeft()
{
    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.5, -0.5, -0.5, 0.5 );
    cm->setRotation( q );
768 769 770 771 772 773
}

void WMainWindow::setPresetViewRight()
{
    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.5, -0.5, -0.5, -0.5 );
    cm->setRotation( q );
777 778 779 780 781 782
}

void WMainWindow::setPresetViewSuperior()
{
    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., 0., 0., 1 );
    cm->setRotation( q );
786 787 788 789 790 791
}

void WMainWindow::setPresetViewInferior()
{
    boost::shared_ptr< WGEViewer > viewer;
    viewer = WKernel::getRunningKernel()->getGraphicsEngine()->getViewerByName( "main" );
schurade's avatar
schurade committed
792 793 794
    osg::ref_ptr<osgGA::TrackballManipulator>  cm = osg::dynamic_pointer_cast<osgGA::TrackballManipulator>( viewer->getCameraManipulator() );
    osg::Quat q( 0., -1., 0., 0. );
    cm->setRotation( q );
795 796 797 798 799 800
}

void WMainWindow::setPresetViewAnterior()
{
    boost::shared_ptr< WGEViewer > viewer;
    viewer = WKernel::getRunningKernel()->getGraphicsEngine()->getViewerByName( "main" );
schurade's avatar
schurade committed
801 802 803
    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 );
804 805 806 807 808 809
}

void WMainWindow::setPresetViewPosterior()
{
    boost::shared_ptr< WGEViewer > viewer;
    viewer = WKernel::getRunningKernel()->getGraphicsEngine()->getViewerByName( "main" );
schurade's avatar
schurade committed
810 811 812
    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 );
813 814
}

815 816 817 818 819 820 821
void WMainWindow::openNotImplementedDialog()
{
    QMessageBox::information( this, "Not yet implemented!",
                              "This functionality is planned for future versions of OpenWalnut. "