WMainWindow.cpp 43 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"
79
#include "WSettingAction.h"
80
#include "WSettingMenu.h"
Mathias Goldau's avatar
Mathias Goldau committed
81 82

#include "WMainWindow.h"
83
#include "WMainWindow.moc"
84

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

93 94 95 96 97
WMainWindow::~WMainWindow()
{
    // cleanup
}

98
void WMainWindow::setupGUI()
99
{
100 101 102 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
    /////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // 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() );

133 134 135 136 137 138 139 140 141 142 143 144 145 146 147
    // 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 ) ) );

148 149 150 151
    /////////////////////////////////////////////////////////////////////////////////////////////////////////////////
    // GUI setup
    /////////////////////////////////////////////////////////////////////////////////////////////////////////////////

152
    m_iconManager.addIcon( std::string( "load" ), fileopen_xpm );
153
    m_iconManager.addIcon( std::string( "loadProject" ), projOpen_xpm );
154
    m_iconManager.addIcon( std::string( "saveProject" ), projSave_xpm );
155
    m_iconManager.addIcon( std::string( "logo" ), logoIcon_xpm );
156
    m_iconManager.addIcon( std::string( "help" ), question_xpm );
157
    m_iconManager.addIcon( std::string( "quit" ), quit_xpm );
158 159 160
    m_iconManager.addIcon( std::string( "moduleBusy" ), moduleBusy_xpm );
    m_iconManager.addIcon( std::string( "moduleCrashed" ), moduleCrashed_xpm );
    m_iconManager.addIcon( std::string( "remove" ), remove_xpm );
161
    m_iconManager.addIcon( std::string( "config" ), preferences_system_xpm );
162
    m_iconManager.addIcon( std::string( "view" ), camera_xpm );
163

164
    if( objectName().isEmpty() )
165
    {
166
        setObjectName( QString::fromUtf8( "MainWindow" ) );
167
    }
168
    // TODO(all): what is this?
169 170
    resize( 946, 632 );
    setWindowIcon( m_iconManager.getIcon( "logo" ) );
171
    setWindowTitle( QApplication::translate( "MainWindow", "OpenWalnut (development version)", 0, QApplication::UnicodeUTF8 ) );
172

173 174
    setDockOptions( QMainWindow::AnimatedDocks |  QMainWindow::AllowNestedDocks | QMainWindow::AllowTabbedDocks );

175 176 177
    //network Editor
    m_networkEditor = new WQtNetworkEditor( this );
    m_networkEditor->setFeatures( QDockWidget::AllDockWidgetFeatures );
178

179 180 181 182
    // the control panel instance is needed for the menu
    m_controlPanel = new WQtControlPanel( this );
    m_controlPanel->setFeatures( QDockWidget::AllDockWidgetFeatures );
    m_controlPanel->addSubject( "Default Subject" );
183

184 185 186 187 188
    // add all docks
    addDockWidget( Qt::RightDockWidgetArea, m_controlPanel->getModuleDock() );
    addDockWidget( Qt::RightDockWidgetArea, m_networkEditor );
    tabifyDockWidget( m_networkEditor, m_controlPanel->getModuleDock() );

189
    addDockWidget( Qt::RightDockWidgetArea, m_controlPanel->getColormapperDock() );
190
    addDockWidget( Qt::RightDockWidgetArea, m_controlPanel->getRoiDock() );
191
    tabifyDockWidget( m_controlPanel->getColormapperDock(), m_controlPanel->getRoiDock() );
192 193 194

    addDockWidget( Qt::RightDockWidgetArea, m_controlPanel );

195
    m_glDock = new QMainWindow();
196
    m_glDock->setObjectName( "GLDock" );
197 198 199 200 201 202 203
    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 );
204

205
    m_permanentToolBar = new WQtToolBar( "Standard Toolbar", this );
206
    addToolBar( Qt::TopToolBarArea, m_permanentToolBar );
207 208 209 210 211 212 213

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

214
    m_loadButton = new QAction( m_iconManager.getIcon( "load" ), "Load", m_permanentToolBar );
215 216 217
    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 ) );
218 219
    QAction* projectLoadButton = new QAction( m_iconManager.getIcon( "loadProject" ), "Load Project", m_permanentToolBar );
    QAction* projectSaveButton = new QAction( m_iconManager.getIcon( "saveProject" ), "Save Project", m_permanentToolBar );
