~ubuntu-branches/ubuntu/vivid/openwalnut/vivid

« back to all changes in this revision

Viewing changes to .pc/boost153/src/qt4gui/WMainWindow.cpp

  • Committer: Package Import Robot
  • Author(s): Dmitrijs Ledkovs
  • Date: 2013-05-24 03:12:03 UTC
  • Revision ID: package-import@ubuntu.com-20130524031203-l5g1lzm1vd83fupi
Tags: 1.3.1+hg5849-1ubuntu1
Cherrypick boost1.53 pointer cast fixes.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
//---------------------------------------------------------------------------
 
2
//
 
3
// Project: OpenWalnut ( http://www.openwalnut.org )
 
4
//
 
5
// Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS
 
6
// For more information see http://www.openwalnut.org/copying
 
7
//
 
8
// This file is part of OpenWalnut.
 
9
//
 
10
// OpenWalnut is free software: you can redistribute it and/or modify
 
11
// it under the terms of the GNU Lesser General Public License as published by
 
12
// the Free Software Foundation, either version 3 of the License, or
 
13
// (at your option) any later version.
 
14
//
 
15
// OpenWalnut is distributed in the hope that it will be useful,
 
16
// but WITHOUT ANY WARRANTY; without even the implied warranty of
 
17
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
18
// GNU Lesser General Public License for more details.
 
19
//
 
20
// You should have received a copy of the GNU Lesser General Public License
 
21
// along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
 
22
//
 
23
//---------------------------------------------------------------------------
 
24
 
 
25
#include <iostream>
 
26
#include <map>
 
27
#include <string>
 
28
#include <vector>
 
29
 
 
30
#include <boost/thread.hpp>
 
31
#include <boost/regex.hpp>
 
32
#include <boost/filesystem.hpp>
 
33
 
 
34
#include <QtGui/QApplication>
 
35
#include <QtGui/QCloseEvent>
 
36
#include <QtGui/QDockWidget>
 
37
#include <QtGui/QFileDialog>
 
38
#include <QtGui/QIcon>
 
39
#include <QtGui/QMenu>
 
40
#include <QtGui/QMenuBar>
 
41
#include <QtGui/QMessageBox>
 
42
#include <QtGui/QTextEdit>
 
43
#include <QtGui/QShortcut>
 
44
#include <QtGui/QSlider>
 
45
#include <QtGui/QVBoxLayout>
 
46
#include <QtGui/QWidget>
 
47
#include <QtCore/QSettings>
 
48
#include <QtCore/QUrl>
 
49
#include <QtGui/QInputDialog>
 
50
 
 
51
#ifndef QT4GUI_NOWEBKIT
 
52
    #include <QtWebKit/QWebView>
 
53
#endif
 
54
 
 
55
#include "core/WVersion.h"   // NOTE: this file is auto-generated by CMAKE
 
56
 
 
57
#include "controlPanel/WPropertyBoolWidget.h"
 
58
#include "controlPanel/WQtControlPanel.h"
 
59
#include "core/common/WColor.h"
 
60
#include "core/common/WIOTools.h"
 
61
#include "core/common/WPathHelper.h"
 
62
#include "core/common/WProjectFileIO.h"
 
63
#include "core/dataHandler/WDataSetFibers.h"
 
64
#include "core/dataHandler/WDataSetSingle.h"
 
65
#include "core/dataHandler/WEEG2.h"
 
66
#include "core/graphicsEngine/WGEZoomTrackballManipulator.h"
 
67
#include "core/graphicsEngine/WROIBox.h"
 
68
#include "core/kernel/WDataModule.h"
 
69
#include "core/kernel/WKernel.h"
 
70
#include "core/kernel/WModule.h"
 
71
#include "core/kernel/WModuleCombiner.h"
 
72
#include "core/kernel/WModuleCombinerTypes.h"
 
73
#include "core/kernel/WProjectFile.h"
 
74
#include "core/kernel/WROIManager.h"
 
75
#include "core/kernel/WSelectionManager.h"
 
76
#include "events/WEventTypes.h"
 
77
#include "events/WModuleCrashEvent.h"
 
78
#include "events/WModuleReadyEvent.h"
 
79
#include "events/WModuleRemovedEvent.h"
 
80
#include "events/WOpenCustomDockWidgetEvent.h"
 
81
#include "events/WCloseCustomDockWidgetEvent.h"
 
82
#include "events/WLoadFinishedEvent.h"
 
83
#include "guiElements/WQtPropertyBoolAction.h"
 
84
#include "WQt4Gui.h"
 
85
#include "WQtCombinerToolbar.h"
 
86
#include "WQtCustomDockWidget.h"
 
87
#include "WQtGLDockWidget.h"
 
88
#include "WQtNavGLWidget.h"
 
89
#include "WSettingAction.h"
 
90
#include "WSettingMenu.h"
 
91
#include "WQtMessageDialog.h"
 
92
#include "WQtGLScreenCapture.h"
 
93
 
 
94
#include "WMainWindow.h"
 
95
#include "WMainWindow.moc"
 
96
 
 
97
WMainWindow::WMainWindow( QSplashScreen* splash ):
 
98
    QMainWindow(),
 
99
    m_splash( splash ),
 
100
    m_currentCompatiblesToolbar( NULL ),
 
101
    m_iconManager()
 
102
{
 
103
    setAcceptDrops( true ); // enable drag and drop events
 
104
}
 
105
 
 
106
WMainWindow::~WMainWindow()
 
107
{
 
108
    // cleanup
 
109
}
 
110
 
 
111
void WMainWindow::setupGUI()
 
