WMainWindow.cpp 44.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/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_glDock->addDockWidget( Qt::LeftDockWidgetArea, m_navAxial.get() );
375

376 377
            m_navCoronal = boost::shared_ptr< WQtNavGLWidget >( new WQtNavGLWidget( "Coronal View", "Coronal View", this, "Coronal Slice",
                                                                                    m_mainGLWidget.get() ) );
378
            m_navCoronal->setFeatures( QDockWidget::AllDockWidgetFeatures );
379
            m_glDock->addDockWidget( Qt::LeftDockWidgetArea, m_navCoronal.get() );
380

ledig's avatar
ledig committed
381
            m_navSagittal =
382 383
                boost::shared_ptr< WQtNavGLWidget >( new WQtNavGLWidget( "Sagittal View", "Sagittal View", this, "Sagittal Slice",
                                                                         m_mainGLWidget.get() ) );
384
            m_navSagittal->setFeatures( QDockWidget::AllDockWidgetFeatures );
385
            m_glDock->addDockWidget( Qt::LeftDockWidgetArea, m_navSagittal.get() );
386

387 388 389
            bgColorMenu->addAction( m_navAxial->getGLWidget()->getBackgroundColorAction() );
            bgColorMenu->addAction( m_navCoronal->getGLWidget()->getBackgroundColorAction() );
            bgColorMenu->addAction( m_navSagittal->getGLWidget()->getBackgroundColorAction() );
390 391 392
        }
    }

393
    // Temporarily disabled. We need a proper command prompt implementation first.
394
    // create command prompt toolbar
395 396 397
    // 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
398

399
    // setup permanent toolbar
400
    m_permanentToolBar->addAction( m_loadButton );
401
    m_permanentToolBar->addSeparator();
402 403
    m_permanentToolBar->addAction( projectLoadButton );
    m_permanentToolBar->addAction( projectSaveButton );
404
    m_permanentToolBar->addSeparator();
405 406
    m_permanentToolBar->addAction( resetButton );
    m_permanentToolBar->addAction( roiButton );
407
    m_permanentToolBar->addSeparator();
408

409 410
    // after creating the GUI, restore its saved state
    restoreSavedState();
411
}
412

413 414 415
void WMainWindow::autoAdd( boost::shared_ptr< WModule > module, std::string proto )
{
    // get the prototype.
Alexander Wiebel's avatar
Alexander Wiebel committed
416
    if( !WKernel::getRunningKernel()->getRootContainer()->applyModule( module, proto, true ) )
417 418 419 420 421 422
    {
        WLogger::getLogger()->addLogMessage( "Auto Display active but module " + proto + " could not be added.",
                                             "GUI", LL_ERROR );
    }
}

423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440
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 );
441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459


        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 );
        }
460 461 462
    }
}

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

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

502
    // nav slices use separate buttons for slice on/off switching
Alexander Wiebel's avatar
Alexander Wiebel committed
503
    if( module->getName() == "Navigation Slices" )