220 221 222 223 224 225 226 227 228 229 230 231

    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" );
232 233 234

    // 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.
235
    m_controlPanel->selectUpperMostEntry();
236

Sebastian Eichelbaum's avatar
Sebastian Eichelbaum committed
237 238 239 240
    // 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.

241
    m_menuBar = new QMenuBar( this );
242 243

    // hide menu?
244 245 246
    m_menuBar->setVisible( hideMenuAction->get() );
    connect( hideMenuAction, SIGNAL( change( bool ) ), m_menuBar, SLOT( setVisible( bool ) ) );
    addAction( hideMenuAction );
247

248
    QMenu* fileMenu = m_menuBar->addMenu( "File" );
249

Sebastian Eichelbaum's avatar
Sebastian Eichelbaum committed
250 251
    fileMenu->addAction( m_iconManager.getIcon( "load" ), "Load Dataset", this, SLOT( openLoadDialog() ), QKeySequence(  QKeySequence::Open ) );
    fileMenu->addSeparator();
252
    fileMenu->addAction( m_iconManager.getIcon( "loadProject" ), "Load Project", this, SLOT( projectLoad() ) );
253 254
    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
255 256 257
    saveMenu->addAction( "Save Modules Only", this, SLOT( projectSaveModuleOnly() ) );
    saveMenu->addAction( "Save Camera Only", this, SLOT( projectSaveCameraOnly() ) );
    saveMenu->addAction( "Save ROIs Only", this, SLOT( projectSaveROIOnly() ) );
258 259
    projectSaveButton->setMenu( saveMenu );

260 261 262
    // 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
263

Sebastian Eichelbaum's avatar
Sebastian Eichelbaum committed
264
    // This QAction stuff is quite ugly and complicated some times ... There is no nice constructor which takes name, slot keysequence and so on
265 266
    // directly -> set shortcuts, and some further properties using QAction's interface
    QMenu* viewMenu = m_menuBar->addMenu( "View" );
267
    viewMenu->addAction( hideMenuAction );
268
    viewMenu->addSeparator();
269
    viewMenu->addAction( showNavWidgets );
270 271 272 273
    viewMenu->addSeparator();
    viewMenu->addMenu( m_permanentToolBar->getStyleMenu() );

    // Camera menu
274 275 276
    QMenu* bgColorMenu = new QMenu( "Background Colors" );
    bgColorMenu->addAction( mainGLDock->getGLWidget()->getBackgroundColorAction() );

277
    QMenu* cameraMenu = m_menuBar->addMenu( "Camera" );
278 279
    cameraMenu->addAction( mainGLDock->getGLWidget()->getThrowingSetting() );
    cameraMenu->addMenu( bgColorMenu );
280 281 282
    cameraMenu->addSeparator();

    QMenu* settingsMenu = m_menuBar->addMenu( "Settings" );
283 284
    settingsMenu->addAction( m_autoDisplaySetting );
    settingsMenu->addAction( mtViews );
285
    settingsMenu->addMenu( logLevels );
286 287 288

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

290 291 292 293 294
    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
295

Sebastian Eichelbaum's avatar
Sebastian Eichelbaum committed
296 297 298
    // 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 ).
299
    // By additionally adding the action to the main window, we ensure the action can be triggered even if the menu bar is hidden.
300
    QAction* tmpAction = cameraPresetMenu->addAction( m_iconManager.getIcon( "sagittal icon" ), "Left", this, SLOT( setPresetViewLeft() ),
301
                                             QKeySequence( Qt::CTRL + Qt::SHIFT + Qt::Key_L ) );
Mathias Goldau's avatar
[MERGE]  
Mathias Goldau committed
302
    tmpAction->setIconVisibleInMenu( true );
303 304
    this->addAction( tmpAction );

305 306
    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
307
    tmpAction->setIconVisibleInMenu( true );
308 309
    this->addAction( tmpAction );

310 311
    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
312
    tmpAction->setIconVisibleInMenu( true );
313 314
    this->addAction( tmpAction );

315 316
    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
317
    tmpAction->setIconVisibleInMenu( true );
318 319
    this->addAction( tmpAction );

320 321
    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
322
    tmpAction->setIconVisibleInMenu( true );