112
{
 
113
    wlog::info( "WMainWindow" ) << "Setting up GUI";
 
114
 
 
115
    /////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 
116
    // Setting setup
 
117
    /////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 
118
 
 
119
    WSettingAction* hideMenuAction = new WSettingAction( this, "qt4gui/showMenu",
 
120
                                                               "Show Menubar",
 
121
                                                               "Allows you to hide the menu. Can be restored using CTRL-M.",
 
122
                                                               true,
 
123
                                                               false,
 
124
                                                               QKeySequence( Qt::CTRL + Qt::Key_M ) );
 
125
 
 
126
    WSettingAction* showNavWidgets = new WSettingAction( this, "qt4gui/showNavigationWidgets",
 
127
                                                               "Show Navigation Views",
 
128
                                                               "Disables the navigation views completely. This can lead to a speed-up and is "
 
129
                                                               "recommended for those who do not need them.",
 
130
                                                               true,
 
131
                                                               true    // this requires a restart
 
132
                                                       );
 
133
    m_autoDisplaySetting = new WSettingAction( this, "qt4gui/useAutoDisplay",
 
134
                                                     "Auto-Display",
 
135
                                                     "If enabled, the best matching module is automatically added if some data was loaded.",
 
136
                                                     true );
 
137
 
 
138
    WSettingAction* mtViews = new WSettingAction( this, "qt4gui/ge/multiThreadedViewer",
 
139
                                                        "Multi-Threaded Views",
 
140
                                                        "If enabled, the graphic windows are rendered in different threads. This can speed-up "
 
141
                                                        "rendering on machines with multiple cores. WARNING: can lead to crashes sometimes.",
 
142
                                                        false,
 
143
                                                        true // require restart
 
144
                                                );
 
145
    // NOTE: the multi-threading feature needs to be activated BEFORE the first viewer is created. To ensure this we do it here.
 
146
    WGraphicsEngine::getGraphicsEngine()->setMultiThreadedViews( mtViews->get() );
 
147
 
 
148
    // set the log-level setting.
 
149
    // NOTE: see WQt4Gui which reads the setting.
 
150
    QList< QString > logOptions;
 
151
    logOptions.push_back( "Debug" );
 
152
    logOptions.push_back( "Info" );
 
153
    logOptions.push_back( "Warning" );
 
154
    logOptions.push_back( "Error" );
 
155
    WSettingMenu* logLevels = new WSettingMenu( this, "qt4gui/logLevel",
 
156
                                                      "Log-Level",
 
157
                                                      "Allows one to set the log verbosity.",
 
158
                                                      1,    // info is the default
 
159
                                                      logOptions
 
160
                                              );
 
161
    connect( logLevels, SIGNAL( change( unsigned int ) ), this, SLOT( handleLogLevelUpdate( unsigned int ) ) );
 
162
 
 
163
    /////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 
164
    // GUI setup
 
165
    /////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 
166
 
 
167
    // We need several icons later in the GUI. Build some mappings:
 
168
    m_iconManager.addMapping( "logo", "openwalnut" );
 
169
    m_iconManager.addMapping( "axial icon", "orientation_axial" );
 
170
    m_iconManager.addMapping( "coronal icon", "orientation_coronal" );
 
171
    m_iconManager.addMapping( "sagittal icon", "orientation_sagittal" );
 
172
    m_iconManager.addMapping( "ROI icon", "roi" );
 
173
    m_iconManager.addMapping( "DefaultModuleIcon", "default" );
 
174
    m_iconManager.addMapping( "missingModule", "question" );
 
175
    m_iconManager.addMapping( "view", "camera" );
 
176
    m_iconManager.addMapping( "moduleCrashed", "error" );
 
177
    m_iconManager.addMapping( "moduleBusy", "busy" );
 
178
    m_iconManager.addMapping( "saveProject", "save" );
 
179
 
 
180
    if( objectName().isEmpty() )
 
181
    {
 
182
        setObjectName( QString::fromUtf8( "MainWindow" ) );
 
183
    }
 
184
 
 
185
    // NOTE: this only is an initial size. The state reloaded from QSettings will set it to the value the user had last session.
 
186
    resize( 800, 600 );
 
187
    setWindowIcon( m_iconManager.getIcon( "logo" ) );
 
188
    std::string windowHeading =  std::string( "OpenWalnut " ) + std::string( W_VERSION );
 
189
    setWindowTitle( QApplication::translate( "MainWindow", windowHeading.c_str(), 0, QApplication::UnicodeUTF8 ) );
 
190
 
 
191
    setDockOptions( QMainWindow::AnimatedDocks |  QMainWindow::AllowNestedDocks | QMainWindow::AllowTabbedDocks );
 
192
 
 
193
    //network Editor
 
194
    m_networkEditor = NULL;
 
195
    m_networkEditor = new WQtNetworkEditor( this );
 
196
    m_networkEditor->setFeatures( QDockWidget::AllDockWidgetFeatures );
 
197
 
 
198
    // strangely, the QGraphics* objects do not properly forward drag/drop events. We need to explicitly handle them.
 
199
    connect( m_networkEditor->getView(), SIGNAL( dragDrop( QDropEvent* ) ),
 
200
             this, SLOT( handleDrop( QDropEvent* ) ) );
 
201
 
 
202
    // the control panel instance is needed for the menu
 
203
    m_controlPanel = new WQtControlPanel( this );
 
204
    m_controlPanel->setFeatures( QDockWidget::AllDockWidgetFeatures );
 
205
    m_controlPanel->addSubject( "Default Subject" );
 
206
 
 
207
    // add all docks
 
208
    addDockWidget( Qt::RightDockWidgetArea, m_controlPanel->getModuleDock() );
 
209
    if( m_networkEditor )
 
210
    {
 
211
        addDockWidget( Qt::RightDockWidgetArea, m_networkEditor );
 
212
    }
 
213
 
 
214
    addDockWidget( Qt::RightDockWidgetArea, m_controlPanel->getColormapperDock() );
 
215
    addDockWidget( Qt::RightDockWidgetArea, m_controlPanel->getRoiDock() );
 
216
 
 
217
    // tabify those panels by default
 
218
    if( m_networkEditor )
 
219
    {
 
220
        tabifyDockWidget( m_networkEditor, m_controlPanel->getModuleDock() );
 
221
    }
 
222
    tabifyDockWidget( m_controlPanel->getModuleDock(), m_controlPanel->getColormapperDock() );
 
223
    tabifyDockWidget( m_controlPanel->getColormapperDock(), m_controlPanel->getRoiDock() );
 
224
 
 
225
    m_glDock = new QMainWindow();
 
226
    m_glDock->setObjectName( "GLDock" );
 
227
    m_glDock->setDockOptions( QMainWindow::AnimatedDocks |  QMainWindow::AllowNestedDocks | QMainWindow::AllowTabbedDocks );
 
228
    m_glDock->setDocumentMode( true );
 
229
    setCentralWidget( m_glDock );
 
230
    WQtGLDockWidget* mainGLDock = new WQtGLDockWidget( "Main View", "3D View", m_glDock );
 
231
    mainGLDock->getGLWidget()->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding );
 
232
    m_mainGLWidget = mainGLDock->getGLWidget();
 
233
    m_mainGLWidgetScreenCapture = m_mainGLWidget->getScreenCapture( this );
 
234
    m_glDock->addDockWidget( Qt::RightDockWidgetArea, mainGLDock );
 
235
    addDockWidget( Qt::RightDockWidgetArea, m_mainGLWidgetScreenCapture );
 
236
    tabifyDockWidget( m_controlPanel->getRoiDock(), m_mainGLWidgetScreenCapture );
 
237
    connect( m_mainGLWidget.get(), SIGNAL( renderedFirstFrame() ), this, SLOT( handleGLVendor() ) );
 
238
 
 
239
    addDockWidget( Qt::RightDockWidgetArea, m_controlPanel );
 
240
 
 
241
    // by default, the module editor should be in front
 
242
    if( m_networkEditor )
 
243
    {
 
244
        m_networkEditor->raise();
 
245
    }
 
246
    else
 
247
    {
 
248
        m_controlPanel->getModuleDock()->raise();
 
249
    }
 
250
 
 
251
    // NOTE: we abuse the gl widgets first frame event to handle startup news.
 
252
    connect( m_mainGLWidget.get(), SIGNAL( renderedFirstFrame() ), this, SLOT( handleStartMessages() ) );
 
253
    connect( m_mainGLWidget.get(), SIGNAL( renderedFirstFrame() ), this, SLOT( closeSplash() ) );
 
254
 
 
255
    m_permanentToolBar = new WQtToolBar( "Standard Toolbar", this );
 
256
    addToolBar( Qt::TopToolBarArea, m_permanentToolBar );
 
257
 
 
258
    m_loadButton = new QAction( m_iconManager.getIcon( "load" ), "Load Dataset or Project", m_permanentToolBar );
 
259
    m_loadButton->setShortcut( QKeySequence(  QKeySequence::Open ) );
 
260
    QAction* roiButton = new QAction( m_iconManager.getIcon( "ROI icon" ), "ROI", m_permanentToolBar );
 
261
    QAction* resetButton = new QAction( m_iconManager.getIcon( "view" ), "Reset", m_permanentToolBar );
 
262
    m_saveAction = new QAction( m_iconManager.getIcon( "saveProject" ), "Save Project", m_permanentToolBar );
 
263
 
 
264
    connect( m_loadButton, SIGNAL(  triggered( bool ) ), this, SLOT( openLoadDialog() ) );
 
265
    connect( resetButton, SIGNAL(  triggered( bool ) ), m_mainGLWidget.get(), SLOT( reset() ) );
 
266
    connect( roiButton, SIGNAL(  triggered( bool ) ), this, SLOT( newRoi() ) );
 
267
    connect( m_saveAction, SIGNAL( triggered( bool ) ), this, SLOT( projectSaveAll() ) );
 
268
 
 
269
    m_loadButton->setToolTip( "Load a dataset or project from file" );
 
270
    resetButton->setToolTip( "Reset main view" );
 
271
    roiButton->setToolTip( "Create new ROI" );
 
272
    m_saveAction->setToolTip( "Save current project to file" );
 
273
 
 
274
    // we want the upper most tree item to be selected. This helps to make the always compatible modules
 