504
    {
505
        boost::shared_ptr< WPropertyBase > prop = module->getProperties()->findProperty( "Slices/Show Axial" );
Alexander Wiebel's avatar
Alexander Wiebel committed
506
        if( !prop )
507 508
        {
               WLogger::getLogger()->
509
                   addLogMessage( "Navigation Slices module does not provide the property \"Show Axial\", which is required by the GUI.", "GUI",
510 511 512 513
                                  LL_ERROR );
        }
        else
        {
514 515 516
            WQtPropertyBoolAction* a = new WQtPropertyBoolAction( prop->toPropBool(), m_permanentToolBar );
            a->setToolTip( "Toggle Axial Slice" );
            a->setText( "Toggle Axial Slice" );
517
            a->setIcon( m_iconManager.getIcon( "axial icon" ) );
518
            m_permanentToolBar->addAction( a );
519
            propertyActionMap[prop] = a;
520
        }
521

522
        prop = module->getProperties()->findProperty( "Slices/Show Coronal" );
Alexander Wiebel's avatar
Alexander Wiebel committed
523
        if( !prop )
524 525
        {
               WLogger::getLogger()->
526
                   addLogMessage( "Navigation Slices module does not provide the property \"Show Coronal\", which is required by the GUI.", "GUI",
527 528 529 530
                                  LL_ERROR );
        }
        else
        {
531 532 533
            WQtPropertyBoolAction* a = new WQtPropertyBoolAction( prop->toPropBool(), m_permanentToolBar );
            a->setToolTip( "Toggle Coronal Slice" );
            a->setText( "Toggle Coronal Slice" );
534
            a->setIcon( m_iconManager.getIcon( "coronal icon" ) );
535
            m_permanentToolBar->addAction( a );
536
            propertyActionMap[prop] = a;
537
        }
538

539
        prop = module->getProperties()->findProperty( "Slices/Show Sagittal" );
Alexander Wiebel's avatar
Alexander Wiebel committed
540
        if( !prop )
541 542
        {
               WLogger::getLogger()->
543
                   addLogMessage( "Navigation Slices module does not provide the property \"Show Sagittal\", which is required by the GUI.", "GUI",
544 545 546 547
                                  LL_ERROR );
        }
        else
        {
548 549 550
            WQtPropertyBoolAction* a = new WQtPropertyBoolAction( prop->toPropBool(), m_permanentToolBar );
            a->setToolTip( "Toggle Saggital Slice" );
            a->setText( "Toggle Saggital Slice" );
551
            a->setIcon( m_iconManager.getIcon( "sagittal icon" ) );
552
            m_permanentToolBar->addAction( a );
553
            propertyActionMap[prop] = a;
554
        }
555 556

        // now setup the nav widget sliders
557
        prop = module->getProperties()->findProperty( "Slices/Axial Position" );
Alexander Wiebel's avatar
Alexander Wiebel committed
558
        if( !prop )
559 560
        {
               WLogger::getLogger()->
Sebastian Eichelbaum's avatar
[STYLE]  
Sebastian Eichelbaum committed
561
               addLogMessage( "Navigation Slices module does not provide the property \"Axial Position\", which is required by the GUI.", "GUI",
562 563 564 565
                                  LL_ERROR );
        }
        else
        {
566 567
            if( m_navAxial )
            {
568
                //m_navAxial->setSliderProperty( prop );
569
            }
570 571
        }

572
        prop = module->getProperties()->findProperty( "Slices/Coronal Position" );
Alexander Wiebel's avatar
Alexander Wiebel committed
573
        if( !prop )
574 575
        {
               WLogger::getLogger()->
Sebastian Eichelbaum's avatar
[STYLE]  
Sebastian Eichelbaum committed
576
               addLogMessage( "Navigation Slices module does not provide the property \"Coronal Position\", which is required by the GUI.", "GUI",
577 578 579 580
                                  LL_ERROR );
        }
        else
        {
581 582
            if( m_navCoronal )
            {
583
                //m_navCoronal->setSliderProperty( prop );
584
            }
585 586
        }

587
        prop = module->getProperties()->findProperty( "Slices/Sagittal Position" );
Alexander Wiebel's avatar
Alexander Wiebel committed
588
        if( !prop )
589 590
        {
               WLogger::getLogger()->
Sebastian Eichelbaum's avatar
[STYLE]  
Sebastian Eichelbaum committed
591
               addLogMessage( "Navigation Slices module does not provide the property \"Sagittal Position\", which is required by the GUI.", "GUI",
592 593 594 595
                                  LL_ERROR );
        }
        else
        {
596 597
            if( m_navSagittal )
            {
598
               //m_navSagittal->setSliderProperty( prop );
599
            }
600
        }
601
    }
wiebel's avatar
wiebel committed
602
}
603

604 605
void WMainWindow::setCompatiblesToolbar( WQtCombinerToolbar* toolbar )
{
Alexander Wiebel's avatar
Alexander Wiebel committed
606
    if( m_currentCompatiblesToolbar )
607 608 609 610 611
    {
        delete m_currentCompatiblesToolbar;
    }
    m_currentCompatiblesToolbar = toolbar;

Alexander Wiebel's avatar
Alexander Wiebel committed
612
    if( !toolbar )
613 614 615
    {
        // ok, reset the toolbar
        // So create a dummy to permanently reserve the space
616
        m_currentCompatiblesToolbar = new WQtCombinerToolbar( this );
617 618
    }

619 620 621 622 623
    // 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 ) ) );

624
    // and the position of the toolbar
625
    addToolBar( Qt::TopToolBarArea, m_currentCompatiblesToolbar );
626
}
627

628 629 630 631 632
WQtCombinerToolbar* WMainWindow::getCompatiblesToolbar()
{
    return m_currentCompatiblesToolbar;
}

633
WQtControlPanel* WMainWindow::getControlPanel()
634
{
635
    return m_controlPanel;
636
}
637

638 639 640 641 642
WQtNetworkEditor* WMainWindow::getNetworkEditor()
{
    return m_networkEditor;
}