323 324
    this->addAction( tmpAction );

325 326
    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
327
    tmpAction->setIconVisibleInMenu( true );
328 329
    this->addAction( tmpAction );

330
    resetButton->setMenu( cameraPresetMenu );
331

332
    QMenu* helpMenu = m_menuBar->addMenu( "Help" );
333
    helpMenu->addAction( m_iconManager.getIcon( "help" ), "OpenWalnut Help", this, SLOT( openOpenWalnutHelpDialog() ),
334 335 336 337
                         QKeySequence( QKeySequence::HelpContents ) );
    helpMenu->addSeparator();
    helpMenu->addAction( m_iconManager.getIcon( "logo" ), "About OpenWalnut", this, SLOT( openAboutDialog() ) );
    helpMenu->addAction( "About Qt", this, SLOT( openAboutQtDialog() ) );
338

339 340
    setMenuBar( m_menuBar );

341 342
    // initially 3 navigation views
    {
343
        if( showNavWidgets->get() )
344
        {
Sebastian Eichelbaum's avatar
[STYLE]  
Sebastian Eichelbaum committed
345
            m_navAxial = boost::shared_ptr< WQtNavGLWidget >( new WQtNavGLWidget( "Axial View", "Axial View", this, "Axial Slice",
346
                                                                                  m_mainGLWidget.get() ) );
347
            m_navAxial->setFeatures( QDockWidget::AllDockWidgetFeatures );
348
            m_glDock->addDockWidget( Qt::LeftDockWidgetArea, m_navAxial.get() );
349

350 351
            m_navCoronal = boost::shared_ptr< WQtNavGLWidget >( new WQtNavGLWidget( "Coronal View", "Coronal View", this, "Coronal Slice",
                                                                                    m_mainGLWidget.get() ) );
352
            m_navCoronal->setFeatures( QDockWidget::AllDockWidgetFeatures );
353
            m_glDock->addDockWidget( Qt::LeftDockWidgetArea, m_navCoronal.get() );
354

355
            m_navSagittal =
356 357
                boost::shared_ptr< WQtNavGLWidget >( new WQtNavGLWidget( "Sagittal View", "Sagittal View", this, "Sagittal Slice",
                                                                         m_mainGLWidget.get() ) );
358
            m_navSagittal->setFeatures( QDockWidget::AllDockWidgetFeatures );
359
            m_glDock->addDockWidget( Qt::LeftDockWidgetArea, m_navSagittal.get() );
360 361 362 363

            bgColorMenu->addAction( m_navAxial->getGLWidget()->getBackgroundColorAction() );
            bgColorMenu->addAction( m_navCoronal->getGLWidget()->getBackgroundColorAction() );
            bgColorMenu->addAction( m_navSagittal->getGLWidget()->getBackgroundColorAction() );
364 365
        }
    }
366

367
    // Temporarily disabled. We need a proper command prompt implementation first.
368
    // create command prompt toolbar
369 370 371
    // 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
372

373
    // setup permanent toolbar
374
    m_permanentToolBar->addAction( m_loadButton );
375
    m_permanentToolBar->addSeparator();
376 377
    m_permanentToolBar->addAction( projectLoadButton );
    m_permanentToolBar->addAction( projectSaveButton );
378
    m_permanentToolBar->addSeparator();
379 380
    m_permanentToolBar->addAction( resetButton );
    m_permanentToolBar->addAction( roiButton );
381
    m_permanentToolBar->addSeparator();
382

383 384
    // after creating the GUI, restore its saved state
    restoreSavedState();
385
}
386

387 388 389
void WMainWindow::autoAdd( boost::shared_ptr< WModule > module, std::string proto )
{
    // get the prototype.
Alexander Wiebel's avatar
Alexander Wiebel committed
390
    if( !WKernel::getRunningKernel()->getRootContainer()->applyModule( module, proto, true ) )
391 392 393 394 395 396
    {
        WLogger::getLogger()->addLogMessage( "Auto Display active but module " + proto + " could not be added.",
                                             "GUI", LL_ERROR );
    }
}

397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414
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 );
415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433


        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 );
        }
434 435 436
    }
}