275
    // show up in the tool bar from the beginning. And ... it doesn't hurt.
 
276
    m_controlPanel->selectUpperMostEntry();
 
277
 
 
278
    // NOTE: Please be aware that not every menu needs a shortcut key. If you add a shortcut, you should use one of the
 
279
    // QKeySequence::StandardKey defaults and avoid ambiguities like Ctrl-C for the configure dialog is not the best choice as Ctrl-C, for the
 
280
    // most users is the Copy shortcut.
 
281
 
 
282
    m_menuBar = new QMenuBar( this );
 
283
 
 
284
    // hide menu?
 
285
    m_menuBar->setVisible( hideMenuAction->get() );
 
286
    connect( hideMenuAction, SIGNAL( change( bool ) ), m_menuBar, SLOT( setVisible( bool ) ) );
 
287
    addAction( hideMenuAction );
 
288
 
 
289
    QMenu* fileMenu = m_menuBar->addMenu( "File" );
 
290
 
 
291
    fileMenu->addAction( m_loadButton );
 
292
    m_saveMenu = fileMenu->addMenu( m_iconManager.getIcon( "saveProject" ), "Save Project" );
 
293
    m_saveMenu->addAction( "Save Project", this, SLOT( projectSaveAll() ), QKeySequence::Save );
 
294
    m_saveMenu->addAction( "Save Modules Only", this, SLOT( projectSaveModuleOnly() ) );
 
295
    m_saveMenu->addAction( "Save Camera Only", this, SLOT( projectSaveCameraOnly() ) );
 
296
    // saveMenu->addAction( "Save ROIs Only", this, SLOT( projectSaveROIOnly() ) );
 
297
    m_saveAction->setMenu( m_saveMenu );
 
298
 
 
299
    fileMenu->addSeparator();
 
300
    // TODO(all): If all distributions provide a newer QT version we should use QKeySequence::Quit here
 
301
    //fileMenu->addAction( m_iconManager.getIcon( "quit" ), "Quit", this, SLOT( close() ), QKeySequence( QKeySequence::Quit ) );
 
302
    m_quitAction = fileMenu->addAction( m_iconManager.getIcon( "quit" ), "Quit", this, SLOT( close() ),  QKeySequence( Qt::CTRL + Qt::Key_Q ) );
 
303
 
 
304
    // This QAction stuff is quite ugly and complicated some times ... There is no nice constructor which takes name, slot keysequence and so on
 
305
    // directly -> set shortcuts, and some further properties using QAction's interface
 
306
 
 
307
    m_viewAction = new QAction( "View", this );
 
308
    m_viewMenu = m_menuBar->addMenu( "View" );
 
309
    m_viewMenu->addAction( hideMenuAction );
 
310
    m_viewMenu->addSeparator();
 
311
    m_viewMenu->addAction( showNavWidgets );
 
312
    m_viewMenu->addSeparator();
 
313
    m_viewMenu->addMenu( m_permanentToolBar->getStyleMenu() );
 
314
    m_viewAction->setMenu( m_viewMenu );
 
315
 
 
316
    // Camera menu
 
317
    m_cameraAction = new QAction( "Camera", this );
 
318
    m_cameraMenu = m_menuBar->addMenu( "Camera" );
 
319
    m_cameraMenu->addAction( mainGLDock->getGLWidget()->getThrowingSetting() );
 
320
    m_cameraAction->setMenu( m_cameraMenu );
 
321
 
 
322
    m_settingsAction = new QAction( "Settings", this );
 
323
    m_settingsMenu = m_menuBar->addMenu( "Settings" );
 
324
    m_settingsMenu->addAction( m_autoDisplaySetting );
 
325
    m_settingsMenu->addAction( m_controlPanel->getModuleConfig().getConfigureAction() );
 
326
    m_settingsMenu->addSeparator();
 
327
    m_settingsMenu->addAction( mtViews );
 
328
    m_settingsMenu->addSeparator();
 
329
    m_settingsMenu->addMenu( logLevels );
 
330
    m_settingsAction->setMenu( m_settingsMenu );
 
331
 
 
332
    QAction* controlPanelTrigger = m_controlPanel->toggleViewAction();
 
333
    QList< QKeySequence > controlPanelShortcut;
 
334
    controlPanelShortcut.append( QKeySequence( Qt::Key_F9 ) );
 
335
    controlPanelTrigger->setShortcuts( controlPanelShortcut );
 
336
    this->addAction( controlPanelTrigger );  // this enables the action even if the menu bar is invisible
 
337
 
 
338
    m_cameraMenu->addAction( m_mainGLWidget->getCameraResetAction() );
 
339
    m_cameraMenu->addMenu( m_mainGLWidget->getCameraPresetsMenu() );
 
340
    resetButton->setMenu( m_mainGLWidget->getCameraPresetsMenu() );
 
341
 
 
342
    m_helpAction = new QAction( "Help", this );
 
343
    m_helpMenu = m_menuBar->addMenu( "Help" );
 
344
    m_helpMenu->addAction( m_iconManager.getIcon( "help" ), "OpenWalnut Help", this, SLOT( openOpenWalnutHelpDialog() ),
 
345
                           QKeySequence( QKeySequence::HelpContents ) );
 
346
    m_helpMenu->addAction( m_iconManager.getIcon( "logo" ), "Welcome to OpenWalnut", this, SLOT( showWelcomeDialog() ) );
 
347
    m_helpMenu->addSeparator();
 
348
    m_helpMenu->addAction( m_iconManager.getIcon( "logo" ), "About OpenWalnut", this, SLOT( openAboutDialog() ) );
 
349
    m_helpMenu->addAction( "About Qt", this, SLOT( openAboutQtDialog() ) );
 
350
    m_helpAction->setMenu( m_helpMenu );
 
351
 
 
352
    setMenuBar( m_menuBar );
 
353
 
 
354
    // initially 3 navigation views
 
355
    {
 
356
        if( showNavWidgets->get() )
 
357
        {
 
358
            m_navAxial = boost::shared_ptr< WQtNavGLWidget >( new WQtNavGLWidget( "Axial View", "Axial View", this, "Axial Slice",
 
359
                                                                                  m_mainGLWidget.get() ) );
 
360
            m_navAxial->setFeatures( QDockWidget::AllDockWidgetFeatures );
 
361
            m_navAxial->setSliderProperty( WKernel::getRunningKernel()->getSelectionManager()->getPropAxialPos() );
 
362
            m_navAxial->getGLWidget()->setCameraManipulator( WQtGLWidget::NO_OP );
 
363
 
 
364
            m_glDock->addDockWidget( Qt::LeftDockWidgetArea, m_navAxial.get() );
 
365
 
 
366
            m_navCoronal = boost::shared_ptr< WQtNavGLWidget >( new WQtNavGLWidget( "Coronal View", "Coronal View", this, "Coronal Slice",
 
367
                                                                                    m_mainGLWidget.get() ) );
 
368
            m_navCoronal->setFeatures( QDockWidget::AllDockWidgetFeatures );
 
369
            m_navCoronal->setSliderProperty( WKernel::getRunningKernel()->getSelectionManager()->getPropCoronalPos() );
 
370
            m_navCoronal->getGLWidget()->setCameraManipulator( WQtGLWidget::NO_OP );
 
371
 
 
372
            m_glDock->addDockWidget( Qt::LeftDockWidgetArea, m_navCoronal.get() );
 
373
 
 
374
            m_navSagittal =
 
375
                boost::shared_ptr< WQtNavGLWidget >( new WQtNavGLWidget( "Sagittal View", "Sagittal View", this, "Sagittal Slice",
 
376
                                                                         m_mainGLWidget.get() ) );
 
377
            m_navSagittal->setFeatures( QDockWidget::AllDockWidgetFeatures );
 
378
            m_navSagittal->setSliderProperty( WKernel::getRunningKernel()->getSelectionManager()->getPropSagittalPos() );
 
379
            m_navSagittal->getGLWidget()->setCameraManipulator( WQtGLWidget::NO_OP );
 
380
 
 
381
            m_glDock->addDockWidget( Qt::LeftDockWidgetArea, m_navSagittal.get() );
 
382
        }
 
383
    }
 
