OpenWalnut  1.5.0dev
WMainWindow.cpp
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 <memory>
28 #include <string>
29 #include <vector>
30 
31 #include <boost/thread.hpp>
32 #include <boost/regex.hpp>
33 #include <boost/filesystem.hpp>
34 
35 #include <QApplication>
36 #include <QCloseEvent>
37 #include <QDockWidget>
38 #include <QFileDialog>
39 #include <QIcon>
40 #include <QMenu>
41 #include <QMenuBar>
42 #include <QMessageBox>
43 #include <QTextEdit>
44 #include <QShortcut>
45 #include <QSlider>
46 #include <QVBoxLayout>
47 #include <QWidget>
48 #include <QtCore/QSettings>
49 #include <QtCore/QUrl>
50 #include <QInputDialog>
51 #ifdef OW_FORCE_WEBKIT
52  #include <QWebView> // NOLINT
53 #else
54  #include <QWebEngineView> // NOLINT
55 #endif
56 
57 #include "core/WVersion.h" // NOTE: this file is auto-generated by CMAKE
58 
59 #include "controlPanel/WPropertyBoolWidget.h"
60 #include "controlPanel/WQtControlPanel.h"
61 #include "core/common/WColor.h"
62 #include "core/common/WIOTools.h"
63 #include "core/common/WPathHelper.h"
64 #include "core/common/WProjectFileIO.h"
65 #include "core/dataHandler/WDataHandler.h"
66 #include "core/dataHandler/WDataSetFibers.h"
67 #include "core/dataHandler/WDataSetSingle.h"
68 #include "core/dataHandler/WDataSetPoints.h"
69 #include "core/dataHandler/WEEG2.h"
70 #include "core/graphicsEngine/WGEZoomTrackballManipulator.h"
71 #include "core/graphicsEngine/WROIBox.h"
72 #include "core/kernel/WDataModule.h"
73 #include "core/kernel/WKernel.h"
74 #include "core/kernel/WModule.h"
75 #include "core/kernel/WModuleFactory.h"
76 #include "core/kernel/WModuleCombiner.h"
77 #include "core/kernel/WModuleCombinerTypes.h"
78 #include "core/kernel/WDataModuleInputFilterFile.h"
79 #include "core/kernel/WProjectFile.h"
80 #include "core/kernel/WROIManager.h"
81 #include "core/kernel/WSelectionManager.h"
82 #include "events/WEventTypes.h"
83 #include "events/WDeferredCallEvent.h"
84 #include "events/WModuleCrashEvent.h"
85 #include "events/WModuleReadyEvent.h"
86 #include "events/WModuleRemovedEvent.h"
87 #include "events/WLoadFinishedEvent.h"
88 #include "events/WLogEvent.h"
89 #include "guiElements/WQtPropertyBoolAction.h"
90 #include "abstractUI/WUIQtWidgetBase.h"
91 #include "WQtMessagePopup.h"
92 #include "WQtGui.h"
93 #include "WQtCombinerToolbar.h"
94 #include "WQtGLDockWidget.h"
95 #include "WQtNavGLWidget.h"
96 #include "WSettingAction.h"
97 #include "WSettingMenu.h"
98 #include "WQtMessageDialog.h"
99 
100 #include "WMainWindow.h"
101 
102 WMainWindow::WMainWindow( QSplashScreen* splash ):
103  QMainWindow(),
104  m_splash( splash ),
105  m_currentCompatiblesToolbar( NULL ),
106  m_iconManager(),
107  m_closeFirstStage( false ),
108  m_closeInProgress( false )
109 {
110  setAcceptDrops( true ); // enable drag and drop events
111 }
112 
114 {
115  // cleanup
116 }
117 
118 /**
119  * Create a distinct separator.
120  *
121  * \param parent the parent
122  *
123  * \return the separator
124  */
125 QAction* createSeperator( QWidget* parent )
126 {
127  QAction* separator = new QAction( parent );
128  separator->setSeparator( true );
129  return separator;
130 }
131 
133 {
134  wlog::info( "WMainWindow" ) << "Setting up GUI";
135 
136  /////////////////////////////////////////////////////////////////////////////////////////////////////////////////
137  // Setting setup
138  /////////////////////////////////////////////////////////////////////////////////////////////////////////////////
139 
140  WSettingAction* hideMenuAction = new WSettingAction( this, "qtgui/showMenu",
141  "Show Menubar",
142  "Allows you to hide the menu. Can be restored using CTRL-M.",
143  true,
144  false,
145  QKeySequence( Qt::CTRL + Qt::Key_M ) );
146 
147  WSettingAction* showNavWidgets = new WSettingAction( this, "qtgui/showNavigationWidgets",
148  "Show Navigation Views",
149  "Disables the navigation views completely. This can lead to a speed-up and is "
150  "recommended for those who do not need them.",
151  false,
152  true // this requires a restart
153  );
154  m_sliderMinMaxEditSetting = new WSettingAction( this, std::string( "qtgui/" ) + std::string( "sliderMinMaxEdit" ),
155  "Slider Min/Max Editing",
156  "If enabled, the maximum and minimum values of slider can be edited.",
157  false );
158 
159  WSettingAction* mtViews = new WSettingAction( this, "qtgui/ge/multiThreadedViewer",
160  "Multi-Threaded Views",
161  "If enabled, the graphic windows are rendered in different threads. This can speed-up "
162  "rendering on machines with multiple cores. WARNING: can lead to crashes sometimes.",
163  false,
164  true // require restart
165  );
166  // NOTE: the multi-threading feature needs to be activated BEFORE the first viewer is created. To ensure this we do it here.
167  WGraphicsEngine::getGraphicsEngine()->setMultiThreadedViews( mtViews->get() );
168 
169  // set the log-level setting.
170  // NOTE: see WQtGui which reads the setting.
171  QList< QString > logOptions;
172  logOptions.push_back( "Debug" );
173  logOptions.push_back( "Info" );
174  logOptions.push_back( "Warning" );
175  logOptions.push_back( "Error" );
176  WSettingMenu* logLevels = new WSettingMenu( this, "qtgui/logLevel",
177  "Log-Level",
178  "Allows one to set the log verbosity.",
179  1, // info is the default
180  logOptions
181  );
182  connect( logLevels, SIGNAL( change( unsigned int ) ), this, SLOT( handleLogLevelUpdate( unsigned int ) ) );
183 
184  /////////////////////////////////////////////////////////////////////////////////////////////////////////////////
185  // GUI setup
186  /////////////////////////////////////////////////////////////////////////////////////////////////////////////////
187 
188  // We need several icons later in the GUI. Build some mappings:
189  m_iconManager.addMapping( "logo", "openwalnut" );
190  m_iconManager.addMapping( "axial icon", "orientation_axial" );
191  m_iconManager.addMapping( "coronal icon", "orientation_coronal" );
192  m_iconManager.addMapping( "sagittal icon", "orientation_sagittal" );
193  m_iconManager.addMapping( "center icon", "center_scene" );
194  m_iconManager.addMapping( "DefaultModuleIcon", "default" );
195  m_iconManager.addMapping( "missingModule", "question" );
196  m_iconManager.addMapping( "view", "camera" );
197  m_iconManager.addMapping( "moduleCrashed", "error" );
198  m_iconManager.addMapping( "moduleBusy", "busy" );
199  m_iconManager.addMapping( "saveProject", "save" );
200  m_iconManager.addMapping( "newProject", "new" );
201 
202  if( objectName().isEmpty() )
203  {
204  setObjectName( QString::fromUtf8( "MainWindow" ) );
205  }
206 
207  // NOTE: this only is an initial size. The state reloaded from QSettings will set it to the value the user had last session.
208  resize( 1024, 768 );
209  setWindowIcon( m_iconManager.getIcon( "logo" ) );
210  std::string windowHeading = std::string( "OpenWalnut " ) + std::string( W_VERSION );
211  setWindowTitle( QString::fromStdString( windowHeading ) );
212 
213  setDockOptions( QMainWindow::AnimatedDocks | QMainWindow::AllowNestedDocks | QMainWindow::AllowTabbedDocks );
214 
215  //network Editor
216  m_networkEditor = NULL;
217  m_networkEditor = new WQtNetworkEditor( this );
218  m_networkEditor->setFeatures( QDockWidget::DockWidgetClosable | QDockWidget::DockWidgetMovable | QDockWidget::DockWidgetFloatable );
219 
220  // strangely, the QGraphics* objects do not properly forward drag/drop events. We need to explicitly handle them.
221  connect( m_networkEditor->getView(), SIGNAL( dragDrop( QDropEvent* ) ),
222  this, SLOT( handleDrop( QDropEvent* ) ) );
223 
224  // the control panel instance is needed for the menu
225  m_controlPanel = new WQtControlPanel( this );
226  m_controlPanel->setFeatures( QDockWidget::DockWidgetClosable | QDockWidget::DockWidgetMovable | QDockWidget::DockWidgetFloatable );
227  m_controlPanel->addSubject( "Default Subject" );
228 
229  // add all docks
230  addDockWidget( Qt::RightDockWidgetArea, m_controlPanel->getModuleDock() );
231  if( m_networkEditor )
232  {
233  addDockWidget( Qt::RightDockWidgetArea, m_networkEditor );
234  }
235 
236  addDockWidget( Qt::RightDockWidgetArea, m_controlPanel->getColormapperDock() );
237  addDockWidget( Qt::RightDockWidgetArea, m_controlPanel->getRoiDock() );
238 
239  // the message dock:
240  m_messageDock = new WQtMessageDock( "Messages", this );
241  addDockWidget( Qt::RightDockWidgetArea, m_messageDock );
242 
243  // tabify those panels by default
244  if( m_networkEditor )
245  {
246  tabifyDockWidget( m_networkEditor, m_controlPanel->getModuleDock() );
247  }
249  tabifyDockWidget( m_controlPanel->getColormapperDock(), m_controlPanel->getRoiDock() );
250  tabifyDockWidget( m_controlPanel->getRoiDock(), m_messageDock );
251 
252  m_glDock = new QMainWindow();
253  m_glDock->setObjectName( "GLDock" );
254  m_glDock->setDockOptions( QMainWindow::AnimatedDocks | QMainWindow::AllowNestedDocks | QMainWindow::AllowTabbedDocks );
255  m_glDock->setDocumentMode( true );
256  setCentralWidget( m_glDock );
257 
258  m_mainGLDock = new WQtGLDockWidget( "Main View", "3D View", m_glDock );
259  // activate effects for this view by default
260  m_mainGLDock->getGLWidget()->getViewer()->setEffectsActiveDefault();
261  m_mainGLDock->getGLWidget()->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding );
264  m_glDock->addDockWidget( Qt::LeftDockWidgetArea, m_mainGLDock );
265  connect( m_mainGLWidget, SIGNAL( renderedFirstFrame() ), this, SLOT( handleGLVendor() ) );
266 
267  addDockWidget( Qt::RightDockWidgetArea, m_controlPanel );
268 
269  // by default, the module editor should be in front
270  if( m_networkEditor )
271  {
272  m_networkEditor->raise();
273  }
274  else
275  {
276  m_controlPanel->getModuleDock()->raise();
277  }
278 
279  // NOTE: we abuse the gl widgets first frame event to handle startup news.
280  connect( m_mainGLWidget, SIGNAL( renderedFirstFrame() ), this, SLOT( handleStartMessages() ) );
281  connect( m_mainGLWidget, SIGNAL( renderedFirstFrame() ), this, SLOT( closeSplash() ) );
282 
283  m_permanentToolBar = new WQtToolBar( "Standard Toolbar", this );
284  addToolBar( Qt::TopToolBarArea, m_permanentToolBar );
285 
286  // math: Due to the OLD issue 406 resp.
287  // http://stackoverflow.com/questions/31983269/how-to-identify-a-certain-qt-widget
288  // There might be a white box, on Apple Mac OSX only, which sometimes hides the window buttons
289  // for maximization, minimization and closing. This is extremely disturbing, hence, we leave them
290  // visible as a default. I know this fixes only the symptom, but not the origin, but I've searched
291  // some days by now and couldn't find anything. I will describe all I found so far in the ticket 406.
292  // #ifndef W_OS_OSX
293  // m_permanentToolBar->setVisible( false );
294  // #else
295  // m_permanentToolBar->setVisible( true );
296  // #endif
297  m_permanentToolBar->setVisible( true );
298 
299  m_loadButton = new QAction( m_iconManager.getIcon( "load" ), "Load Dataset or Project", m_permanentToolBar );
300  m_loadButton->setShortcut( QKeySequence( QKeySequence::Open ) );
301  QAction* roiButton = new QAction( m_iconManager.getIcon( "add_roi" ), "ROI", m_permanentToolBar );
302  m_saveAction = new QAction( m_iconManager.getIcon( "saveProject" ), "Save Project", m_permanentToolBar );
303 
304  connect( m_loadButton, SIGNAL( triggered( bool ) ), this, SLOT( openLoadDialog() ) );
305  connect( roiButton, SIGNAL( triggered( bool ) ), this, SLOT( newRoi() ) );
306  connect( m_saveAction, SIGNAL( triggered( bool ) ), this, SLOT( projectSaveAll() ) );
307 
308  m_loadButton->setToolTip( "Load a dataset or project from file" );
309  roiButton->setToolTip( "Insert a new ROI" );
310  m_saveAction->setToolTip( "Save current project to file" );
311 
312  // we want the upper most tree item to be selected. This helps to make the always compatible modules
313  // show up in the tool bar from the beginning. And ... it doesn't hurt.
315 
316  // NOTE: Please be aware that not every menu needs a shortcut key. If you add a shortcut, you should use one of the
317  // QKeySequence::StandardKey defaults and avoid ambiguities like Ctrl-C for the configure dialog is not the best choice as Ctrl-C, for the
318  // most users is the Copy shortcut.
319 
320  m_menuBar = new QMenuBar( this );
321 
322  // hide menu?
323  m_menuBar->setVisible( hideMenuAction->get() );
324  connect( hideMenuAction, SIGNAL( change( bool ) ), m_menuBar, SLOT( setVisible( bool ) ) );
325  addAction( hideMenuAction );
326 
327  QMenu* fileMenu = m_menuBar->addMenu( "File" );
328 
329  m_newAction = fileMenu->addAction( m_iconManager.getIcon( "newProject" ),
330  "New Project",
331  this,
332  SLOT( newProject() ),
333  QKeySequence( Qt::CTRL + Qt::Key_N ) );
334  fileMenu->addAction( m_loadButton );
335  m_saveMenu = fileMenu->addMenu( m_iconManager.getIcon( "saveProject" ), "Save Project" );
336  m_saveMenu->addAction( "Save Project", this, SLOT( projectSaveAll() ), QKeySequence::Save );
337  m_saveMenu->addAction( "Save Modules Only", this, SLOT( projectSaveModuleOnly() ) );
338  m_saveMenu->addAction( "Save Camera Only", this, SLOT( projectSaveCameraOnly() ) );
339  // saveMenu->addAction( "Save ROIs Only", this, SLOT( projectSaveROIOnly() ) );
340  m_saveAction->setMenu( m_saveMenu );
341 
342  fileMenu->addSeparator();
343  m_quitAction = fileMenu->addAction( m_iconManager.getIcon( "quit" ), "Quit", this, SLOT( close() ), QKeySequence( QKeySequence::Quit ) );
344 
345  // This QAction stuff is quite ugly and complicated some times ... There is no nice constructor which takes name, slot keysequence and so on
346  // directly -> set shortcuts, and some further properties using QAction's interface
347 
348  m_settingsAction = new QAction( "Settings", this );
349  m_settingsAction->setIcon( m_iconManager.getIcon( "configure" ) );
350  m_settingsMenu = m_menuBar->addMenu( "Settings" );
351  m_viewMenu = m_settingsMenu->addMenu( "View" );
352  m_viewMenu->addAction( hideMenuAction );
353  m_viewMenu->addSeparator();
354  m_viewMenu->addAction( showNavWidgets );
355  m_viewMenu->addSeparator();
359  m_settingsMenu->addSeparator();
360  m_settingsMenu->addAction( mtViews );
361  m_settingsMenu->addSeparator();
362  m_settingsMenu->addMenu( logLevels );
363  m_settingsMenu->addSeparator();
364  m_settingsAction->setMenu( m_settingsMenu );
365 
366  QAction* controlPanelTrigger = m_controlPanel->toggleViewAction();
367  QList< QKeySequence > controlPanelShortcut;
368  controlPanelShortcut.append( QKeySequence( Qt::Key_F9 ) );
369  controlPanelTrigger->setShortcuts( controlPanelShortcut );
370  this->addAction( controlPanelTrigger ); // this enables the action even if the menu bar is invisible
371 
372  m_helpAction = new QAction( "Help", this );
373  m_helpAction->setIcon( m_iconManager.getIcon( "questionmark" ) );
374  connect( m_helpAction, SIGNAL( triggered() ), this, SLOT( openOpenWalnutHelpDialog() ) );
375  m_helpMenu = m_menuBar->addMenu( "Help" );
376  m_helpMenu->addAction( m_iconManager.getIcon( "logo" ), "Welcome to OpenWalnut", this, SLOT( showWelcomeDialog() ) );
377  m_helpMenu->addAction( m_iconManager.getIcon( "help" ), "OpenWalnut Help", this, SLOT( openOpenWalnutHelpDialog() ),
378  QKeySequence( QKeySequence::HelpContents ) );
379  m_helpMenu->addSeparator();
380  m_helpMenu->addAction( m_iconManager.getIcon( "logo" ), "About OpenWalnut", this, SLOT( openAboutDialog() ) );
381  m_helpMenu->addAction( m_iconManager.getIcon( "qt" ), "About Qt", this, SLOT( openAboutQtDialog() ) );
382  m_helpAction->setMenu( m_helpMenu );
383  connect( m_helpAction, SIGNAL( triggered( bool ) ), this, SLOT( openOpenWalnutHelpDialog() ) );
384 
385  setMenuBar( m_menuBar );
386 
387  // initially 3 navigation views
388  {
389  if( showNavWidgets->get() )
390  {
391  m_navAxial = std::shared_ptr< WQtNavGLWidget >( new WQtNavGLWidget( "Axial View", "Axial View", this, "Axial Slice",
392  m_mainGLWidget ) );
393  m_navAxial->setFeatures( QDockWidget::DockWidgetClosable | QDockWidget::DockWidgetMovable | QDockWidget::DockWidgetFloatable );
394  m_navAxial->setSliderProperty( WKernel::getRunningKernel()->getSelectionManager()->getPropAxialPos() );
395  m_navAxial->getGLWidget()->setCameraManipulator( WQtGLWidget::NO_OP );
396 
397  addDockWidget( Qt::LeftDockWidgetArea, m_navAxial.get(), Qt::Vertical );
398 
399  m_navCoronal = std::shared_ptr< WQtNavGLWidget >( new WQtNavGLWidget( "Coronal View", "Coronal View", this, "Coronal Slice",
400  m_mainGLWidget ) );
401  m_navCoronal->setFeatures( QDockWidget::DockWidgetClosable | QDockWidget::DockWidgetMovable | QDockWidget::DockWidgetFloatable );
402  m_navCoronal->setSliderProperty( WKernel::getRunningKernel()->getSelectionManager()->getPropCoronalPos() );
403  m_navCoronal->getGLWidget()->setCameraManipulator( WQtGLWidget::NO_OP );
404 
405  addDockWidget( Qt::LeftDockWidgetArea, m_navCoronal.get(), Qt::Vertical );
406 
407  m_navSagittal =
408  std::shared_ptr< WQtNavGLWidget >( new WQtNavGLWidget( "Sagittal View", "Sagittal View", this, "Sagittal Slice",
409  m_mainGLWidget ) );
410  m_navSagittal->setFeatures( QDockWidget::DockWidgetClosable | QDockWidget::DockWidgetMovable | QDockWidget::DockWidgetFloatable );
411  m_navSagittal->setSliderProperty( WKernel::getRunningKernel()->getSelectionManager()->getPropSagittalPos() );
412  m_navSagittal->getGLWidget()->setCameraManipulator( WQtGLWidget::NO_OP );
413 
414  addDockWidget( Qt::LeftDockWidgetArea, m_navSagittal.get(), Qt::Vertical );
415  }
416  }
417 
418  // create the show/hide actions using the selection manager's props
419  WQtPropertyBoolAction* showAxial = new WQtPropertyBoolAction( WKernel::getRunningKernel()->getSelectionManager()->getPropAxialShow(),
421  showAxial->setToolTip( "Toggle axial slice" );
422  showAxial->setText( "Toggle Axial Slice" );
423  showAxial->setIcon( m_iconManager.getIcon( "axial icon" ) );
424 
425  WQtPropertyBoolAction* showCoronal = new WQtPropertyBoolAction( WKernel::getRunningKernel()->getSelectionManager()->getPropCoronalShow(),
427  showCoronal->setToolTip( "Toggle coronal slice" );
428  showCoronal->setText( "Toggle Coronal Slice" );
429  showCoronal->setIcon( m_iconManager.getIcon( "coronal icon" ) );
430 
431  WQtPropertyBoolAction* showSagittal = new WQtPropertyBoolAction( WKernel::getRunningKernel()->getSelectionManager()->getPropSagittalShow(),
433  showSagittal->setToolTip( "Toggle sagittal slice" );
434  showSagittal->setText( "Toggle Sagittal Slice" );
435  showSagittal->setIcon( m_iconManager.getIcon( "sagittal icon" ) );
436 
437  // setup permanent toolbar
441  m_permanentToolBar->addSeparator();
442  m_permanentToolBar->addAction( roiButton );
443  m_permanentToolBar->addSeparator();
444  m_permanentToolBar->addAction( showAxial );
445  m_permanentToolBar->addAction( showCoronal );
446  m_permanentToolBar->addAction( showSagittal );
447  m_permanentToolBar->addSeparator();
448 
449  // set the according actions to the toolbars
456 
457  // allow the control panel to complete setup
459 
460  // add the roi actions to roi dock title
461  m_controlPanel->getRoiDock()->addTitleAction( roiButton );
463 
464  // after creating the GUI, restore its saved state
466 
467  // this ensures that there is always at least the main window visible. Removing this might cause a freeze on startup if the user has closed
468  // all gl widgets during the last session.
469  m_mainGLDock->setVisible( true );
470 }
471 
472 void WMainWindow::autoAdd( std::shared_ptr< WModule > module, std::string proto, bool onlyOnce )
473 {
474  // if only one module should be added, and there already is one --- skip.
475  if( onlyOnce && !WKernel::getRunningKernel()->getRootContainer()->getModules( proto ).empty() )
476  {
477  return;
478  }
479 
480  // get the prototype.
481  if( !WKernel::getRunningKernel()->getRootContainer()->applyModule( module, proto, true ) )
482  {
483  WLogger::getLogger()->addLogMessage( "Auto Display active but module " + proto + " could not be added.",
484  "GUI", LL_ERROR );
485  }
486 }
487 
488 void WMainWindow::moduleSpecificCleanup( std::shared_ptr< WModule > /* module */ )
489 {
490  // called for each removed module. Use this to undo modifications done due to added modules (moduleSpecificSetup)
491 }
492 
493 void WMainWindow::moduleSpecificSetup( std::shared_ptr< WModule > /* module */ )
494 {
495  // Add all special handlings here. This method is called whenever a module is marked "ready". You can set up the gui for special modules,
496  // load certain modules for datasets and so on.
497 
498  // 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.
499  // NOTE: Auto Display is currently disabled.
500  /*bool useAutoDisplay = m_autoDisplaySetting->get();
501  if( useAutoDisplay && module->getType() == MODULE_DATA )
502  {
503  WLogger::getLogger()->addLogMessage( "Auto Display active and Data module added. The proper module will be added.",
504  "GUI", LL_DEBUG );
505 
506  // data modules contain an member denoting the real data type. Currently we only have one data module and a not very modulated data
507  // structures.
508  std::shared_ptr< WDataModule > dataModule = std::static_pointer_cast< WDataModule >( module );
509 
510  // grab data and identify type
511  if( dataModule->getDataSet()->isA< WDataSetSingle >() && dataModule->getDataSet()->isTexture() )
512  {
513  // it is a dataset single
514  // load a nav slice module if a WDataSetSingle is available!?
515  autoAdd( module, "Navigation Slices", true );
516  }
517  else if( dataModule->getDataSet()->isA< WDataSetFibers >() )
518  {
519  // it is a fiber dataset -> add the FiberDisplay module
520  autoAdd( module, "Fiber Display" );
521  }
522  else if( dataModule->getDataSet()->isA< WEEG2 >() )
523  {
524  // it is a eeg dataset -> add the eegView module
525  autoAdd( module, "EEG View" );
526  }
527  else if( dataModule->getDataSet()->isA< WDataSetPoints >() )
528  {
529  // it is a point dataset -> add the point render module
530  autoAdd( module, "Point Renderer" );
531  }
532  }*/
533 }
534 
536 {
538  {
540  }
541  m_currentCompatiblesToolbar = toolbar;
542 
543  if( !toolbar )
544  {
545  // ok, reset the toolbar
546  // So create a dummy to permanently reserve the space
548  }
549 
550  // we want to keep the tool-button styles in sync
551  m_currentCompatiblesToolbar->setToolButtonStyle( m_permanentToolBar->toolButtonStyle() );
552  connect( m_permanentToolBar, SIGNAL( toolButtonStyleChanged( Qt::ToolButtonStyle ) ),
553  m_currentCompatiblesToolbar, SLOT( setToolButtonStyle( Qt::ToolButtonStyle ) ) );
554 
555  // and the position of the toolbar
556  // math: Due to the OLD issue 406 resp.
557  // http://stackoverflow.com/questions/31983269/how-to-identify-a-certain-qt-widget
558  // There might be a white box, on Apple Mac OSX only, which sometimes hides the window buttons
559  // for maximization, minimization and closing. This is extremely disturbing, hence, we leave them
560  // visible as a default. I know this fixes only the symptom, but not the origin, but I've searched
561  // some days by now and couldn't find anything. I will describe all I found so far in the ticket 406.
562  // #ifndef W_OS_OSX
563  // toolbar->setVisible( false );
564  // #else
565  // toolbar->setVisible( true );
566  // #endif
567  toolbar->setVisible( true );
568 
569  addToolBar( Qt::TopToolBarArea, m_currentCompatiblesToolbar );
570 }
571 
573 {
575 }
576 
578 {
579  return m_controlPanel;
580 }
581 
583 {
584  return m_networkEditor;
585 }
586 
587 bool WMainWindow::projectSave( const std::vector< std::shared_ptr< WProjectFileIO > >& writer )
588 {
589  QString lastPath = WQtGui::getSettings().value( "LastProjectSavePath", "" ).toString();
590  QString selected = QFileDialog::getSaveFileName( this, "Save Project as", lastPath,
591  "Project File (*.owproj *.owp)" );
592  if( selected == "" )
593  {
594  return false;
595  }
596 
597  // extract path and save to settings
598  boost::filesystem::path p( selected.toStdString() );
599  WQtGui::getSettings().setValue( "LastProjectSavePath", QString::fromStdString( p.parent_path().string() ) );
600 
601  bool success = true;
602  std::string filename = ( selected ).toStdString();
603 
604  // append owp if suffix is not present, yet
605  if( filename.rfind( ".owp" ) != filename.size() - 4
606  && filename.rfind( ".owproj" ) != filename.size() - 7 )
607  {
608  filename += ".owp";
609  }
610 
611  std::shared_ptr< WProjectFile > proj = std::shared_ptr< WProjectFile >(
612  new WProjectFile( filename )
613  );
614 
615  try
616  {
617  // This call is synchronous.
618  if( writer.empty() )
619  {
620  proj->save();
621  }
622  else
623  {
624  proj->save( writer );
625  }
626  }
627  catch( const std::exception& e )
628  {
629  QString title = "Problem while saving project file.";
630  QString message = "<b>Problem while saving project file.</b><br/><br/><b>File: </b>" + selected +
631  "<br/><b>Message: </b>" + QString::fromStdString( e.what() );
632  QMessageBox::critical( this, title, message );
633  success = false;
634  }
635  return success;
636 }
637 
639 {
640  std::vector< std::shared_ptr< WProjectFileIO > > w;
641  // an empty list equals "all"
642  return projectSave( w );
643 }
644 
646 {
647  std::vector< std::shared_ptr< WProjectFileIO > > w;
648  w.push_back( WProjectFile::getCameraWriter() );
649  return projectSave( w );
650 }
651 
653 {
654  std::vector< std::shared_ptr< WProjectFileIO > > w;
655  w.push_back( WProjectFile::getROIWriter() );
656  return projectSave( w );
657 }
658 
660 {
661  std::vector< std::shared_ptr< WProjectFileIO > > w;
662  w.push_back( WProjectFile::getModuleWriter() );
663  return projectSave( w );
664 }
665 
667 {
669  WDataHandler::getDataHandler()->clear();
670 }
671 
672 QString collectFilters()
673 {
674  QString result;
675  QString all;
676 
677  // add all the filters the data modules provide
678  std::vector< WDataModule::SPtr > dataModules = WModuleFactory::getModuleFactory()->getPrototypesByType< WDataModule >();
679 
680  for( std::vector< WDataModule::SPtr >::const_iterator iter = dataModules.begin(); iter != dataModules.end(); ++iter )
681  {
682  std::vector< WDataModuleInputFilter::ConstSPtr > filters = ( *iter )->getInputFilter();
683  for( std::vector< WDataModuleInputFilter::ConstSPtr >::const_iterator filterIter = filters.begin(); filterIter != filters.end();
684  ++filterIter )
685  {
686  WDataModuleInputFilterFile::ConstSPtr ff = std::dynamic_pointer_cast< const WDataModuleInputFilterFile >( *filterIter );
687  if( ff )
688  {
689  QString description = QString::fromStdString( ff->getDescription() );
690  QString extension = QString::fromStdString( ff->getExtension() );
691  all += QString( " *." ) + extension;
692  result += description + QString( "(*." ) + extension + QString( ");;" );
693  }
694  }
695  }
696 
697  // Project files:
698  all += QString( " *.owp *.owproj" );
699  result += QString( "Project File (*.owp *.owproj );;" );
700 
701  // Interpreter files.
702  for( std::size_t k = 0; k < WKernel::getRunningKernel()->getScriptEngine()->getNumInterpreters(); ++k )
703  {
704  QString description = QString::fromStdString( WKernel::getRunningKernel()->getScriptEngine()->getInterpreter( k )->getName() );
705  // NOTE: unlike above, this already contains the "."
706  QString extension = QString::fromStdString( WKernel::getRunningKernel()->getScriptEngine()->getInterpreter( k )->getExtension() );
707  all += QString( " *" ) + extension;
708  result += description + QString( "(*" ) + extension + QString( ");;" );
709  }
710 
711  // math: on 11. Aug. 2015, related old issues 404
712  // The following #ifdef is due to the following QT-Bug: https://bugreports.qt.io/browse/QTBUG-38303
713  // Hence, we use any file as known file type for MAC OSX only.
714  #ifdef Q_OS_OSX
715  return QString( "Known file types (* " ) + all + QString( ");;" ) + result;
716  #else
717  return QString( "Known file types (" ) + all + QString( ");;" ) + result;
718  #endif
719 }
720 
722 {
723  QString lastPath = WQtGui::getSettings().value( "LastOpenPath", "" ).toString();
724 
725  // build filter list
726  // NOTE: Qt Doc says we need to separate multiple filters by ";;"
727  QString filters = collectFilters();
728  // add extensions of script files
729  filters += QString( "Any files (*)" );
730 
731  QStringList filenames = QFileDialog::getOpenFileNames( this, "Open Data, Project or Script", lastPath, filters );
732  if( filenames.empty() )
733  {
734  return;
735  }
736 
737  // extract path and save to settings
738  boost::filesystem::path p( filenames[0].toStdString() );
739  WQtGui::getSettings().setValue( "LastOpenPath", QString::fromStdString( p.parent_path().string() ) );
740 
741  std::vector< std::string > loadDataFilenames;
742  QStringList::const_iterator constIterator;
743  for( constIterator = filenames.constBegin(); constIterator != filenames.constEnd(); ++constIterator )
744  {
745  boost::filesystem::path fn( ( *constIterator ).toLocal8Bit().constData() );
746  std::string suffix = getSuffix( fn );
747 
748  // is this a project file?
749  if( ( suffix == ".owp" ) || ( suffix == ".owproj" ) )
750  {
751  asyncProjectLoad( fn.string() );
752  }
753  else
754  {
755  // this is not a project. So we assume it is a data file or script
756  std::shared_ptr< WScriptInterpreter > scriptInterpreter =
757  WKernel::getRunningKernel()->getScriptEngine()->getInterpreterByFileExtension( suffix );
758 
759  if( scriptInterpreter )
760  {
761  scriptInterpreter->executeFileAsync( fn.string() );
762  }
763  else
764  {
765  loadDataFilenames.push_back( fn.string() );
766  }
767  }
768  }
769 
770  m_loaderSignal( loadDataFilenames );
771 }
772 
773 void WMainWindow::asyncProjectLoad( std::string filename )
774 {
775  WProjectFile::SPtr proj( new WProjectFile( filename, boost::bind( &WMainWindow::slotLoadFinished,
776  this,
777  boost::placeholders::_1,
778  boost::placeholders::_2,
779  boost::placeholders::_3 ) ) );
780  proj->load();
781 }
782 
783 void WMainWindow::slotLoadFinished( boost::filesystem::path file, std::vector< std::string > errors, std::vector< std::string > warnings )
784 {
785  // as this function might be called from outside the gui thread, use an event:
786  QCoreApplication::postEvent( this, new WLoadFinishedEvent( file, errors, warnings ) );
787 
788  if( errors.size() )
789  {
790  wlog::warn( "MainWindow" ) << "Async load error occurred. Informing user.";
791  }
792 }
793 
795 {
796  QMessageBox::aboutQt( this, "About Qt" );
797 }
798 
800 {
801  std::string filename( WPathHelper::getDocPath().string() + "/openwalnut-qt/OpenWalnutAbout.html" );
802  std::string content = readFileIntoString( filename );
803  std::string windowHeading = std::string( "About OpenWalnut " ) + std::string( W_VERSION );
804  QMessageBox::about( this, windowHeading.c_str(), content.c_str() );
805 }
806 
808 {
809  std::string filename( WPathHelper::getDocPath().string() + "/openwalnut-qt/OpenWalnutHelp.html" );
810 
811  std::string content = readFileIntoString( filename );
812 
813  QWidget* window = new QWidget( this, Qt::Window );
814  window->setWindowTitle( "OpenWalnut Help" );
815  // specify intial layout
816  QVBoxLayout *layout = new QVBoxLayout( window );
817  window->setLayout( layout );
818  window->resize( 500, 500 );
819 
820  window->show();
821 
822 #ifdef OW_FORCE_WEBKIT
823  QWebView *view = new QWebView( this );
824 #else
825  QWebEngineView *view = new QWebEngineView( this );
826 #endif
827 
828  QString location( QString( "file://" ) + WPathHelper::getDocPath().string().c_str() + "/openwalnut-qt/" );
829  view->setHtml( content.c_str(), QUrl( location ) );
830  view->show();
831  layout->addWidget( view );
832 }
833 
835 {
836  QMessageBox::information( this, "Not yet implemented!",
837  "This functionality is planned for future versions of OpenWalnut. "
838  "It is not yet implemented." );
839 }
840 
841 boost::signals2::signal< void( std::vector< std::string > ) >* WMainWindow::getLoaderSignal()
842 {
843  return &m_loaderSignal;
844 }
845 
847 {
848  return &m_iconManager;
849 }
850 
852 {
854 
855  // close all registered custom widgets -> modules might have missed them.
856  // But first, we need to copy the custom widget list as the close function of the custom widgets modifies this list
857  CustomWidgets copy;
858  {
860  copy = r->get();
861  // IMPORTANT: free lock
862  }
863 
864  // close all of them now
865  for( CustomWidgets::iterator it = copy.begin(); it != copy.end(); ++it )
866  {
867  wlog::warn( "MainWindow" ) << "Closing custom UI widget \"" << ( *it )->getTitleQString().toStdString() << "\". This should have be"
868  " done by the owning module!";
869  ( *it )->close();
870  }
871  copy.clear();
872 
873  // notify main window -> just call close() again with updated state
875 }
876 
878 {
879  m_closeFirstStage = false;
880  // NOTE: runs in GUI thread
881  close();
882 }
883 
884 void WMainWindow::closeEvent( QCloseEvent* e )
885 {
886  // closing is a two-stage process. When the user requests the close, we tell the kernel to shutdown, while the GUI still is active. In the
887  // second stage, we close the GUI itself (it is freezed). The kernel shutdown needs a running GUI to properly close everything -> thus we
888  // ensure a running GUI in stage 1.
889 
890  // start stage stage 1
891  if( !m_closeInProgress )
892  {
893  m_closeInProgress = true;
894  m_closeFirstStage = true;
895 
896  // IMPORTANT: we tell QT to not close the app
897  e->ignore();
898 
899  // show splash
900  m_splash->show();
901  m_splash->showMessage( "Shutting down" );
902  setDisabled( true ); // avoid user interaction
903 
904  // save state
905  saveWindowState();
906 
907  // tell kernel to shutdown
908  m_splash->showMessage( "Shutting down kernel. Waiting for modules to finish and cleanup." );
909 
910  // start a thread for this
912  m_closeStage1Thread->run( boost::bind( &WMainWindow::closeStage1Thread, this ) );
913  return;
914  }
915 
916  // stage 1 finished, close in progress -> stage 2
918  {
919  // now nobody accesses the osg anymore
920  m_splash->showMessage( "Shutting down GUI." );
921 
922  // clean up gl widgets
923  m_mainGLDock->close();
924  if( m_navAxial )
925  {
926  m_navAxial->close();
927  }
928  if( m_navCoronal )
929  {
930  m_navCoronal->close();
931  }
932  if( m_navSagittal )
933  {
934  m_navSagittal->close();
935  }
936 
937  // finally close
938  e->accept();
939  return;
940  }
941 
942  // all other cases: user pressed "close" somewhere during shutdown
943  e->ignore();
944 }
945 
947 {
948  if( event->type() == WDeferredCallEvent::CUSTOM_TYPE )
949  {
950  static_cast< WDeferredCallEvent* >( event )->call();
951  }
952  else
953  {
954  // other event
955  QMainWindow::customEvent( event );
956  }
957 }
958 
959 void WMainWindow::reportError( QWidget* parent, QString title, QString message )
960 {
961  WQtMessagePopup* m = new WQtMessagePopup( parent, title, message, LL_ERROR );
962  m->show();
963  m_messageDock->addMessage( title, message, LL_ERROR );
964 }
965 
966 void WMainWindow::reportWarning( QWidget* parent, QString title, QString message )
967 {
968  WQtMessagePopup* m = new WQtMessagePopup( parent, title, message, LL_WARNING );
969  m->show();
970  m_messageDock->addMessage( title, message, LL_WARNING );
971 }
972 
973 void WMainWindow::reportInfo( QWidget* parent, QString title, QString message )
974 {
975  WQtMessagePopup* m = new WQtMessagePopup( parent, title, message, LL_INFO );
976  m->show();
977  m_messageDock->addMessage( title, message, LL_INFO );
978 }
979 
981 {
982  // a module got associated with the root container -> add it to the list
983  if( event->type() == WQT_READY_EVENT )
984  {
985  // convert event to ready event
986  WModuleReadyEvent* e1 = dynamic_cast< WModuleReadyEvent* >( event ); // NOLINT
987  if( e1 )
988  {
990  }
991  }
992 
993  // push the log message to the message dock
994  if( event->type() == WQT_LOG_EVENT )
995  {
996  WLogEvent* e1 = dynamic_cast< WLogEvent* >( event ); // NOLINT
997  if( e1 && getMessageDock() )
998  {
999  QString title = "Log message from " + QString::fromStdString( e1->getEntry().getSource() );
1000  QString message = QString::fromStdString( e1->getEntry().getMessage() );
1001  switch( e1->getEntry().getLogLevel() )
1002  {
1003  case LogLevel::LL_WARNING:
1004  reportWarning( this, title, message );
1005  break;
1006  case LogLevel::LL_ERROR:
1007  reportError( this, title, message );
1008  break;
1009  default:
1011  break;
1012  }
1013  }
1014  }
1015 
1016  if( event->type() == WQT_CRASH_EVENT )
1017  {
1018  // convert event to ready event
1019  WModuleCrashEvent* e1 = dynamic_cast< WModuleCrashEvent* >( event ); // NOLINT
1020  if( e1 )
1021  {
1022  QString title = "Module \"" + QString::fromStdString( e1->getModule()->getName() ) + "\" caused a problem.";
1023  QString message = QString::fromStdString( e1->getMessage() );
1024  reportError( this, title, message );
1025  }
1026  }
1027 
1028  if( event->type() == WQT_MODULE_REMOVE_EVENT )
1029  {
1030  // convert event to ready event
1031  WModuleRemovedEvent* e1 = dynamic_cast< WModuleRemovedEvent* >( event ); // NOLINT
1032  if( e1 )
1033  {
1035  }
1036  }
1037 
1038  if( event->type() == WQT_LOADFINISHED )
1039  {
1040  // convert event
1041  WLoadFinishedEvent* e1 = dynamic_cast< WLoadFinishedEvent* >( event );
1042  if( e1 )
1043  {
1044  if( e1->getErrors().size() || e1->getWarnings().size() )
1045  {
1046  size_t curErrCount = 0;
1047  const size_t maxErrCount = 5;
1048  std::string errors = "<ul>";
1049  for( std::vector< std::string >::const_iterator iter = e1->getErrors().begin(); iter != e1->getErrors().end(); ++iter )
1050  {
1051  errors += "<li> " + *iter;
1052  curErrCount++;
1053 
1054  if( ( curErrCount == maxErrCount ) && ( e1->getErrors().size() > maxErrCount ) )
1055  {
1056  size_t errDiff = e1->getErrors().size() - curErrCount;
1057  errors += "<li> ... and " + string_utils::toString( errDiff ) + " more errors.";
1058  break;
1059  }
1060  }
1061  errors += "</ul>";
1062 
1063  size_t curWarnCount = 0;
1064  const size_t maxWarnCount = 5;
1065  std::string warnings = "<ul>";
1066  for( std::vector< std::string >::const_iterator iter = e1->getWarnings().begin(); iter != e1->getWarnings().end(); ++iter )
1067  {
1068  warnings += "<li> " + *iter;
1069  curWarnCount++;
1070 
1071  if( ( curWarnCount == maxWarnCount ) && ( e1->getWarnings().size() > maxWarnCount ) )
1072  {
1073  size_t warnDiff = e1->getWarnings().size() - curWarnCount;
1074  warnings += "<li> ... and " + string_utils::toString( warnDiff ) + " more warnings.";
1075  break;
1076  }
1077  }
1078  warnings += "</ul>";
1079 
1080  if( curWarnCount && curErrCount ) // Errors and warnings
1081  {
1082  reportError( this, "There where errors and warnings during load.",
1083  "Errors occurred during load of \"" + QString::fromStdString( e1->getFilename() ) + "\". "
1084  "The loader tried to apply as much as possible, ignoring the erroneous data. The first errors where:"
1085  + QString::fromStdString( errors ) +
1086  "Warnings occurred during load of \"" + QString::fromStdString( e1->getFilename() ) + "\". "
1087  + QString::fromStdString( warnings )
1088  );
1089  }
1090  else if( curWarnCount && !curErrCount ) // only warnings
1091  {
1092  reportWarning( this, "There where warnings during load.",
1093  "Warnings occurred during load of \"" + QString::fromStdString( e1->getFilename() ) + "\". "
1094  + QString::fromStdString( warnings )
1095  );
1096  }
1097  else if( !curWarnCount && curErrCount ) // only errors
1098  {
1099  reportError( this, "There where errors during load.",
1100  "Errors occurred during load of \"" + QString::fromStdString( e1->getFilename() ) + "\". "
1101  "The loader tried to apply as much as possible, ignoring the erroneous data. The first errors where:"
1102  + QString::fromStdString( errors )
1103  );
1104  }
1105  }
1106  }
1107  }
1108 
1109  return QMainWindow::event( event );
1110 }
1111 
1113 {
1114  // do nothing if we can not get
1115  WPosition crossHairPos = WKernel::getRunningKernel()->getSelectionManager()->getCrosshair()->getPosition();
1116  WPosition minROIPos = crossHairPos - WPosition( 10., 10., 10. );
1117  WPosition maxROIPos = crossHairPos + WPosition( 10., 10., 10. );
1118 
1119  if( m_controlPanel->getFirstRoiInSelectedBranch().get() == NULL )
1120  {
1121  osg::ref_ptr< WROIBox > newRoi = osg::ref_ptr< WROIBox >( new WROIBox( minROIPos, maxROIPos ) );
1123  }
1124  else
1125  {
1126  osg::ref_ptr< WROIBox > newRoi = osg::ref_ptr< WROIBox >( new WROIBox( minROIPos, maxROIPos ) );
1128  }
1129 }
1130 
1132 {
1133  wlog::info( "MainWindow" ) << "Restoring window state.";
1134 
1135  restoreGeometry( WQtGui::getSettings().value( "MainWindowGeometry", "" ).toByteArray() );
1136  restoreState( WQtGui::getSettings().value( "MainWindowState", "" ).toByteArray() );
1137 
1138  m_glDock->restoreGeometry( WQtGui::getSettings().value( "GLDockWindowGeometry", "" ).toByteArray() );
1139  m_glDock->restoreState( WQtGui::getSettings().value( "GLDockWindowState", "" ).toByteArray() );
1140 
1141  if( m_navAxial )
1142  {
1143  m_navAxial->restoreSettings();
1144  }
1145  if( m_navCoronal )
1146  {
1147  m_navCoronal->restoreSettings();
1148  }
1149  if( m_navSagittal )
1150  {
1151  m_navSagittal->restoreSettings();
1152  }
1153 }
1154 
1156 {
1157  wlog::info( "MainWindow" ) << "Saving window state.";
1158 
1159  // this saves the window state to some common location on the target OS in user scope.
1160  WQtGui::getSettings().setValue( "MainWindowState", saveState() );
1161  WQtGui::getSettings().setValue( "GLDockWindowState", m_glDock->saveState() );
1162 
1163  // NOTE: Qt Doc says that saveState also saves geometry. But this somehow is wrong (at least for 4.6.3)
1164  WQtGui::getSettings().setValue( "MainWindowGeometry", saveGeometry() );
1165  WQtGui::getSettings().setValue( "GLDockWindowGeometry", m_glDock->saveGeometry() );
1166 
1168 }
1169 
1171 {
1172  return WQtGui::getSettings();
1173 }
1174 
1175 void WMainWindow::setSetting( std::string key, std::string value )
1176 {
1177  WMainWindow::getSettings().setValue( QString::fromStdString( key ), QString::fromStdString( value ) );
1178 }
1179 
1180 void WMainWindow::handleLogLevelUpdate( unsigned int logLevel )
1181 {
1182  WLogger::getLogger()->setDefaultLogLevel( static_cast< LogLevel >( logLevel ) );
1183 }
1184 
1186 {
1187  // WARNING: never put blocking code here, as it might freeze the mainGLWidget.
1188  std::string vendor = string_utils::toLower( m_mainGLWidget->getViewer()->getOpenGLVendor() );
1189 
1190  // is this a mesa card?
1191  if( vendor.find( "mesa" ) != std::string::npos )
1192  {
1193  QString msg = "<b>Warning:</b> Your graphics card is powered by the Mesa OpenGL implementation. OpenWalnut does not support Mesa "
1194  "officially, since Mesa has some severe problems with GLSL shaders. You can still use OpenWalnut, but you should be "
1195  "aware that Mesa can freeze OpenWalnut. Ensure you have the latest version of Mesa installed to avoid problems.";
1196  QLabel* l = new QLabel( msg );
1197  l->setWordWrap( true );
1198  l->setMinimumWidth( 640 );
1199 
1200  WQtMessageDialog* msgDia = new WQtMessageDialog( "MesaWarning", "Mesa Warning", l, getSettings(), this );
1201  msgDia->show();
1202  }
1203 
1204  // is this a mesa card?
1205  if( ( vendor.find( "Chromium" ) != std::string::npos ) ||
1206  ( vendor.find( "Humper" ) != std::string::npos ) )
1207  {
1208  QString msg = "<b>Warning:</b> You seem to use OpenWalnut from inside a virtual machine. Graphics acceleration on these virtual machines"
1209  " is often limited. OpenWalnut might not properly work in your setup.";
1210  QLabel* l = new QLabel( msg );
1211  l->setWordWrap( true );
1212  l->setMinimumWidth( 640 );
1213 
1214  WQtMessageDialog* msgDia = new WQtMessageDialog( "VMChromiumWarning", "Virtual Machine Warning", l, getSettings(), this );
1215  msgDia->show();
1216  }
1217 }
1218 
1220 {
1221  // Load welcome file
1222  std::string filename( WPathHelper::getDocPath().string() + "/openwalnut-qt/OpenWalnutWelcome.html" );
1223  std::string content = readFileIntoString( filename );
1224 
1225  // gen ID for it using version (allows showing release/welcome message for each new release)
1226  QString msgID = "OpenWalnutWelcome" + QString( W_LIB_VERSION );
1227 
1228  // replace OW_VERSION
1229  boost::regex reg1( "%OW_LIB_VERSION%" );
1230  boost::regex reg2( "%OW_VERSION%" );
1231  content = boost::regex_replace( content, reg1, std::string( W_LIB_VERSION ) );
1232  content = boost::regex_replace( content, reg2, std::string( W_VERSION ) );
1233 
1234  QWidget* w = NULL;
1235 #ifdef OW_FORCE_WEBKIT
1236  QWebView *view = new QWebView( this );
1237 #else
1238  QWebEngineView *view = new QWebEngineView( this );
1239 #endif
1240  view->setHtml( QString::fromStdString( content ) );
1241  view->setMinimumWidth( 640 );
1242 #ifdef OW_FORCE_WEBKIT
1243  view->page()->setLinkDelegationPolicy( QWebPage::DelegateExternalLinks );
1244 #endif
1245  w = view;
1246 
1247  WQtMessageDialog* msgDia = new WQtMessageDialog( msgID, "Welcome to OpenWalnut", w, getSettings(), this );
1248  msgDia->show( force );
1249 }
1250 
1252 {
1253  // only show welcome dialog for now
1254  showWelcomeDialog( false );
1255 }
1256 
1257 void WMainWindow::handleDrop( QDropEvent* event )
1258 {
1259  if( event->mimeData()->hasUrls() )
1260  {
1261  std::vector < std::string > projects;
1262  std::vector < std::string > filenames;
1263  std::vector < std::string > unsupported;
1264  foreach( QUrl url, event->mimeData()->urls() )
1265  {
1266  QString path = url.toLocalFile();
1267  QFileInfo info( path );
1268  QString suffix = info.completeSuffix();
1269  if( suffix == "owp" || suffix == "owproj" )
1270  {
1271  projects.push_back( path.toStdString() );
1272  }
1273  else
1274  {
1275  filenames.push_back( path.toStdString() );
1276  }
1277  }
1278  if( projects.size() > 0 )
1279  {
1280  for( size_t i = 0; i < projects.size(); ++i )
1281  {
1282  asyncProjectLoad( projects[ i ] );
1283  }
1284  event->accept();
1285  }
1286  if( filenames.size() > 0 )
1287  {
1288  m_loaderSignal( filenames );
1289  event->accept();
1290  }
1291  }
1292 }
1293 
1294 void WMainWindow::dropEvent( QDropEvent* event )
1295 {
1296  handleDrop( event );
1297  QMainWindow::dropEvent( event );
1298 }
1299 
1300 bool WMainWindow::isDropAcceptable( const QMimeData* mimeData )
1301 {
1302  return mimeData->hasUrls();
1303 }
1304 
1305 void WMainWindow::dragMoveEvent( QDragMoveEvent* event )
1306 {
1307  if( WMainWindow::isDropAcceptable( event->mimeData() ) )
1308  {
1309  event->acceptProposedAction();
1310  }
1311  QMainWindow::dragMoveEvent( event );
1312 }
1313 
1314 void WMainWindow::dragEnterEvent( QDragEnterEvent* event )
1315 {
1316  if( WMainWindow::isDropAcceptable( event->mimeData() ) )
1317  {
1318  event->acceptProposedAction();
1319  }
1320  QMainWindow::dragEnterEvent( event );
1321 }
1322 
1324 {
1325  m_splash->finish( this );
1326 }
1327 
1328 QSplashScreen* WMainWindow::getSplash() const
1329 {
1330  return m_splash;
1331 }
1332 
1333 void WMainWindow::addGlobalMenu( QWidget* widget )
1334 {
1335  widget->addAction( createSeperator( this ) );
1336  widget->addAction( m_newAction );
1337  widget->addAction( m_loadButton );
1338  widget->addAction( m_saveAction );
1339  widget->addAction( createSeperator( this ) );
1340  widget->addAction( m_settingsAction );
1341  widget->addAction( createSeperator( this ) );
1342  widget->addAction( m_helpAction );
1343  widget->addAction( createSeperator( this ) );
1344  widget->addAction( m_quitAction );
1345 }
1346 
1348 {
1349  return m_messageDock;
1350 }
1351 
1353 {
1354  return m_messageDock;
1355 }
1356 
1358 {
1360 }
1361 
1363 {
1364  // remove
1365  m_customWidgets.remove( widget );
1366 }
1367 
1368 Qt::DockWidgetArea WMainWindow::getDefaultCustomDockArea() const
1369 {
1370  return Qt::BottomDockWidgetArea;
1371 }
1372 
1374 {
1375  return m_glDock;
1376 }
1377 
1378 void WMainWindow::switchVisibility( QWidget* who )
1379 {
1380  who->setVisible( !who->isVisible() );
1381 }
static std::shared_ptr< WDataHandler > getDataHandler()
As WDataHandler is a singleton -> return instance.
std::shared_ptr< const WDataModuleInputFilterFile > ConstSPtr
Convenience typedef for a std::shared_ptr< const WDataModuleInputFilterFile >.
Base for all data loader modules.
Definition: WDataModule.h:47
virtual std::vector< WDataModuleInputFilter::ConstSPtr > getInputFilter() const =0
Return a list of input filters.
static const QEvent::Type CUSTOM_TYPE
Constant which saves the number used to distinguish this event from other custom events.
Derived WDeferredCallEvent allowing result values in calls.
static std::shared_ptr< WGraphicsEngine > getGraphicsEngine()
Returns instance of the graphics engine.
Manages icon access.
Definition: WIconManager.h:41
void addMapping(const std::string &newName, const std::string &mapToThis)
Add a mapping for icons.
QIcon getIcon(const std::string name)
Searches icons in the internal map and all modules for the given icon name.
std::shared_ptr< WSelectionManager > getSelectionManager()
get for selection manager
Definition: WKernel.cpp:214
static WKernel * getRunningKernel()
Returns pointer to the currently running kernel.
Definition: WKernel.cpp:117
std::shared_ptr< WModuleContainer > getRootContainer() const
Returns the root module container.
Definition: WKernel.cpp:127
void finalize()
Stops execution of the modules in the root container.
Definition: WKernel.cpp:137
std::shared_ptr< WScriptEngine > getScriptEngine()
Get the script engine of this kernel.
Definition: WKernel.cpp:219
std::shared_ptr< WROIManager > getRoiManager()
get for roi manager
Definition: WKernel.cpp:209
Event signalling a finished asynchronous load job.
const std::vector< std::string > & getWarnings() const
Returns the list of warnings.
const std::vector< std::string > & getErrors() const
Returns the list of errors.
std::string getFilename() const
The filename of the file loaded.
LogLevel getLogLevel() const
Definition: WLogEntry.cpp:116
std::string getMessage() const
Returns the plain message of the entry.
Definition: WLogEntry.cpp:121
std::string getSource() const
Returns the sender of the log.
Definition: WLogEntry.cpp:126
This event is triggered when a new event is to be added to the log.
Definition: WLogEvent.h:36
const WLogEntry & getEntry() const
To access the WLogEntry of associated with the event.
Definition: WLogEvent.cpp:39
void addLogMessage(std::string message, std::string source="", LogLevel level=LL_DEBUG)
Appends a log message to the logging queue.
Definition: WLogger.cpp:84
void setDefaultLogLevel(const LogLevel &level)
Set the default log-level used for log entries in default console-output.
Definition: WLogger.cpp:106
static WLogger * getLogger()
Returns pointer to the currently running logger instance.
Definition: WLogger.cpp:64
WQtToolBar * m_permanentToolBar
The permanent toolbar of the main window.
Definition: WMainWindow.h:424
void handleDrop(QDropEvent *event)
Handles the given drop.
void showWelcomeDialog(bool force=true)
Shows the welcome message.
WThreadedRunner::SPtr m_closeStage1Thread
The thread responsible for doing stage 1 stuff.
Definition: WMainWindow.h:472
QAction * m_loadButton
the load button
Definition: WMainWindow.h:433
WSettingAction * m_sliderMinMaxEditSetting
The action for allowing editing min and max of sliders.
Definition: WMainWindow.h:518
void deregisterCustomWidget(WUIQtWidgetBase *widget)
De-register a custom widget.
WQtControlPanel * getControlPanel()
Returns a pointer to the control panel object.
void openAboutDialog()
gets called when menu entry "About OpenWalnut" is activated
QAction * m_settingsAction
the settings
Definition: WMainWindow.h:440
std::shared_ptr< WQtNavGLWidget > m_navAxial
the axial view widget GL widget of the GUI
Definition: WMainWindow.h:452
bool projectSaveCameraOnly()
Gets called by the save menu to only save the camera settings.
bool projectSaveAll()
Gets called whenever the user presses the project save button.
std::shared_ptr< WQtNavGLWidget > m_navCoronal
the coronal view widget GL widget of the GUI
Definition: WMainWindow.h:453
void saveWindowState()
Saves the current window states and geometries to a file.
QAction * m_quitAction
quit OpenWalnut
Definition: WMainWindow.h:434
QMenu * m_viewMenu
view and camera control menu
Definition: WMainWindow.h:438
QSplashScreen * getSplash() const
Get the current splash screen.
QMenu * m_settingsMenu
the settings
Definition: WMainWindow.h:441
WQtGLDockWidget * m_mainGLDock
the dock containing the main gl widget
Definition: WMainWindow.h:457
void handleGLVendor()
Handles some special GL vendors and shows the user a dialog.
void openOpenWalnutHelpDialog()
Gets called when menu entry "OpenWalnut Help" is activated.
void closeStage2()
The second stage function.
void moduleSpecificCleanup(std::shared_ptr< WModule > module)
Cleanup the GUI by handling special modules.
void handleLogLevelUpdate(unsigned int logLevel)
Is able to handle updates in the log-level setting.
void setupGUI()
Set up all widgets menus an buttons in the main window.
QSplashScreen * m_splash
The splash screen object opened on startup.
Definition: WMainWindow.h:413
static bool isDropAcceptable(const QMimeData *mimeData)
This method checks whether a given drop event is acceptable.
void moduleSpecificSetup(std::shared_ptr< WModule > module)
Setup the GUI by handling special modules.
void newRoi()
gets called when the button new ROI is pressed
QAction * m_newAction
the new project button
Definition: WMainWindow.h:432
WQtMessageDock * m_messageDock
Message and log window.
Definition: WMainWindow.h:429
void registerCustomWidget(WUIQtWidgetBase *widget)
Register a custom widget.
void openLoadDialog()
gets called when menu option or toolbar button load is activated
WIconManager * getIconManager()
Return icon manager.
void closeStage1Thread()
The actual thread function for m_closeStage1Thread.
WQtControlPanel * m_controlPanel
control panel
Definition: WMainWindow.h:446
QMainWindow * m_glDock
the dock that is used for gl widgets
Definition: WMainWindow.h:455
virtual void customEvent(QEvent *event)
Handle custom events.
QMainWindow * getDefaultCustomDockAreaWidget() const
The Widget to add custom docks.
QMenu * m_saveMenu
the menu using m_saveAction
Definition: WMainWindow.h:436
bool projectSaveROIOnly()
Gets called by the save menu to only save the ROI settings.
void dropEvent(QDropEvent *event)
drag and drop implementation for loading files
void reportWarning(QWidget *parent, QString title, QString message)
Allows comfortable warning reporting using popups.
bool projectSaveModuleOnly()
Gets called by the save menu to only save the Module settings.
QMenu * m_helpMenu
the help menu
Definition: WMainWindow.h:444
WSharedSequenceContainer< CustomWidgets > m_customWidgets
All registered widgets created by the core/UI api.
Definition: WMainWindow.h:492
void dragEnterEvent(QDragEnterEvent *event)
drag and drop implementation for loading files
bool m_closeFirstStage
Used to handle the two-stage close process.
Definition: WMainWindow.h:462
void setCompatiblesToolbar(WQtCombinerToolbar *toolbar=NULL)
This method removes the old compatibles toolbar and sets the specified one.
void addGlobalMenu(QWidget *widget)
Add the default OW menu to the given widget using addAction.
void slotLoadFinished(boost::filesystem::path file, std::vector< std::string > errors, std::vector< std::string > warnings)
Called whenever a async load has finished.
bool m_closeInProgress
Flag whether the system is shutting down now.
Definition: WMainWindow.h:467
void reportInfo(QWidget *parent, QString title, QString message)
Allows comfortable info reporting using popups.
virtual ~WMainWindow()
Destructor.
Qt::DockWidgetArea getDefaultCustomDockArea() const
The default dock area to use for adding custom docks.
void closeSplash()
Finally closes the splash screen.
void asyncProjectLoad(std::string filename)
Loads a given project asynchronously.
void reportError(QWidget *parent, QString title, QString message)
Allows comfortable error reporting using popups.
virtual bool projectSave(const std::vector< std::shared_ptr< WProjectFileIO > > &writer)
Called for each project save request.
static void setSetting(std::string key, std::string value)
Set a setting specified by a key to a given value.
WQtNetworkEditor * m_networkEditor
network editor
Definition: WMainWindow.h:448
boost::signals2::signal< void(std::vector< std::string >) > * getLoaderSignal()
Returns a pointer to a signal object which signals a list of filenames to load.
std::shared_ptr< WQtNavGLWidget > m_navSagittal
the sgittal view widget GL widget of the GUI
Definition: WMainWindow.h:454
WQtGLWidget * m_mainGLWidget
the main GL widget of the GUI
Definition: WMainWindow.h:450
std::vector< WUIQtWidgetBase * > CustomWidgets
Container for core/UI widgetd.
Definition: WMainWindow.h:487
WQtCombinerToolbar * getCompatiblesToolbar()
This method returns the a pointer to the current compatibles toolbar.
void restoreSavedState()
Loads the window states and geometries from a file.
QAction * m_saveAction
the save menu
Definition: WMainWindow.h:435
WQtCombinerToolbar * m_currentCompatiblesToolbar
The currently set compatibles toolbar.
Definition: WMainWindow.h:418
virtual void closeEvent(QCloseEvent *e)
We want to react on close events.
void openNotImplementedDialog()
Gets called when a menu entry that has no functionality yet is activated.
void handleStartMessages()
Shows startup info messages.
const WQtMessageDock * getMessageDock() const
Return the message dock widget.
static QSettings & getSettings()
Returns the settings object.
QAction * m_helpAction
the help menu
Definition: WMainWindow.h:443
boost::signals2::signal< void(std::vector< std::string >) > m_loaderSignal
boost signal for open file dialog
Definition: WMainWindow.h:494
QMenuBar * m_menuBar
The main menu bar of the GUI.
Definition: WMainWindow.h:422
void newProject()
Slot handling the pressed new project button.
void openAboutQtDialog()
Gets called when menu entry "About Qt" is activated.
WIconManager m_iconManager
manager to provide icons in the gui thread
Definition: WMainWindow.h:420
void dragMoveEvent(QDragMoveEvent *event)
drag and drop implementation for loading files
WQtNetworkEditor * getNetworkEditor()
Returns a pointer to the network editor object.
void switchVisibility(QWidget *who)
Change visibility of the given widget.
void autoAdd(std::shared_ptr< WModule > module, std::string proto, bool onlyOnce=false)
Combine a module with a prototype only if the module is available.
virtual bool event(QEvent *event)
Custom event dispatcher.
WMainWindow(QSplashScreen *splash)
Constructor of the main window.
Event signalling a new module has been associated with the root container in the kernel.
std::string getMessage()
The crash message.
std::shared_ptr< WModule > getModule()
Getter for the module that got associated.
static SPtr getModuleFactory()
Returns instance of the module factory to use to create modules.
Event signalling a new module has been associated with the root container in the kernel.
std::shared_ptr< WModule > getModule()
Getter for the module that got associated.
Event signalling a module was removed from the kernel root container.
std::shared_ptr< WModule > getModule()
Getter for the module that got removed.
static boost::filesystem::path getDocPath()
The path where the doc files reside in.
This only is a 3d double vector.
Class loading project files.
Definition: WProjectFile.h:50
static std::shared_ptr< WProjectFileIO > getModuleWriter()
Returns an instance of the module writer.
std::shared_ptr< WProjectFile > SPtr
Abbreviation for a shared pointer.
Definition: WProjectFile.h:55
static std::shared_ptr< WProjectFileIO > getROIWriter()
Returns an instance of the ROI writer.
static std::shared_ptr< WProjectFileIO > getCameraWriter()
Returns an instance of the Camera writer.
This is a toolbar.
container widget for a tree widget with context menu and some control widgets
WQtDockWidget * getModuleDock() const
Gets the module dock widget.
WQtModuleConfig & getModuleConfig() const
Returns the module config dialog.
WQtSubjectTreeItem * addSubject(std::string name)
Adds a subject entry to the tree widget.
void selectUpperMostEntry()
Selects the uppermost entry in the module tree.
QAction * getRoiDeleteAction() const
Return the action to delete a selected roi.
void completeGuiSetup()
Complete own GUI setup.
WQtDockWidget * getColormapperDock() const
Gets the colormapper dock.
QAction * toggleViewAction() const
Returns a checkable action that can be used to show or close this dock widget.
WQtDockWidget * getRoiDock() const
Gets the ROI dock widget.
osg::ref_ptr< WROI > getFirstRoiInSelectedBranch()
Returns the first ROI in the currently selected branch.
virtual void addTitleSeperator()
Add a separator.
virtual void addTitleAction(QAction *action, bool instantPopup=false)
Add the given action to the titlebar.
Dock widget containing only a GLWidget.
WQtGLWidget * getGLWidget() const
Gets the contained GL widget instance.
virtual void restoreSettings()
Restore settings.
std::shared_ptr< WGEViewer > getViewer() const
Get the included viewer.
static QSettings & getSettings()
Returns the settings object.
Definition: WQtGui.cpp:394
static void execInGUIThreadAsync(boost::function< void(void) > functor, WCondition::SPtr notify=WCondition::SPtr())
Call a given function from within the GUI thread.
Definition: WQtGui.cpp:421
General purpose message dialog, able to show arbitrary content.
virtual void show()
Shows the dialog if the user does not disabled it.
Dock widget for showing messages and logs.
void saveSettings()
Save state to settings.
void addMessage(QString title, QString message, WQtMessagePopup::MessageType type)
Add a message to the dock.
void addLogMessage(QString sender, QString message, WQtMessagePopup::MessageType type)
Add a message to the dock.
Nice looking message popup.
void show()
Reimplement show from QWidget to be able to auto-close it.
QAction * getConfigureAction() const
Creates an action instance allowing the configuration.
container widget to hold as GL widget and a slider
Container widget to hold the WQtNetworkScene.
WQtNetworkEditorView * getView()
Get the view handling the scene.
Implements a property action for WPropBool.
QMenu * getStyleMenu(QString title=QString("Toolbar Style")) const
Returns a menu for styling the menu items.
This is a toolbar.
Definition: WQtToolBar.h:39
void addAction(QAction *action)
Allows addition of new actions to the toolbar.
Definition: WQtToolBar.cpp:42
A box representing a region of interest.
Definition: WROIBox.h:49
Class to handle a certain setting with an action.
bool get() const
Gets the current state.
Similar to WSettingAction, this can handle a multi-option setting as QMenu.
Definition: WSettingMenu.h:36
ReadTicket getReadTicket() const
Returns a ticket to get read access to the contained data.
This class provides a common interface for thread-safe access to sequence containers (list,...
void remove(const typename S::value_type &element)
Searches and removes the specified element.
void unique_push_back(const typename S::value_type &x)
Add the element only if it is not inside the container until now.
Base class for all classes needing to be executed in a separate thread.
std::shared_ptr< WThreadedRunner > SPtr
Abbreviation to a shared_ptr to this type.
Implementation of WUIWidgetBase.
std::string toLower(const std::string &source)
Transforms all characters in the given string into lower case characters.
std::string toString(const T &value)
Convert a given value to a string.
Definition: WStringUtils.h:120
WStreamedLogger warn(const std::string &source)
Logging a warning message.
Definition: WLogger.h:309
WStreamedLogger info(const std::string &source)
Logging an information message.
Definition: WLogger.h:320