437 438
void WMainWindow::moduleSpecificSetup( boost::shared_ptr< WModule > module )
{
439 440 441 442
    // 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.
443
    bool useAutoDisplay = m_autoDisplaySetting->get();
Alexander Wiebel's avatar
Alexander Wiebel committed
444
    if( useAutoDisplay && module->getType() == MODULE_DATA )
445 446 447 448 449 450 451 452 453
    {
        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
454
        if( dataModule->getDataSet()->isA< WDataSetSingle >() && dataModule->getDataSet()->isTexture() )
455 456 457
        {
            // it is a dataset single
            // load a nav slice module if a WDataSetSingle is available!?
458
            if( !m_navSlicesAlreadyLoaded )
459
            {
460
                autoAdd( module, "Navigation Slices" );
461
                m_navSlicesAlreadyLoaded = true;
462
            }
463
        }
Alexander Wiebel's avatar
Alexander Wiebel committed
464
        else if( dataModule->getDataSet()->isA< WDataSetFibers >() )
465 466
        {
            // it is a fiber dataset -> add the FiberDisplay module
467
            autoAdd( module, "Fiber Display" );
468
        }
Alexander Wiebel's avatar
Alexander Wiebel committed
469
        else if( dataModule->getDataSet()->isA< WEEG2 >() )
470
        {
471
            // it is a eeg dataset -> add the eegView module
472 473 474 475
            autoAdd( module, "EEG View" );
        }
    }

476
    // nav slices use separate buttons for slice on/off switching
Alexander Wiebel's avatar
Alexander Wiebel committed
477
    if( module->getName() == "Navigation Slices" )
478
    {
479
        boost::shared_ptr< WPropertyBase > prop = module->getProperties()->findProperty( "Slices/Show Axial" );
Alexander Wiebel's avatar
Alexander Wiebel committed
480
        if( !prop )
481 482
        {
               WLogger::getLogger()->
483
                   addLogMessage( "Navigation Slices module does not provide the property \"Show Axial\", which is required by the GUI.", "GUI",
484 485 486 487
                                  LL_ERROR );
        }
        else
        {
488 489 490
            WQtPropertyBoolAction* a = new WQtPropertyBoolAction( prop->toPropBool(), m_permanentToolBar );
            a->setToolTip( "Toggle Axial Slice" );
            a->setText( "Toggle Axial Slice" );
491
            a->setIcon( m_iconManager.getIcon( "axial icon" ) );
492
            m_permanentToolBar->addAction( a );
493
            propertyActionMap[prop] = a;
494
        }
495

496
        prop = module->getProperties()->findProperty( "Slices/Show Coronal" );
Alexander Wiebel's avatar
Alexander Wiebel committed
497
        if( !prop )
498 499
        {
               WLogger::getLogger()->
500
                   addLogMessage( "Navigation Slices module does not provide the property \"Show Coronal\", which is required by the GUI.", "GUI",
501 502 503 504
                                  LL_ERROR );
        }
        else
        {
505 506 507
            WQtPropertyBoolAction* a = new WQtPropertyBoolAction( prop->toPropBool(), m_permanentToolBar );
            a->setToolTip( "Toggle Coronal Slice" );
            a->setText( "Toggle Coronal Slice" );
508
            a->setIcon( m_iconManager.getIcon( "coronal icon" ) );
509
            m_permanentToolBar->addAction( a );
510
            propertyActionMap[prop] = a;
511
        }
512

513
        prop = module->getProperties()->findProperty( "Slices/Show Sagittal" );
Alexander Wiebel's avatar
Alexander Wiebel committed
514
        if( !prop )
515 516
        {
               WLogger::getLogger()->
517
                   addLogMessage( "Navigation Slices module does not provide the property \"Show Sagittal\", which is required by the GUI.", "GUI",
518 519 520 521
                                  LL_ERROR );
        }
        else
        {
522 523 524
            WQtPropertyBoolAction* a = new WQtPropertyBoolAction( prop->toPropBool(), m_permanentToolBar );
            a->setToolTip( "Toggle Saggital Slice" );
            a->setText( "Toggle Saggital Slice" );
525
            a->setIcon( m_iconManager.getIcon( "sagittal icon" ) );
526
            m_permanentToolBar->addAction( a );
527
            propertyActionMap[prop] = a;
528
        }
529 530

        // now setup the nav widget sliders
531
        prop = module->getProperties()->findProperty( "Slices/Axial Position" );
Alexander Wiebel's avatar
Alexander Wiebel committed
532
        if( !prop )
533 534
        {
               WLogger::getLogger()->
Sebastian Eichelbaum's avatar
[STYLE]  
Sebastian Eichelbaum committed
535
               addLogMessage( "Navigation Slices module does not provide the property \"Axial Position\", which is required by the GUI.", "GUI",
536 537 538 539
                                  LL_ERROR );
        }
        else
        {
540 541
            if( m_navAxial )
            {
542
                //m_navAxial->setSliderProperty( prop );
543
            }
544 545
        }

546
        prop = module->getProperties()->findProperty( "Slices/Coronal Position" );
Alexander Wiebel's avatar
Alexander Wiebel committed
547
        if( !prop )
548 549
        {
               WLogger::getLogger()->
Sebastian Eichelbaum's avatar
[STYLE]  
Sebastian Eichelbaum committed
550
               addLogMessage( "Navigation Slices module does not provide the property \"Coronal Position\", which is required by the GUI.", "GUI",
551 552 553 554
                                  LL_ERROR );
        }
        else
        {
555 556
            if( m_navCoronal )
            {
557
                //m_navCoronal->setSliderProperty( prop );
558
            }
559 560
        }

561
        prop = module->getProperties()->findProperty( "Slices/Sagittal Position" );
Alexander Wiebel's avatar
Alexander Wiebel committed
562
        if( !prop )
563 564
        {
               WLogger::getLogger()->
Sebastian Eichelbaum's avatar
[STYLE]  
Sebastian Eichelbaum committed
565
               addLogMessage( "Navigation Slices module does not provide the property \"Sagittal Position\", which is required by the GUI.", "GUI",
566 567 568 569
                                  LL_ERROR );
        }
        else
        {
570 571
            if( m_navSagittal )
            {
572
               //m_navSagittal->setSliderProperty( prop );
573
            }
574
        }
575
    }
wiebel's avatar
wiebel committed
576
}
577