384
 
 
385
    // create the show/hide actions using the selection manager's props
 
386
    WQtPropertyBoolAction* showAxial = new WQtPropertyBoolAction( WKernel::getRunningKernel()->getSelectionManager()->getPropAxialShow(),
 
387
                                                                  m_permanentToolBar );
 
388
    showAxial->setToolTip( "Toggle axial slice" );
 
389
    showAxial->setText( "Toggle Axial Slice" );
 
390
    showAxial->setIcon( m_iconManager.getIcon( "axial icon" ) );
 
391
 
 
392
    WQtPropertyBoolAction* showCoronal = new WQtPropertyBoolAction( WKernel::getRunningKernel()->getSelectionManager()->getPropCoronalShow(),
 
393
                                                                    m_permanentToolBar );
 
394
    showCoronal->setToolTip( "Toggle coronal slice" );
 
395
    showCoronal->setText( "Toggle Coronal Slice" );
 
396
    showCoronal->setIcon( m_iconManager.getIcon( "coronal icon" ) );
 
397
 
 
398
    WQtPropertyBoolAction* showSagittal = new WQtPropertyBoolAction( WKernel::getRunningKernel()->getSelectionManager()->getPropSagittalShow(),
 
399
                                                                     m_permanentToolBar );
 
400
    showSagittal->setToolTip( "Toggle sagittal slice" );
 
401
    showSagittal->setText( "Toggle Sagittal Slice" );
 
402
    showSagittal->setIcon( m_iconManager.getIcon( "sagittal icon" ) );
 
403
 
 
404
    // setup permanent toolbar
 
405
    m_permanentToolBar->addAction( m_loadButton );
 
406
    m_permanentToolBar->addAction( m_saveAction );
 
407
    m_permanentToolBar->addSeparator();
 
408
    m_permanentToolBar->addAction( m_mainGLWidgetScreenCapture->getScreenshotTrigger() );
 
409
    m_permanentToolBar->addSeparator();
 
410
    m_permanentToolBar->addAction( resetButton );
 
411
    m_permanentToolBar->addAction( roiButton );
 
412
    m_permanentToolBar->addSeparator();
 
413
    m_permanentToolBar->addAction( showAxial );
 
414
    m_permanentToolBar->addAction( showCoronal );
 
415
    m_permanentToolBar->addAction( showSagittal );
 
416
    m_permanentToolBar->addSeparator();
 
417
 
 
418
    // allow the control panel to complete setup
 
419
    m_controlPanel->completeGuiSetup();
 
420
 
 
421
    // after creating the GUI, restore its saved state
 
422
    restoreSavedState();
 
423
}
 
424
 
 
425
void WMainWindow::autoAdd( boost::shared_ptr< WModule > module, std::string proto, bool onlyOnce )
 
426
{
 
427
    // if only one module should be added, and there already is one --- skip.
 
428
    if( onlyOnce && !WKernel::getRunningKernel()->getRootContainer()->getModules( proto ).empty() )
 
429
    {
 
430
        return;
 
431
    }
 
432
 
 
433
    // get the prototype.
 
434
    if( !WKernel::getRunningKernel()->getRootContainer()->applyModule( module, proto, true ) )
 
435
    {
 
436
        WLogger::getLogger()->addLogMessage( "Auto Display active but module " + proto + " could not be added.",
 
437
                                             "GUI", LL_ERROR );
 
438
    }
 
439
}
 
440
 
 
441
void WMainWindow::moduleSpecificCleanup( boost::shared_ptr< WModule > /* module */ )
 
442
{
 
443
    // called for each removed module. Use this to undo modifications done due to added modules (moduleSpecificSetup)
 
444
}
 
445
 
 
446
void WMainWindow::moduleSpecificSetup( boost::shared_ptr< WModule > module )
 
447
{
 
448
    // Add all special handlings here. This method is called whenever a module is marked "ready". You can set up the gui for special modules,
 
449
    // load certain modules for datasets and so on.
 
450
 
 
451
    // 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.
 
452
    bool useAutoDisplay = m_autoDisplaySetting->get();
 
453
    if( useAutoDisplay && module->getType() == MODULE_DATA )
 
454
    {
 
455
        WLogger::getLogger()->addLogMessage( "Auto Display active and Data module added. The proper module will be added.",
 
456
                                             "GUI", LL_DEBUG );
 
457
 
 
458
        // data modules contain an member denoting the real data type. Currently we only have one data module and a not very modulated data
 
459
        // structures.
 
460
        boost::shared_ptr< WDataModule > dataModule = boost::shared_static_cast< WDataModule >( module );
 
461
 
 
462
        // grab data and identify type
 
463
        if( dataModule->getDataSet()->isA< WDataSetSingle >() && dataModule->getDataSet()->isTexture() )
 
464
        {
 
465
            // it is a dataset single
 
466
            // load a nav slice module if a WDataSetSingle is available!?
 
467
            autoAdd( module, "Navigation Slices", true );
 
468
        }
 
469
        else if( dataModule->getDataSet()->isA< WDataSetFibers >() )
 
470
        {
 
471
            // it is a fiber dataset -> add the FiberDisplay module
 
472
            autoAdd( module, "Fiber Display" );
 
473
        }
 
474
        else if( dataModule->getDataSet()->isA< WEEG2 >() )
 
475
        {
 
476
            // it is a eeg dataset -> add the eegView module
 
477
            autoAdd( module, "EEG View" );
 
478
        }
 
479
    }
 
480
}
 
481
 
 
482
void WMainWindow::setCompatiblesToolbar( WQtCombinerToolbar* toolbar )
 
483
{
 
484
    if( m_currentCompatiblesToolbar )
 
485
    {
 
486
        delete m_currentCompatiblesToolbar;
 
487
    }
 
488
    m_currentCompatiblesToolbar = toolbar;
 
489
 
 
490
    if( !toolbar )
 
491
    {
 
492
        // ok, reset the toolbar
 
493
        // So create a dummy to permanently reserve the space
 
494
        m_currentCompatiblesToolbar = new WQtCombinerToolbar( this );
 
495
    }
 
496
 
 
497
    // we want to keep the tool-button styles in sync
 
498
    m_currentCompatiblesToolbar->setToolButtonStyle( m_permanentToolBar->toolButtonStyle() );
 
499
    connect( m_permanentToolBar, SIGNAL( toolButtonStyleChanged( Qt::ToolButtonStyle ) ),
 
500
             m_currentCompatiblesToolbar, SLOT( setToolButtonStyle( Qt::ToolButtonStyle ) ) );
 
501
 
 
502
    // and the position of the toolbar
 
503
    addToolBar( Qt::TopToolBarArea, m_currentCompatiblesToolbar );
 
504
}
 
505
 
 
506
WQtCombinerToolbar* WMainWindow::getCompatiblesToolbar()
 
507
{
 
508
    return m_currentCompatiblesToolbar;
 
509
}
 
510
 
 
511
WQtControlPanel* WMainWindow::getControlPanel()
 
512
{
 
513
    return m_controlPanel;
 
514
}
 
515
 
 
516
WQtNetworkEditor* WMainWindow::getNetworkEditor()
 
517
{
 
518
    return m_networkEditor;
 
519
}
 
520
 
 
521
bool WMainWindow::projectSave( const std::vector< boost::shared_ptr< WProjectFileIO > >& writer )
 