643
void WMainWindow::projectSave( const std::vector< boost::shared_ptr< WProjectFileIO > >& writer )
644 645 646 647
{
    QFileDialog fd;
    fd.setWindowTitle( "Save Project as" );
    fd.setFileMode( QFileDialog::AnyFile );
648
    fd.setAcceptMode( QFileDialog::AcceptSave );
649 650

    QStringList filters;
651
    filters << "Project File (*.owproj *.owp)";
652 653 654
    fd.setNameFilters( filters );
    fd.setViewMode( QFileDialog::Detail );
    QStringList fileNames;
Alexander Wiebel's avatar
Alexander Wiebel committed
655
    if( fd.exec() )
656 657 658 659 660
    {
        fileNames = fd.selectedFiles();
    }

    QStringList::const_iterator constIterator;
Alexander Wiebel's avatar
Alexander Wiebel committed
661
    for( constIterator = fileNames.constBegin(); constIterator != fileNames.constEnd(); ++constIterator )
662
    {
663 664
        std::string filename = ( *constIterator ).toStdString();
        // append owp if not existent
665
        if( filename.rfind( ".owp" ) == std::string::npos )
666 667 668 669
        {
            filename += ".owp";
        }

670
        boost::shared_ptr< WProjectFile > proj = boost::shared_ptr< WProjectFile >(
671
                new WProjectFile( filename )
672 673
        );

674 675 676
        try
        {
            // This call is synchronous.
Alexander Wiebel's avatar
Alexander Wiebel committed
677
            if( writer.empty() )
678 679 680 681 682 683 684
            {
                proj->save();
            }
            else
            {
                proj->save( writer );
            }
685 686 687 688 689 690 691 692
        }
        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 );
        }
693 694 695
    }
}

696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716
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 );
}

717 718 719 720 721 722 723
void WMainWindow::projectSaveModuleOnly()
{
    std::vector< boost::shared_ptr< WProjectFileIO > > w;
    w.push_back( WProjectFile::getModuleWriter() );
    projectSave( w );
}

724 725 726 727 728 729
void WMainWindow::projectLoad()
{
    QFileDialog fd;
    fd.setFileMode( QFileDialog::ExistingFiles );

    QStringList filters;
730
    filters << "Simple Project File (*.owproj *.owp)"
731 732 733 734
            << "Any files (*)";
    fd.setNameFilters( filters );
    fd.setViewMode( QFileDialog::Detail );
    QStringList fileNames;
Alexander Wiebel's avatar
Alexander Wiebel committed
735
    if( fd.exec() )
736 737 738 739 740
    {
        fileNames = fd.selectedFiles();
    }

    QStringList::const_iterator constIterator;
Alexander Wiebel's avatar
Alexander Wiebel committed
741
    for( constIterator = fileNames.constBegin(); constIterator != fileNames.constEnd(); ++constIterator )
742
    {
743 744
        boost::shared_ptr< WProjectFile > proj = boost::shared_ptr< WProjectFile >(
                new WProjectFile( ( *constIterator ).toStdString() )
745
        );
746 747

        // This call is asynchronous. It parses the file and the starts a thread to actually do all the stuff
748
        proj->load();
749 750 751
    }
}

752
void WMainWindow::openLoadDialog()
753
{
754 755 756 757 758 759 760 761 762 763 764
#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
765 766
    QFileDialog fd;
    fd.setFileMode( QFileDialog::ExistingFiles );
wiebel's avatar
wiebel committed
767 768

    QStringList filters;
769 770
    filters << "Known file types (*.cnt *.edf *.asc *.nii *.nii.gz *.fib)"
            << "EEG files (*.cnt *.edf *.asc)"
wiebel's avatar
wiebel committed
771
            << "NIfTI (*.nii *.nii.gz)"
772 773
            << "Fibers (*.fib)"
            << "Any files (*)";
wiebel's avatar
wiebel committed
774
    fd.setNameFilters( filters );
775 776
    fd.setViewMode( QFileDialog::Detail );
    QStringList fileNames;
Alexander Wiebel's avatar
Alexander Wiebel committed
777
    if( fd.exec() )
778 779 780
    {
        fileNames = fd.selectedFiles();
    }
781
#endif
782

783
    std::vector< std::string > stdFileNames;
784 785

    QStringList::const_iterator constIterator;
Alexander Wiebel's avatar
Alexander Wiebel committed
786
    for( constIterator = fileNames.constBegin(); constIterator != fileNames.constEnd(); ++constIterator )