578 579
void WMainWindow::setCompatiblesToolbar( WQtCombinerToolbar* toolbar )
{
Alexander Wiebel's avatar
Alexander Wiebel committed
580
    if( m_currentCompatiblesToolbar )
581 582 583 584 585
    {
        delete m_currentCompatiblesToolbar;
    }
    m_currentCompatiblesToolbar = toolbar;

Alexander Wiebel's avatar
Alexander Wiebel committed
586
    if( !toolbar )
587 588 589
    {
        // ok, reset the toolbar
        // So create a dummy to permanently reserve the space
590
        m_currentCompatiblesToolbar = new WQtCombinerToolbar( this );
591 592
    }

593 594 595 596 597
    // 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 ) ) );

598
    // and the position of the toolbar
599
    addToolBar( Qt::TopToolBarArea, m_currentCompatiblesToolbar );
600
}
601

602 603 604 605 606
WQtCombinerToolbar* WMainWindow::getCompatiblesToolbar()
{
    return m_currentCompatiblesToolbar;
}

607
WQtControlPanel* WMainWindow::getControlPanel()
608
{
609
    return m_controlPanel;
610
}
611

612 613 614 615 616
WQtNetworkEditor* WMainWindow::getNetworkEditor()
{
    return m_networkEditor;
}

617
void WMainWindow::projectSave( const std::vector< boost::shared_ptr< WProjectFileIO > >& writer )
618 619 620 621
{
    QFileDialog fd;
    fd.setWindowTitle( "Save Project as" );
    fd.setFileMode( QFileDialog::AnyFile );
622
    fd.setAcceptMode( QFileDialog::AcceptSave );
623 624

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

    QStringList::const_iterator constIterator;
Alexander Wiebel's avatar
Alexander Wiebel committed
635
    for( constIterator = fileNames.constBegin(); constIterator != fileNames.constEnd(); ++constIterator )
636
    {
637 638
        std::string filename = ( *constIterator ).toStdString();
        // append owp if not existent
639
        if( filename.rfind( ".owp" ) == std::string::npos )
640 641 642 643
        {
            filename += ".owp";
        }

644
        boost::shared_ptr< WProjectFile > proj = boost::shared_ptr< WProjectFile >(
645
                new WProjectFile( filename )
646 647
        );

648 649 650
        try
        {
            // This call is synchronous.
Alexander Wiebel's avatar
Alexander Wiebel committed
651
            if( writer.empty() )
652 653 654 655 656 657 658
            {
                proj->save();
            }
            else
            {
                proj->save( writer );
            }
659 660 661 662 663 664 665 666
        }
        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 );
        }