522
{
 
523
    QFileDialog fd;
 
524
    fd.setWindowTitle( "Save Project as" );
 
525
    fd.setFileMode( QFileDialog::AnyFile );
 
526
    fd.setAcceptMode( QFileDialog::AcceptSave );
 
527
 
 
528
    // My Mac OSX Lion automatically appends .owproj to the file name
 
529
    // if no extension is given.
 
530
    QStringList filters;
 
531
    filters << "Project File (*.owproj *.owp)";
 
532
    fd.setNameFilters( filters );
 
533
    fd.setViewMode( QFileDialog::Detail );
 
534
    QStringList filenames;
 
535
    if( fd.exec() )
 
536
    {
 
537
        filenames = fd.selectedFiles();
 
538
    }
 
539
    else
 
540
    {
 
541
        return false; // the user canceled, no files, so nothing saved
 
542
    }
 
543
 
 
544
    bool success = true;
 
545
    QStringList::const_iterator constIterator;
 
546
    for( constIterator = filenames.constBegin(); constIterator != filenames.constEnd(); ++constIterator )
 
547
    {
 
548
        std::string filename = ( *constIterator ).toStdString();
 
549
 
 
550
        // append owp if suffix is not present, yet
 
551
        if( filename.rfind( ".owp" ) != filename.size() - 4
 
552
         && filename.rfind( ".owproj" ) != filename.size() - 7 )
 
553
        {
 
554
            filename += ".owp";
 
555
        }
 
556
 
 
557
        boost::shared_ptr< WProjectFile > proj = boost::shared_ptr< WProjectFile >(
 
558
                new WProjectFile( filename )
 
559
        );
 
560
 
 
561
        try
 
562
        {
 
563
            // This call is synchronous.
 
564
            if( writer.empty() )
 
565
            {
 
566
                proj->save();
 
567
            }
 
568
            else
 
569
            {
 
570
                proj->save( writer );
 
571
            }
 
572
        }
 
573
        catch( const std::exception& e )
 
574
        {
 
575
            QString title = "Problem while saving project file.";
 
576
            QString message = "<b>Problem while saving project file.</b><br/><br/><b>File:  </b>" + ( *constIterator ) +
 
577
                              "<br/><b>Message:  </b>" + QString::fromStdString( e.what() );
 
578
            QMessageBox::critical( this, title, message );
 
579
            success = false;
 
580
        }
 
581
    }
 
582
    return success;
 
583
}
 
584
 
 
585
bool WMainWindow::projectSaveAll()
 
586
{
 
587
    std::vector< boost::shared_ptr< WProjectFileIO > > w;
 
588
    // an empty list equals "all"
 
589
    return projectSave( w );
 
590
}
 
591
 
 
592
bool WMainWindow::projectSaveCameraOnly()
 
593
{
 
594
    std::vector< boost::shared_ptr< WProjectFileIO > > w;
 
595
    w.push_back( WProjectFile::getCameraWriter() );
 
596
    return projectSave( w );
 
597
}
 
598
 
 
599
bool WMainWindow::projectSaveROIOnly()
 
600
{
 
601
    std::vector< boost::shared_ptr< WProjectFileIO > > w;
 
602
    w.push_back( WProjectFile::getROIWriter() );
 
603
    return projectSave( w );
 
604
}
 
605
 
 
606
bool WMainWindow::projectSaveModuleOnly()
 
607
{
 
608
    std::vector< boost::shared_ptr< WProjectFileIO > > w;
 
609
    w.push_back( WProjectFile::getModuleWriter() );
 
610
    return projectSave( w );
 
611
}
 
612
 
 
613
void WMainWindow::openLoadDialog()
 
614
{
 
615
    QFileDialog fd;
 
616
    fd.setFileMode( QFileDialog::ExistingFiles );
 
617
 
 
618
    QStringList filters;
 
619
    filters << "Known file types (*.cnt *.edf *.asc *.nii *.nii.gz *.fib *.owproj *.owp)"
 
620
            << "Simple Project File (*.owproj *.owp)"
 
621
            << "EEG files (*.cnt *.edf *.asc)"
 
622
            << "NIfTI (*.nii *.nii.gz)"
 
623
            << "Fibers (*.fib)"
 
624
            << "Any files (*)";
 
625
    fd.setNameFilters( filters );
 
626
    fd.setViewMode( QFileDialog::Detail );
 
627
    QStringList filenames;
 
628
    if( fd.exec() )
 
629
    {
 
630
        filenames = fd.selectedFiles();
 
631
    }
 
632
 
 
633
    std::vector< std::string > loadDataFilenames;
 
634
 
 
635
    QStringList::const_iterator constIterator;
 
636
    for( constIterator = filenames.constBegin(); constIterator != filenames.constEnd(); ++constIterator )
 
637
    {
 
638
        boost::filesystem::path fn( ( *constIterator ).toLocal8Bit().constData() );
 
639
        std::string suffix = getSuffix( fn );
 
640
 
 
641
        // is this a project file?
 
642
        if( ( suffix == ".owp" ) || ( suffix == ".owproj" ) )
 
643
        {
 
644
            asyncProjectLoad( fn.string() );
 
645
        }
 
646
        else
 
647
        {
 
648
            // this is not a project. So we assume it is a data file
 
649
            loadDataFilenames.push_back( fn.string() );
 
650
        }
 
651
    }
 
652
 
 
653
    m_loaderSignal( loadDataFilenames );
 
654
}
 
655
 
 
656
void WMainWindow::asyncProjectLoad( std::string filename )
 
657
{
 
658
    WProjectFile::SPtr proj( new WProjectFile( filename, boost::bind( &WMainWindow::slotLoadFinished, this, _1, _2 ) ) );
 
659
    proj->load();
 
660
}
 
661
 
 
662
void WMainWindow::slotLoadFinished( boost::filesystem::path file, std::vector< std::string > errors )
 
663
{
 
664
    // as this function might be called from outside the gui thread, use an event:
 
665
    QCoreApplication::postEvent( this, new WLoadFinishedEvent( file, errors ) );
 
666
 
 
667
    if( errors.size() )
 
668
    {
 
669
        wlog::warn( "MainWindow" ) << "Async load error occurred. Informing user.";
 
670
    }
 
671
}
 
672
 
 
673
void WMainWindow::openAboutQtDialog()
 
674
{
 
675
    QMessageBox::aboutQt( this, "About Qt" );
 
676
}
 
677
 
 
678
void WMainWindow::openAboutDialog()
 
679
{
 
680
    std::string filename( WPathHelper::getDocPath().string() + "/openwalnut-qt4/OpenWalnutAbout.html" );
 
681
    std::string content = readFileIntoString( filename );
 
682
    std::string windowHeading =  std::string( "About OpenWalnut " ) + std::string( W_VERSION );
 
683
    QMessageBox::about( this, windowHeading.c_str(), content.c_str() );
 
684
}
 
685
 
 
686
void WMainWindow::openOpenWalnutHelpDialog()
 
687
{
 
688
    std::string filename( WPathHelper::getDocPath().string() + "/openwalnut-qt4/OpenWalnutHelp.html" );
 
689
 
 
690
#ifndef QT4GUI_NOWEBKIT
 
691
    std::string content = readFileIntoString( filename );
 
692
 
 
693
    QWidget* window = new QWidget( this, Qt::Window );
 
694
    window->setWindowTitle( "OpenWalnut Help" );
 
695
    // specify intial layout
 
696
    QVBoxLayout *layout = new QVBoxLayout( window );
 
697
    window->setLayout( layout );
 
698
    window->resize( 500, 500 );
 
699
 
 
700
    window->show();
 
701
 
 
702
    QWebView *view = new QWebView( this );
 
703
    QString location( QString( "file://" ) + WPathHelper::getDocPath().string().c_str() + "/openwalnut-qt4/" );
 
704
    view->setHtml( content.c_str(), QUrl( location  ) );
 
705
    view->show();
 
706
    layout->addWidget( view );
 
707
#else
 
708
    QMessageBox::information( this, "Help", QString::fromStdString( "Sorry! Your version of OpenWalnut was not compiled with embedded help. "
 
709
                                                                    "To open the help pages in your browser, use this link: <a href=" +
 
710
                                                                    filename + ">Help</a>." ) );
 
711
#endif
 
712
}
 
713
 
 
714
void WMainWindow::openNotImplementedDialog()
 
715
{
 
716
    QMessageBox::information( this, "Not yet implemented!",
 
717
                              "This functionality is planned for future versions of OpenWalnut. "
 
718
                              "It is not yet implemented." );
 
719
}
 
720
 
 
721
boost::signals2::signal1< void, std::vector< std::string > >* WMainWindow::getLoaderSignal()
 
722
{
 
723
    return &m_loaderSignal;
 
724
}
 
725
 
 
726
WIconManager*  WMainWindow::getIconManager()
 
727
{
 
728
    return &m_iconManager;
 
729
}
 
730
 
 
731
void WMainWindow::closeEvent( QCloseEvent* e )
 
732
{
 
733
    // use some "Really Close?" Dialog here
 
734
    bool reallyClose = true;
 
735
 
 
736
    // handle close event
 
737
    if( reallyClose )
 
738
    {
 
739
        m_splash->show();
 
740
        m_splash->showMessage( "Shutting down" );
 
741
 
 
742
        saveWindowState();
 
743
 
 
744
        // signal everybody to shut down properly.
 
745
        m_splash->showMessage( "Shutting down kernel. Waiting for modules to finish." );
 
746
        WKernel::getRunningKernel()->finalize();
 
747
 
 
748
        // now nobody acesses the osg anymore
 
749
        m_splash->showMessage( "Shutting down GUI." );
 
750
 
 
751
        // clean up gl widgets
 
752
        m_mainGLWidget->close();
 
753
        if( m_navAxial )
 
754
        {
 
755
            m_navAxial->close();
 
756
        }
 
757
        if( m_navCoronal )
 
758
        {
 
759
            m_navCoronal->close();
 
760
        }
 
761
        if( m_navSagittal )
 
762
        {
 
763
            m_navSagittal->close();
 
764
        }
 
765
 
 
766
        // delete CustomDockWidgets
 
767
        boost::mutex::scoped_lock lock( m_customDockWidgetsLock );
 
768
        for( std::map< std::string, boost::shared_ptr< WQtCustomDockWidget > >::iterator it = m_customDockWidgets.begin();
 
769
             it != m_customDockWidgets.end(); ++it )
 
770
        {
 
771
            it->second->close();
 
772
        }
 
773
        //m_customDockWidgetsLock.unlock();
 
774
 
 
775
        // finally close
 
776
        e->accept();
 
777
    }
 
778
    else
 
779
    {
 
780
        e->ignore();
 
781
    }
 
782
}
 
783
 
 
784
void WMainWindow::customEvent( QEvent* event )
 
785
{
 
786
    if( event->type() == WOpenCustomDockWidgetEvent::CUSTOM_TYPE )
 
787
    {
 
788
        // OpenCustomDockWidgetEvent
 
789
        WOpenCustomDockWidgetEvent* ocdwEvent = static_cast< WOpenCustomDockWidgetEvent* >( event );
 
790
        std::string title = ocdwEvent->getTitle();
 
791
 
 
792
        boost::shared_ptr< WQtCustomDockWidget > widget;
 
793
 
 
794
        boost::mutex::scoped_lock lock( m_customDockWidgetsLock );
 
795
        if( m_customDockWidgets.count( title ) == 0 )
 
796
        {
 
797
            // create new custom dock widget
 
798
            widget = boost::shared_ptr< WQtCustomDockWidget >(
 
799
                new WQtCustomDockWidget( title, m_glDock, ocdwEvent->getProjectionMode() ) );
 
800
            m_glDock->addDockWidget( Qt::BottomDockWidgetArea, widget.get() );
 
801
 
 
802
            // restore state and geometry
 
803
            m_glDock->restoreDockWidget( widget.get() );
 
804
            //TODO(mario): is there a fallback if the configuration is "stupid" or not set?
 
805
 
 
806
            // store it in CustomDockWidget list
 
807
            m_customDockWidgets.insert( make_pair( title, widget ) );
 
808
        }
 
809
        else
 
810
        {
 
811
            widget = m_customDockWidgets[title];
 
812
            widget->increaseUseCount();
 
813
        }
 
814
 
 
815
        ocdwEvent->getFlag()->set( widget );
 
816
        boost::shared_dynamic_cast< QDockWidget >( widget )->toggleViewAction()->activate( QAction::Trigger );
 
817
    }
 
818
    else if( event->type() == WCloseCustomDockWidgetEvent::CUSTOM_TYPE )
 
819
    {
 
820
        WCloseCustomDockWidgetEvent* closeEvent = static_cast< WCloseCustomDockWidgetEvent* >( event );
 
821
        boost::mutex::scoped_lock lock( m_customDockWidgetsLock );
 
822
        if( m_customDockWidgets.count( closeEvent->getTitle() ) > 0 )
 
823
        {
 
824
            if( m_customDockWidgets[closeEvent->getTitle()]->decreaseUseCount() )
 
825
            {
 
826
                // custom dock widget should be deleted
 
827
                m_customDockWidgets.erase( closeEvent->getTitle() );
 
828
            }
 
829
        }
 
830
    }
 
831
    else
 
832
    {
 
833
        // other event
 
834
        QMainWindow::customEvent( event );
 
835
    }
 
836
}
 
837
 
 
838
bool WMainWindow::event( QEvent* event )
 
839
{
 
840
    // a module got associated with the root container -> add it to the list
 
841
    if( event->type() == WQT_READY_EVENT )
 
842
    {
 
843
        // convert event to ready event
 
844
        WModuleReadyEvent* e1 = dynamic_cast< WModuleReadyEvent* >( event );     // NOLINT
 
845
        if( e1 )
 
846
        {
 
847
            moduleSpecificSetup( e1->getModule() );
 
848
        }
 
849
    }
 
850
 
 
851
    if( event->type() == WQT_CRASH_EVENT )
 
852
    {
 
853
        // convert event to ready event
 
854
        WModuleCrashEvent* e1 = dynamic_cast< WModuleCrashEvent* >( event );     // NOLINT
 
855
        if( e1 )
 
856
        {
 
857
            QString title = "Problem in module: " + QString::fromStdString( e1->getModule()->getName() );
 
858
            QString description = "<b>Module Problem</b><br/><br/><b>Module:  </b>" + QString::fromStdString( e1->getModule()->getName() );
 
859
 
 
860
            QString message = QString::fromStdString( e1->getMessage() );
 
861
            QMessageBox msgBox;
 
862
            msgBox.setText( description );
 
863
            msgBox.setInformativeText( message  );
 
864
            msgBox.setStandardButtons( QMessageBox::Ok );
 
865
            msgBox.exec();
 
866
        }
 
867
    }
 
868
 
 
869
    if( event->type() == WQT_MODULE_REMOVE_EVENT )
 
870
    {
 
871
        // convert event to ready event
 
872
        WModuleRemovedEvent* e1 = dynamic_cast< WModuleRemovedEvent* >( event );     // NOLINT
 
873
        if( e1 )
 
874
        {
 
875
            moduleSpecificCleanup( e1->getModule() );
 
876
        }
 
877
    }
 
878
 
 
879
    if( event->type() == WQT_LOADFINISHED )
 
880
    {
 
881
        // convert event
 
882
        WLoadFinishedEvent* e1 = dynamic_cast< WLoadFinishedEvent* >( event );
 
883
        if( e1 )
 
884
        {
 
885
            if( e1->getErrors().size() )
 
886
            {
 
887
                size_t curErrCount = 0;
 
888
                const size_t maxErrCount = 5;
 
889
                std::string errors = "<ul>";
 
890
                for( std::vector< std::string >::const_iterator iter = e1->getErrors().begin(); iter != e1->getErrors().end(); ++iter )
 
891
                {
 
892
                    errors += "<li> " + *iter;
 
893
                    curErrCount++;
 
894
 
 
895
                    if( ( curErrCount == maxErrCount ) && ( e1->getErrors().size() > maxErrCount ) )
 
896
                    {
 
897
                        size_t errDiff = e1->getErrors().size() - curErrCount;
 
898
                        errors += "<li> ... and " + string_utils::toString( errDiff ) + " more errors.";
 
899
                        break;
 
900
                    }
 
901
                }
 
902
                errors += "</ul>";
 
903
 
 
904
                QMessageBox::critical( this, "Error during load",
 
905
                                             "Errors occurred during load of \"" + QString::fromStdString( e1->getFilename() ) + "\". "
 
906
                                             "The loader tried to apply as much as possible, ignoring the erroneous data. The first errors where:"
 
907
                                             "<br><br>"
 
908
                                             "<font color=\"#f00\">" + QString::fromStdString( errors )+ "</font>" );
 
909
            }
 
910
        }
 
911
    }
 
912
 
 
913
    return QMainWindow::event( event );
 
914
}
 