667 668 669
    }
}

670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690
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 );
}

691 692 693 694 695 696 697
void WMainWindow::projectSaveModuleOnly()
{
    std::vector< boost::shared_ptr< WProjectFileIO > > w;
    w.push_back( WProjectFile::getModuleWriter() );
    projectSave( w );
}

698 699 700 701 702 703
void WMainWindow::projectLoad()
{
    QFileDialog fd;
    fd.setFileMode( QFileDialog::ExistingFiles );

    QStringList filters;
704
    filters << "Simple Project File (*.owproj *.owp)"
705 706 707 708
            << "Any files (*)";
    fd.setNameFilters( filters );
    fd.setViewMode( QFileDialog::Detail );
    QStringList fileNames;
Alexander Wiebel's avatar
Alexander Wiebel committed
709
    if( fd.exec() )
710 711 712 713 714
    {
        fileNames = fd.selectedFiles();
    }

    QStringList::const_iterator constIterator;
Alexander Wiebel's avatar
Alexander Wiebel committed
715
    for( constIterator = fileNames.constBegin(); constIterator != fileNames.constEnd(); ++constIterator )
716
    {
717 718
        boost::shared_ptr< WProjectFile > proj = boost::shared_ptr< WProjectFile >(
                new WProjectFile( ( *constIterator ).toStdString() )
719
        );
720 721

        // This call is asynchronous. It parses the file and the starts a thread to actually do all the stuff
722
        proj->load();
723 724 725
    }
}

726
void WMainWindow::openLoadDialog()
727
{
728 729 730 731 732 733 734 735 736 737 738
#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
739 740
    QFileDialog fd;
    fd.setFileMode( QFileDialog::ExistingFiles );
wiebel's avatar
wiebel committed
741 742

    QStringList filters;
743 744
    filters << "Known file types (*.cnt *.edf *.asc *.nii *.nii.gz *.fib)"
            << "EEG files (*.cnt *.edf *.asc)"
wiebel's avatar
wiebel committed
745
            << "NIfTI (*.nii *.nii.gz)"
746 747
            << "Fibers (*.fib)"
            << "Any files (*)";
wiebel's avatar
wiebel committed
748
    fd.setNameFilters( filters );
749 750
    fd.setViewMode( QFileDialog::Detail );
    QStringList fileNames;
Alexander Wiebel's avatar
Alexander Wiebel committed
751
    if( fd.exec() )
752 753 754
    {
        fileNames = fd.selectedFiles();
    }
755
#endif
756

757
    std::vector< std::string > stdFileNames;
758 759

    QStringList::const_iterator constIterator;
Alexander Wiebel's avatar
Alexander Wiebel committed
760
    for( constIterator = fileNames.constBegin(); constIterator != fileNames.constEnd(); ++constIterator )
761 762 763
    {
        stdFileNames.push_back( ( *constIterator ).toLocal8Bit().constData() );
    }
764

765
    m_loaderSignal( stdFileNames );
766
}
767

768 769 770 771
void WMainWindow::openAboutQtDialog()
{
    QMessageBox::aboutQt( this, "About Qt" );
}
772

773 774
void WMainWindow::openAboutDialog()
{
775
    std::string filename( WPathHelper::getDocPath().file_string() + "/qt4gui/OpenWalnutAbout.html" );
776
    std::string content = readFileIntoString( filename );
777
    QMessageBox::about( this, "About OpenWalnut", content.c_str() );
778 779
}

780
void WMainWindow::openOpenWalnutHelpDialog()
781
{
782
    std::string filename( WPathHelper::getDocPath().file_string() + "/qt4gui/OpenWalnutHelp.html" );
783
    std::string content = readFileIntoString( filename );
784 785

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

787 788
    // specify intial layout
    QVBoxLayout *layout = new QVBoxLayout( window );
789
    window->setLayout( layout );
790 791 792 793 794
    window->resize( 500, 500 );

    window->show();

    QWebView *view = new QWebView( this );