915
 
 
916
boost::shared_ptr< WQtCustomDockWidget > WMainWindow::getCustomDockWidget( std::string title )
 
917
{
 
918
    boost::mutex::scoped_lock lock( m_customDockWidgetsLock );
 
919
    boost::shared_ptr< WQtCustomDockWidget > out = m_customDockWidgets.count( title ) > 0 ?
 
920
        m_customDockWidgets[title] :
 
921
        boost::shared_ptr< WQtCustomDockWidget >();
 
922
    return out;
 
923
}
 
924
 
 
925
 
 
926
void WMainWindow::closeCustomDockWidget( std::string title )
 
927
{
 
928
    QCoreApplication::postEvent( this, new WCloseCustomDockWidgetEvent( title ) );
 
929
}
 
930
 
 
931
void WMainWindow::newRoi()
 
932
{
 
933
    // do nothing if we can not get
 
934
    WPosition crossHairPos = WKernel::getRunningKernel()->getSelectionManager()->getCrosshair()->getPosition();
 
935
    WPosition minROIPos = crossHairPos - WPosition( 10., 10., 10. );
 
936
    WPosition maxROIPos = crossHairPos + WPosition( 10., 10., 10. );
 
937
 
 
938
    if( m_controlPanel->getFirstRoiInSelectedBranch().get() == NULL )
 
939
    {
 
940
        osg::ref_ptr< WROIBox > newRoi = osg::ref_ptr< WROIBox >( new WROIBox( minROIPos, maxROIPos ) );
 
941
        WKernel::getRunningKernel()->getRoiManager()->addRoi( newRoi );
 
942
    }
 
943
    else
 
944
    {
 
945
        osg::ref_ptr< WROIBox > newRoi = osg::ref_ptr< WROIBox >( new WROIBox( minROIPos, maxROIPos ) );
 
946
        WKernel::getRunningKernel()->getRoiManager()->addRoi( newRoi, m_controlPanel->getFirstRoiInSelectedBranch() );
 
947
    }
 
948
}
 
949
 
 
950
void WMainWindow::restoreSavedState()
 
951
{
 
952
    wlog::info( "MainWindow" ) << "Restoring window state.";
 
953
 
 
954
    restoreGeometry( WQt4Gui::getSettings().value( "MainWindowGeometry", "" ).toByteArray() );
 
955
    restoreState( WQt4Gui::getSettings().value( "MainWindowState", "" ).toByteArray() );
 
956
 
 
957
    m_glDock->restoreGeometry( WQt4Gui::getSettings().value( "GLDockWindowGeometry", "" ).toByteArray() );
 
958
    m_glDock->restoreState( WQt4Gui::getSettings().value( "GLDockWindowState", "" ).toByteArray() );
 
959
}
 
960
 
 
961
void WMainWindow::saveWindowState()
 
962
{
 
963
    wlog::info( "MainWindow" ) << "Saving window state.";
 
964
 
 
965
    // this saves the window state to some common location on the target OS in user scope.
 
966
    WQt4Gui::getSettings().setValue( "MainWindowState", saveState() );
 
967
    WQt4Gui::getSettings().setValue( "GLDockWindowState", m_glDock->saveState() );
 
968
 
 
969
    // NOTE: Qt Doc says that saveState also saves geometry. But this somehow is wrong (at least for 4.6.3)
 
970
    WQt4Gui::getSettings().setValue( "MainWindowGeometry", saveGeometry() );
 
971
    WQt4Gui::getSettings().setValue( "GLDockWindowGeometry", m_glDock->saveGeometry() );
 
972
}
 
973
 
 
974
QSettings& WMainWindow::getSettings()
 
975
{
 
976
    return WQt4Gui::getSettings();
 
977
}
 
978
 
 
979
void WMainWindow::handleLogLevelUpdate( unsigned int logLevel )
 
980
{
 
981
    WLogger::getLogger()->setDefaultLogLevel( static_cast< LogLevel >( logLevel ) );
 
982
}
 
983
 
 
984
void WMainWindow::handleGLVendor()
 
985
{
 
986
    // WARNING: never put blocking code here, as it might freeze the mainGLWidget.
 
987
    std::string vendor = string_utils::toLower( m_mainGLWidget->getViewer()->getOpenGLVendor() );
 
988
 
 
989
    // is this a mesa card?
 
990
    if( vendor.find( "mesa" ) != std::string::npos )
 
991
    {
 
992
        QString msg = "<b>Warning:</b> Your graphics card is powered by the Mesa OpenGL implementation. OpenWalnut does not support Mesa "
 
993
                      "officially, since Mesa has some severe problems with GLSL shaders. You can still use OpenWalnut, but you should be "
 
994
                      "aware that Mesa can freeze OpenWalnut. Ensure you have the latest version of Mesa installed to avoid problems.";
 
995
        QLabel* l = new QLabel( msg );
 
996
        l->setWordWrap( true );
 
997
        l->setMinimumWidth( 640 );
 
998
 
 
999
        WQtMessageDialog* msgDia = new WQtMessageDialog( "MesaWarning", "Mesa Warning", l, getSettings(), this );
 
1000
        msgDia->show();
 
1001
    }
 
1002
 
 
1003
    // is this a mesa card?
 
1004
    if( ( vendor.find( "Chromium" ) != std::string::npos ) ||
 
1005
        ( vendor.find( "Humper" ) != std::string::npos ) )
 
1006
    {
 
1007
        QString msg = "<b>Warning:</b> You seem to use OpenWalnut from inside a virtual machine. Graphics acceleration on these virtual machines"
 
1008
                      " is often limited. OpenWalnut might not properly work in your setup.";
 
1009
        QLabel* l = new QLabel( msg );
 
1010
        l->setWordWrap( true );
 
1011
        l->setMinimumWidth( 640 );
 
1012
 
 
1013
        WQtMessageDialog* msgDia = new WQtMessageDialog( "VMChromiumWarning", "Virtual Machine Warning", l, getSettings(), this );
 
1014
        msgDia->show();
 
1015
    }
 
1016
}
 
1017
 
 
1018
void WMainWindow::showWelcomeDialog( bool force )
 
1019
{
 
1020
    // Load welcome file
 
1021
    std::string filename( WPathHelper::getDocPath().string() + "/openwalnut-qt4/OpenWalnutWelcome.html" );
 
1022
    std::string content = readFileIntoString( filename );
 
1023
 
 
1024
    // gen ID for it using version (allows showing release/welcome message for each new release)
 
1025
    QString msgID = "OpenWalnutWelcome" + QString( W_LIB_VERSION );
 
1026
 
 
1027
    // replace OW_VERSION
 
1028
    boost::regex reg1( "%OW_LIB_VERSION%" );
 
1029
    boost::regex reg2( "%OW_VERSION%" );
 
1030
    content = boost::regex_replace( content, reg1, std::string( W_LIB_VERSION ) );
 
1031
    content = boost::regex_replace( content, reg2, std::string( W_VERSION ) );
 
1032
 
 
1033
    QWidget* w = NULL;
 
1034
#ifndef QT4GUI_NOWEBKIT
 
1035
    QWebView* view = new QWebView( this );
 
1036
    view->setHtml( QString::fromStdString( content ) );
 
1037
    view->setMinimumWidth( 640 );
 
1038
    view->page()->setLinkDelegationPolicy( QWebPage::DelegateExternalLinks );
 
1039
    w = view;
 
1040
#else
 
1041
    QLabel* l = new QLabel( QString::fromStdString( content ) );
 
1042
    l->setWordWrap( true );
 
1043
    l->setMinimumWidth( 640 );
 
1044
    w = l;
 
1045
#endif
 
1046
 
 
1047
    WQtMessageDialog* msgDia = new WQtMessageDialog( msgID, "Welcome to OpenWalnut", w, getSettings(), this );
 
1048
    msgDia->show( force );
 
1049
}
 
1050
 
 
1051
void WMainWindow::handleStartMessages()
 
1052
{
 
1053
    // only show welcome dialog for now
 
1054
    showWelcomeDialog( false );
 
1055
}
 
1056
 
 
1057
void WMainWindow::forceMainGLWidgetSize( size_t w, size_t h )
 
1058
{
 
1059
    m_mainGLWidget->setFixedSize( w, h );
 
1060
}
 
1061
 
 
1062
void WMainWindow::restoreMainGLWidgetSize()
 
1063
{
 
1064
    m_mainGLWidget->setMinimumHeight( 250 );
 
1065
    m_mainGLWidget->setMaximumHeight( QWIDGETSIZE_MAX );
 
1066
    m_mainGLWidget->setMinimumWidth( 250 );
 
1067
    m_mainGLWidget->setMaximumWidth( QWIDGETSIZE_MAX );
 
1068
}
 
1069
 
 
1070
void WMainWindow::handleDrop( QDropEvent* event )
 
1071
{
 
1072
    if( event->mimeData()->hasUrls() )
 
1073
    {
 
1074
        std::vector < std::string > projects;
 
1075
        std::vector < std::string > filenames;
 
1076
        std::vector < std::string > unsupported;
 
1077
        foreach( QUrl url, event->mimeData()->urls() )
 
1078
        {
 
1079
            QString path =  url.toLocalFile();
 
1080
            QFileInfo info( path );
 
1081
            QString suffix =  info.completeSuffix();
 
1082
            if( suffix.endsWith( "cnt" )
 
1083
              || suffix.endsWith( "edf" )
 
1084
              || suffix.endsWith( "asc" )
 
1085
              || suffix.endsWith( "nii" )
 
1086
              || suffix.endsWith( "nii.gz" )
 
1087
              || suffix.endsWith( "fib" ) )
 
1088
            {
 
1089
                filenames.push_back( path.toStdString() );
 
1090
            }
 
1091
            else
 
1092
            {
 
1093
                if( suffix == "owp" || suffix == "owproj" )
 
1094
                {
 
1095
                    projects.push_back( path.toStdString() );
 
1096
                }
 
1097
                else
 
1098
                {
 
1099
                    unsupported.push_back( path.toStdString() );
 
1100
                }
 
1101
            }
 
1102
        }
 
1103
        if( projects.size() > 0 )
 
1104
        {
 
1105
            for( size_t i = 0; i < projects.size(); ++i )
 
1106
            {
 
1107
                asyncProjectLoad( projects[ i ] );
 
1108
            }
 
1109
            event->accept();
 
1110
        }
 
1111
        if( filenames.size() > 0 )
 
1112
        {
 
1113
            m_loaderSignal( filenames );
 
1114
            event->accept();
 
1115
        }
 
1116
        if( unsupported.size() > 0 )
 
1117
        {
 
1118
            QString message = QString() +
 
1119
                "The following files are not supported as standard data types by OpenWalnut at the moment:<br>";
 
1120
            for( size_t i = 0; i < unsupported.size(); ++i )
 
1121
            {
 
1122
                message += QString::fromStdString( unsupported[ i ] ) + QString( "<br>" );
 
1123
            }
 
1124
            message += "There may be additional modules supporting them.<br>"
 
1125
                "All other files have been loaded and should be visible in the module "
 
1126
                "browser and network editor.";
 
1127
            QMessageBox::information( this, "Not yet implemented!",
 
1128
                    message
 
1129
                    );
 
1130
        }
 
1131
    }
 
1132
}
 
1133
 
 
1134
void WMainWindow::dropEvent( QDropEvent* event )
 
1135
{
 
1136
    handleDrop( event );
 
1137
    QMainWindow::dropEvent( event );
 
1138
}
 
1139
 
 
1140
bool WMainWindow::isDropAcceptable( const QMimeData* mimeData )
 
1141
{
 
1142
    if( mimeData->hasUrls() )
 
1143
    {
 
1144
        foreach( QUrl url, mimeData->urls() )
 
1145
        {
 
1146
            QString path =  url.toLocalFile();
 
1147
            QFileInfo info( path );
 
1148
            QString suffix =  info.completeSuffix();
 
1149
            if( suffix.endsWith( "cnt" )
 
1150
              || suffix.endsWith( "edf" )
 
1151
              || suffix.endsWith( "asc" )
 
1152
              || suffix.endsWith( "nii" )
 
1153
              || suffix.endsWith( "nii.gz" )
 
1154
              || suffix.endsWith( "fib" )
 
1155
              || suffix.endsWith( "owp" )
 
1156
              || suffix.endsWith( "owproj" ) )
 
1157
            {
 
1158
                return true;
 
1159
            }
 
1160
        }
 
1161
    }
 
1162
 
 
1163
    return false;
 
1164
}
 
1165
 
 
1166
void WMainWindow::dragMoveEvent( QDragMoveEvent* event )
 
1167
{
 
1168
    if( WMainWindow::isDropAcceptable( event->mimeData() ) )
 
1169
    {
 
1170
        event->acceptProposedAction();
 
1171
    }
 
1172
    QMainWindow::dragMoveEvent( event );
 
1173
}
 
1174
 
 
1175
void WMainWindow::dragEnterEvent( QDragEnterEvent* event )
 
1176
{
 
1177
    if( WMainWindow::isDropAcceptable( event->mimeData() ) )
 
1178
    {
 
1179
        event->acceptProposedAction();
 
1180
    }
 
1181
    QMainWindow::dragEnterEvent( event );
 
1182
}
 
1183
 
 
1184
void WMainWindow::closeSplash()
 
1185
{
 
1186
    m_splash->finish( this );
 
1187
}
 
1188
 
 
1189
QSplashScreen* WMainWindow::getSplash() const
 
1190
{
 
1191
    return m_splash;
 
1192
}
 
1193
 
 
1194
/**
 
1195
 * Create a distinct separator.
 
1196
 *
 
1197
 * \param parent the parent
 
1198
 *
 
1199
 * \return the separator
 
1200
 */
 
1201
QAction* createSeperator( QWidget* parent )
 
1202
{
 
1203
    QAction* separator = new QAction( parent );
 
1204
    separator->setSeparator( true );
 
1205
    return separator;
 
1206
}
 
1207
 
 
1208
void WMainWindow::addGlobalMenu( QWidget* widget )
 
1209
{
 
1210
    widget->addAction( createSeperator( this ) );
 
1211
    widget->addAction( m_loadButton );
 
1212
    widget->addAction( m_saveAction );
 
1213
    widget->addAction( createSeperator( this ) );
 
1214
    widget->addAction( m_viewAction );
 
1215
    widget->addAction( m_cameraAction );
 
1216
    widget->addAction( m_settingsAction );
 
1217
    widget->addAction( createSeperator( this ) );
 
1218
    widget->addAction( m_helpAction );
 
1219
    widget->addAction( createSeperator( this ) );
 
1220
    widget->addAction( m_quitAction );
 
1221
}
 
1222