Salome HOME
Revert "Merge branch 'agr/edf12447-catalyst'"
[modules/paravis.git] / src / PVGUI / PVGUI_Module.cxx
1 // PARAVIS : ParaView wrapper SALOME module
2 //
3 // Copyright (C) 2010-2015  CEA/DEN, EDF R&D
4 //
5 // This library is free software; you can redistribute it and/or
6 // modify it under the terms of the GNU Lesser General Public
7 // License as published by the Free Software Foundation; either
8 // version 2.1 of the License, or (at your option) any later version.
9 //
10 // This library is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13 // Lesser General Public License for more details.
14 //
15 // You should have received a copy of the GNU Lesser General Public
16 // License along with this library; if not, write to the Free Software
17 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
18 //
19 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
20 //
21 // File   : PVGUI_Module.cxx
22
23 #define PARAVIS_MODULE_NAME "PARAVIS"
24
25 #include <Standard_math.hxx>  // E.A. must be included before Python.h to fix compilation on windows
26 #ifdef HAVE_FINITE
27 #undef HAVE_FINITE            // VSR: avoid compilation warning on Linux : "HAVE_FINITE" redefined
28 #endif
29 #include <vtkPython.h> // Python first
30
31 #include "PVGUI_Module.h"
32
33 #include "PVViewer_ViewManager.h"
34 #include "PVViewer_Core.h"
35 #include "PVViewer_ViewWindow.h"
36 #include "PVViewer_ViewModel.h"
37 #include "PVGUI_ParaViewSettingsPane.h"
38 #include "PVViewer_GUIElements.h"
39 #include "PVServer_ServiceWrapper.h"
40 #include "PVGUI_DataModel.h"
41
42 // SALOME Includes
43 #include <utilities.h>
44 #include <SUIT_DataBrowser.h>
45 #include <SUIT_Desktop.h>
46 #include <SUIT_MessageBox.h>
47 #include <SUIT_ResourceMgr.h>
48 #include <SUIT_Session.h>
49 #include <SUIT_OverrideCursor.h>
50 #include <SUIT_ExceptionHandler.h>
51
52 #include <LightApp_SelectionMgr.h>
53 #include <LightApp_NameDlg.h>
54 #include <LightApp_Application.h>
55 #include <LightApp_Study.h>
56 #include <SALOME_ListIO.hxx>
57
58 #include <QtxActionMenuMgr.h>
59 #include <QtxActionToolMgr.h>
60
61 #include <PARAVIS_version.h>
62
63 // External includes
64 #include <sstream>
65
66 #include <QAction>
67 #include <QApplication>
68 #include <QCursor>
69 #include <QDir>
70 #include <QFile>
71 #include <QFileInfo>
72 #include <QIcon>
73 #include <QInputDialog>
74 #include <QMenu>
75 #include <QStatusBar>
76 #include <QString>
77 #include <QStringList>
78 #include <QTimer>
79 #include <QToolBar>
80 #include <QTextStream>
81 #include <QShortcut>
82 #include <QDockWidget>
83 #include <QHelpEngine>
84
85 // Paraview includes
86 #include <vtkPVConfig.h>  // for symbol PARAVIEW_VERSION
87 #include <vtkProcessModule.h>
88 #include <vtkPVSession.h>
89 #include <vtkPVProgressHandler.h>
90 #include <vtkOutputWindow.h>
91 #include <vtkEventQtSlotConnect.h>
92 #include <vtkNew.h>
93 #include <vtkSMProxy.h>
94 #include <vtkSmartPointer.h>
95 #include <vtkSMSession.h>
96 #include <vtkSMTrace.h>
97 #include <vtkSMSessionProxyManager.h>
98 #include <vtkSMParaViewPipelineController.h>
99 #include <vtkSmartPyObject.h>
100
101 #include <pqApplicationCore.h>
102 #include <pqPVApplicationCore.h>
103 #include <pqObjectBuilder.h>
104 #include <pqOptions.h>
105 #include <pqSettings.h>
106 #include <pqServer.h>
107 #include <pqUndoStack.h>
108 #include <pqTabbedMultiViewWidget.h>
109 #include <pqActiveObjects.h>
110 #include <pqHelpReaction.h>
111 #include <pqPluginManager.h>
112 #include <pqPythonDialog.h>
113 #include <pqPythonManager.h>
114 #include <pqLoadDataReaction.h>
115 #include <pqPythonScriptEditor.h>
116 #include <pqDataRepresentation.h>
117 #include <pqDisplayColorWidget.h>
118 #include <pqColorToolbar.h>
119 #include <pqScalarBarVisibilityReaction.h>
120 #include <pqServerResource.h>
121 #include <pqServerConnectReaction.h>
122 #include <pqPluginManager.h>
123 #include <pqVCRToolbar.h>
124 #include <pqAnimationScene.h>
125 #include <pqServerManagerModel.h>
126 #include <pqAnimationTimeToolbar.h>
127
128 //----------------------------------------------------------------------------
129 PVGUI_Module* ParavisModule = 0;
130
131 /*!
132   \mainpage
133   This is the doxygen documentation of the ParaVis module.
134   If you are looking for general information about the structure of the module, you should
135   take a look at the <a href="../index.html">Sphinx documentation</a> first.
136
137   The integration of ParaView into SALOME is split in two parts:
138   \li the PVViewer in the GUI module (folder *src/PVViewer*)
139   \li the ParaVis module itself (the pages you are currently browsing)
140 */
141
142 /*!
143   \class PVGUI_Module
144   \brief Implementation 
145          SALOME module wrapping ParaView GUI.
146 */
147
148 /*!
149   \brief Clean up function
150
151   Used to stop ParaView progress events when
152   exception is caught by global exception handler.
153 */
154 void paravisCleanUp()
155 {
156   if ( pqApplicationCore::instance() ) {
157     pqServer* s = pqApplicationCore::instance()->getActiveServer();
158     if ( s ) s->session()->GetProgressHandler()->CleanupPendingProgress();
159   }
160 }
161
162 /*!
163   \brief Constructor. Sets the default name for the module.
164 */
165 PVGUI_Module::PVGUI_Module()
166   : LightApp_Module( PARAVIS_MODULE_NAME ),
167     mySourcesMenuId( -1 ),
168     myFiltersMenuId( -1 ),
169     myMacrosMenuId(-1),
170     myRecentMenuId(-1),
171     myOldMsgHandler(0),
172     myTraceWindow(0),
173     myInitTimer(0),
174     myGuiElements(0)
175 {
176 #ifdef HAS_PV_DOC
177   Q_INIT_RESOURCE( PVGUI );
178 #endif
179   ParavisModule = this;
180
181   // Clear old copies of embedded macros files
182   QString aDestPath = QString( "%1/.config/%2/Macros" ).arg( QDir::homePath() ).arg( QApplication::applicationName() );
183   QStringList aFilter;
184   aFilter << "*.py";
185
186   QDir aDestDir(aDestPath);
187   QStringList aDestFiles = aDestDir.entryList(aFilter, QDir::Files);
188   foreach (QString aMacrosPath, getEmbeddedMacrosList()) {
189     QString aMacrosName = QFileInfo(aMacrosPath).fileName();
190     if (aDestFiles.contains(aMacrosName)) {
191       aDestDir.remove(aMacrosName);
192     }
193   }
194 }
195
196 /*!
197   \brief Destructor.
198 */
199 PVGUI_Module::~PVGUI_Module()
200 {
201   if (myInitTimer)
202     delete myInitTimer;
203 }
204
205 /*!
206   \brief Retrieve the PVSERVER CORBA engine.
207   This uses the Python wrapper provided
208   by the PVViewer code in GUI (class PVViewer_EngineWrapper).
209   \sa GetCPPEngine()
210 */
211 PVServer_ServiceWrapper* PVGUI_Module::GetEngine()
212 {
213   return PVServer_ServiceWrapper::GetInstance();
214 }
215
216 /*!
217   \brief Create data model.
218   \return module specific data model
219 */
220 CAM_DataModel* PVGUI_Module::createDataModel()
221 {
222   return new PVGUI_DataModel( this );
223 }
224
225 /*!
226   \brief Get the ParaView application singleton.
227 */
228 pqPVApplicationCore* PVGUI_Module::GetPVApplication()
229 {
230   return PVViewer_Core::GetPVApplication();
231 }
232
233 /*!
234   \brief Initialize module. Creates menus, prepares context menu, etc.
235   \param app SALOME GUI application instance
236 */
237 void PVGUI_Module::initialize( CAM_Application* app )
238 {
239   LightApp_Module::initialize( app );
240
241   // Uncomment to debug ParaView initialization
242   // "aa" used instead of "i" as GDB doesn't like "i" variables :)
243   /*
244   int aa = 1;
245   while( aa ){
246     aa = aa;
247   }
248   */
249
250   LightApp_Application* anApp = getApp();
251   SUIT_Desktop* aDesktop = anApp->desktop();
252
253   // Remember current state of desktop toolbars
254   QList<QToolBar*> foreignToolbars = aDesktop->findChildren<QToolBar*>();
255
256   // Initialize ParaView client and associated behaviors
257   // and connect to externally launched pvserver
258   PVViewer_Core::ParaviewInitApp(aDesktop, anApp->logWindow());
259   myGuiElements = PVViewer_GUIElements::GetInstance(aDesktop);
260
261   // [ABN]: careful with the order of the GUI element creation, the loading of the configuration
262   // and the connection to the server. This order is very sensitive if one wants to make
263   // sure all menus, etc ... are correctly populated.
264   // Reference points are: ParaViewMainWindow.cxx and branded_paraview_initializer.cxx.in
265   setupDockWidgets();
266
267   pvCreateActions();
268   pvCreateMenus();
269   pvCreateToolBars();
270
271   PVViewer_Core::ParaviewInitBehaviors(true, aDesktop);
272
273   QList<QDockWidget*> activeDocks = aDesktop->findChildren<QDockWidget*>();
274   QList<QMenu*> activeMenus = aDesktop->findChildren<QMenu*>();
275
276   // Setup quick-launch shortcuts.
277   QShortcut *ctrlSpace = new QShortcut(Qt::CTRL + Qt::Key_Space, aDesktop);
278   QObject::connect(ctrlSpace, SIGNAL(activated()),
279     pqApplicationCore::instance(), SLOT(quickLaunch()));
280
281   // Find Plugin Dock Widgets
282   QList<QDockWidget*> currentDocks = aDesktop->findChildren<QDockWidget*>();
283   QList<QDockWidget*>::iterator i;
284   for (i = currentDocks.begin(); i != currentDocks.end(); ++i) {
285     if(!activeDocks.contains(*i)) {
286       myDockWidgets[*i] = false; // hidden by default
287       (*i)->hide();
288     }
289   }
290
291     // Find Plugin Menus
292     // [ABN] TODO: fix this - triggers a SEGFAULT at deactivation() time.
293 //    QList<QMenu*> currentMenus = aDesktop->findChildren<QMenu*>();
294 //    QList<QMenu*>::iterator im;
295 //    for (im = currentMenus.begin(); im != currentMenus.end(); ++im) {
296 //      if(!activeMenus.contains(*im)) {
297 //          QString s = (*im)->title();
298 //          std::cout << " MENU "<<  s.toStdString() << std::endl;
299 //          myMenus.append(*im);
300 //      }
301 //    }
302
303   // Connect after toolbar creation, etc ... as some activations of the toolbars is triggered
304   // by the ServerConnection event:
305   const QString configPath(PVViewer_ViewManager::GetPVConfigPath());
306   PVViewer_Core::ParaviewLoadConfigurations(configPath, true);
307   PVViewer_ViewManager::ConnectToExternalPVServer(aDesktop);
308   updateObjBrowser();
309
310   // Find created toolbars
311   QCoreApplication::processEvents();
312
313   // process PVViewer toolbars (might be added by PVViewer created BEFORE activating ParaVis)
314   QList<QToolBar*> pvToolbars = myGuiElements->getToolbars();
315   foreach(QToolBar* aBar, pvToolbars) {
316     if (!myToolbars.contains(aBar)) {
317       myToolbars[aBar] = true;
318       myToolbarBreaks[aBar] = false;
319       aBar->setVisible(false);
320       aBar->toggleViewAction()->setVisible(false);
321     }
322   }
323
324   // process other toolbars (possibly added by Paraview)
325   QList<QToolBar*> allToolbars = aDesktop->findChildren<QToolBar*>();
326   foreach(QToolBar* aBar, allToolbars) {
327     if (!foreignToolbars.contains(aBar) && !myToolbars.contains(aBar)) {
328       myToolbars[aBar] = true;
329       myToolbarBreaks[aBar] = false;
330       aBar->setVisible(false);
331       aBar->toggleViewAction()->setVisible(false);
332     }
333   }
334
335   updateMacros();
336  
337   SUIT_ResourceMgr* aResourceMgr = SUIT_Session::session()->resourceMgr();
338   bool isStop = aResourceMgr->booleanValue( PARAVIS_MODULE_NAME, "stop_trace", false );
339   if(!isStop)
340     {
341       // Start a timer to schedule asap:
342       //  - the trace start
343       myInitTimer = new QTimer(aDesktop);
344       QObject::connect(myInitTimer, SIGNAL(timeout()), this, SLOT(onInitTimer()) );
345       myInitTimer->setSingleShot(true);
346       myInitTimer->start(0);
347     }
348
349   this->VTKConnect = vtkEventQtSlotConnect::New();
350   
351   vtkProcessModule* pm = vtkProcessModule::GetProcessModule();
352   if(pm) {
353     vtkPVSession* pvs = dynamic_cast<vtkPVSession*>(pm->GetSession());
354     if(pvs) {
355       vtkPVProgressHandler* ph = pvs->GetProgressHandler();
356       if(ph) {
357           this->VTKConnect->Connect(ph, vtkCommand::StartEvent,
358                                     this, SLOT(onStartProgress()));
359           this->VTKConnect->Connect(ph, vtkCommand::EndEvent,
360                                     this, SLOT(onEndProgress()));
361       }
362     }
363   }
364   connect( application(), SIGNAL( appClosed() ), this, SLOT( onStopTrace() ) );
365 }
366
367 /*!
368  * \brief Slot called when the progress bar starts.
369  */
370 void PVGUI_Module::onStartProgress()
371 {
372   // VSR 19/03/2015, issue 0023025
373   // next line is commented: it is bad idea to show wait cursor on ANY vtk event
374   // moreover, it does not work when running pvserver with --multi-client mode
375   //QApplication::setOverrideCursor(Qt::WaitCursor);
376 }
377
378 /*!
379  * \brief Slot called when the progress bar is done.
380  */
381 void PVGUI_Module::onEndProgress()
382 {
383   // VSR 19/03/2015, issue 0023025
384   // next line is commented: it is bad idea to show wait cursor on ANY vtk event
385   // moreover, it does not work when running pvserver with --multi-client mode
386   //QApplication::restoreOverrideCursor();
387 }
388
389 void PVGUI_Module::onDataRepresentationUpdated() {
390   LightApp_Study* activeStudy = dynamic_cast<LightApp_Study*>(application()->activeStudy());
391   if(!activeStudy) return;
392   
393   activeStudy->Modified();
394 }
395
396 /*!
397   \brief Initialisation timer event - Starts up the Python trace
398 */
399 void PVGUI_Module::onInitTimer()
400 {
401   startTrace();
402 }
403   
404 /*!
405   \brief Get list of embedded macros files
406 */
407 QStringList PVGUI_Module::getEmbeddedMacrosList()
408 {
409   QString aRootDir = getenv("PARAVIS_ROOT_DIR");
410
411   QString aSourcePath = aRootDir + "/bin/salome/Macro";
412
413   QStringList aFilter;
414   aFilter << "*.py";
415
416   QDir aSourceDir(aSourcePath);
417   QStringList aSourceFiles = aSourceDir.entryList(aFilter, QDir::Files);
418   QStringList aFullPathSourceFiles;
419   foreach (QString aMacrosName, aSourceFiles) {
420     aFullPathSourceFiles << aSourceDir.absoluteFilePath(aMacrosName);
421   }
422   return aFullPathSourceFiles;
423 }
424
425 /*!
426   \brief Update the list of embedded macros
427 */
428 void PVGUI_Module::updateMacros()
429 {
430   pqPythonManager* aPythonManager = pqPVApplicationCore::instance()->pythonManager();
431   if(!aPythonManager)  {
432     return;
433   }
434   
435   foreach (QString aStr, getEmbeddedMacrosList()) {
436     aPythonManager->addMacro(aStr);
437   }
438 }
439
440
441 /*!
442   \brief Get list of compliant dockable GUI elements
443   \param m map to be filled in ("type":"default_position")
444 */
445 void PVGUI_Module::windows( QMap<int, int>& m ) const
446 {
447   m.insert( LightApp_Application::WT_ObjectBrowser, Qt::LeftDockWidgetArea );
448 #ifndef DISABLE_PYCONSOLE
449   m.insert( LightApp_Application::WT_PyConsole, Qt::BottomDockWidgetArea );
450 #endif
451   // ParaView diagnostic output redirected here
452   m.insert( LightApp_Application::WT_LogWindow, Qt::BottomDockWidgetArea );
453 }
454
455 /*!
456   \brief Shows (toShow = true) or hides ParaView view window
457 */
458 void PVGUI_Module::showView( bool toShow )
459 {
460   // VSR: TODO: all below is not needed, if we use standard approach
461   // that consists in implementing viewManagers() function properly
462   // This should be done after we decide what to do with Log window.
463   LightApp_Application* anApp = getApp();
464   PVViewer_ViewManager* viewMgr =
465     dynamic_cast<PVViewer_ViewManager*>( anApp->getViewManager( PVViewer_Viewer::Type(), false ) );
466   if ( !viewMgr ) {
467     viewMgr = new PVViewer_ViewManager( anApp->activeStudy(), anApp->desktop(), anApp->logWindow() );
468     anApp->addViewManager( viewMgr );
469     connect( viewMgr, SIGNAL( lastViewClosed( SUIT_ViewManager* ) ),
470              anApp, SLOT( onCloseView( SUIT_ViewManager* ) ) );
471   }
472
473   PVViewer_ViewWindow* pvWnd = dynamic_cast<PVViewer_ViewWindow*>( viewMgr->getActiveView() );
474   if ( !pvWnd ) {
475     pvWnd = dynamic_cast<PVViewer_ViewWindow*>( viewMgr->createViewWindow() );
476     // this also connects to the pvserver and instantiates relevant PV behaviors
477   }
478
479   pvWnd->setVisible( toShow );
480   if ( toShow ) pvWnd->setFocus();
481 }
482
483 /*!
484   \brief Slot to show help for proxy.
485 */
486 void PVGUI_Module::showHelpForProxy( const QString& groupname, const QString& proxyname )
487 {
488   pqHelpReaction::showProxyHelp(groupname, proxyname);
489 }
490
491 /*!
492   \brief Slot to show the waiting state.
493 */
494 void PVGUI_Module::onPreAccept()
495 {
496   getApp()->desktop()->statusBar()->showMessage(tr("STB_PREACCEPT"));
497   QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
498 }
499
500 /*!
501   \brief Slot to show the ready state.
502 */
503 void PVGUI_Module::onPostAccept()
504 {
505   getApp()->desktop()->statusBar()->showMessage(tr("STB_POSTACCEPT"), 2000);
506   QTimer::singleShot(0, this, SLOT(endWaitCursor()));
507 }
508
509 /*!
510   \brief Slot to switch off wait cursor.
511 */
512 void PVGUI_Module::endWaitCursor()
513 {
514   QApplication::restoreOverrideCursor();
515 }
516 #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
517 /*!
518   \brief Handler method for the output of messages.
519 */
520 static void ParavisMessageOutput(QtMsgType type, const char *msg)
521 {
522   switch(type)
523     {
524   case QtDebugMsg:
525     vtkOutputWindow::GetInstance()->DisplayText(msg);
526     break;
527   case QtWarningMsg:
528     vtkOutputWindow::GetInstance()->DisplayErrorText(msg);
529     break;
530   case QtCriticalMsg:
531     vtkOutputWindow::GetInstance()->DisplayErrorText(msg);
532     break;
533   case QtFatalMsg:
534     vtkOutputWindow::GetInstance()->DisplayErrorText(msg);
535     break;
536     }
537 }
538 #else
539 /*!
540   \brief Handler method for the output of messages.
541 */
542 static void ParavisMessageOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg)
543 {
544   switch(type)
545     {
546   case QtDebugMsg:
547     vtkOutputWindow::GetInstance()->DisplayText(msg.toLatin1().constData());
548     break;
549   case QtWarningMsg:
550     vtkOutputWindow::GetInstance()->DisplayErrorText(msg.toLatin1().constData());
551     break;
552   case QtCriticalMsg:
553     vtkOutputWindow::GetInstance()->DisplayErrorText(msg.toLatin1().constData());
554     break;
555   case QtFatalMsg:
556     vtkOutputWindow::GetInstance()->DisplayErrorText(msg.toLatin1().constData());
557     break;
558     }
559 }
560 #endif
561 /*!
562   \brief Activate module.
563   \param study current study
564   \return \c true if activaion is done successfully or 0 to prevent
565   activation on error
566 */
567 bool PVGUI_Module::activateModule( SUIT_Study* study )
568 {
569 #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
570   myOldMsgHandler = qInstallMsgHandler(ParavisMessageOutput);
571 #else
572   myOldMsgHandler = qInstallMessageHandler(ParavisMessageOutput);
573 #endif  
574   SUIT_ExceptionHandler::addCleanUpRoutine( paravisCleanUp );
575
576   storeCommonWindowsState();
577
578   bool isDone = LightApp_Module::activateModule( study );
579   if ( !isDone ) return false;
580
581   showView( true );
582   if ( mySourcesMenuId != -1 ) menuMgr()->show(mySourcesMenuId);
583   if ( myFiltersMenuId != -1 ) menuMgr()->show(myFiltersMenuId);
584   if ( myMacrosMenuId != -1 ) menuMgr()->show(myMacrosMenuId);
585
586   // Update the various menus with the content pre-loaded in myGuiElements
587 //  QMenu* srcMenu = menuMgr()->findMenu( mySourcesMenuId );
588 //  myGuiElements->updateSourcesMenu(srcMenu);
589 //  QMenu* filtMenu = menuMgr()->findMenu( myFiltersMenuId );
590 //  myGuiElements->updateFiltersMenu(filtMenu);
591 //  QMenu* macMenu = menuMgr()->findMenu( myMacrosMenuId );
592 //  myGuiElements->updateMacrosMenu(macMenu);
593
594   setMenuShown( true );
595   setToolShown( true );
596
597   restoreDockWidgetsState();
598
599   QMenu* aMenu = menuMgr()->findMenu( myRecentMenuId );
600   if(aMenu) {
601     QList<QAction*> anActns = aMenu->actions();
602     for (int i = 0; i < anActns.size(); ++i) {
603       QAction* a = anActns.at(i);
604       if(a)
605         a->setVisible(true);
606     }
607   }
608
609   QList<QMenu*>::iterator it;
610   for (it = myMenus.begin(); it != myMenus.end(); ++it) {
611     QAction* a = (*it)->menuAction();
612     if(a)
613       a->setVisible(true);
614   }
615
616   if ( myRecentMenuId != -1 ) menuMgr()->show(myRecentMenuId);
617   
618   return isDone;
619 }
620
621
622 /*!
623   \brief Deactivate module.
624   \param study current study
625   \return \c true if deactivaion is done successfully or 0 to prevent
626   deactivation on error
627 */
628 bool PVGUI_Module::deactivateModule( SUIT_Study* study )
629 {
630   MESSAGE("PARAVIS deactivation ...")
631
632   QMenu* aMenu = menuMgr()->findMenu( myRecentMenuId );
633   if(aMenu) {
634     QList<QAction*> anActns = aMenu->actions();
635     for (int i = 0; i < anActns.size(); ++i) {
636       QAction* a = anActns.at(i);
637       if(a)
638         a->setVisible(false);
639     }
640   }
641
642   QList<QMenu*>::iterator it;
643   for (it = myMenus.begin(); it != myMenus.end(); ++it) {
644     QAction* a = (*it)->menuAction();
645     if(a)
646       a->setVisible(false);
647   }
648
649   QList<QDockWidget*> aStreamingViews = application()->desktop()->findChildren<QDockWidget*>("pqStreamingControls");
650   foreach(QDockWidget* aView, aStreamingViews) {
651     if (!myDockWidgets.contains(aView))
652       myDockWidgets[aView] = aView->isVisible();
653   }
654
655   /*if (pqImplementation::helpWindow) {
656     pqImplementation::helpWindow->hide();
657     }*/
658   // hide menus
659   menuMgr()->hide(myRecentMenuId);
660   menuMgr()->hide(mySourcesMenuId);
661   menuMgr()->hide(myFiltersMenuId);
662   menuMgr()->hide(myMacrosMenuId);
663   setMenuShown( false );
664   setToolShown( false );
665
666   saveDockWidgetsState();
667
668   SUIT_ExceptionHandler::removeCleanUpRoutine( paravisCleanUp );
669
670   if (myOldMsgHandler)
671 #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
672     qInstallMsgHandler(myOldMsgHandler);
673 #else
674     qInstallMessageHandler(myOldMsgHandler);
675 #endif
676   restoreCommonWindowsState();
677   
678   return LightApp_Module::deactivateModule( study );
679 }
680
681
682 /*!
683   \brief Called when application is closed.
684
685   Process finalize application functionality from ParaView in order to save server settings
686   and nullify application pointer if the application is being closed.
687
688   \param theApp application
689 */
690 void PVGUI_Module::onApplicationClosed( SUIT_Application* theApp )
691 {
692   PVViewer_Core::ParaviewCleanup();
693   CAM_Module::onApplicationClosed(theApp);
694 }
695
696 /*!
697   \brief Called when study is closed.
698
699   Removes data model from the \a study.
700
701   \param study study being closed
702 */
703 void PVGUI_Module::studyClosed(SUIT_Study* study)
704 {
705   showView(false); // VSR: this seems to be not needed (all views are automatically closed)
706   clearParaviewState();
707   //Re-start trace 
708   onRestartTrace();
709
710   LightApp_Module::studyClosed(study);
711 }
712
713 /*!
714   \brief Open file of format supported by ParaView
715 */
716 void PVGUI_Module::openFile( const char* theName )
717 {
718   QStringList aFiles;
719   aFiles << theName;
720   pqLoadDataReaction::loadData( aFiles );
721 }
722
723 /*!
724   \brief Starts Python trace.
725  
726   Start trace invoking the newly introduced C++ API (PV 4.2)
727   (inspired from pqTraceReaction::start())
728 */
729 void PVGUI_Module::startTrace()
730 {
731   vtkSMSessionProxyManager* pxm = pqActiveObjects::instance().activeServer()->proxyManager();
732
733   vtkSmartPointer<vtkSMProxy> proxy;
734   proxy.TakeReference( pxm->NewProxy( "pythontracing", "PythonTraceOptions" ) );
735   if ( proxy ) {
736     vtkNew<vtkSMParaViewPipelineController> controller;
737     controller->InitializeProxy( proxy );
738   }
739   vtkSMTrace* trace = vtkSMTrace::StartTrace();
740   if ( proxy ) {
741     // Set manually the properties entered via the dialog box poping-up when requiring
742     // a trace start in PV4.2 (trace options)
743     SUIT_ResourceMgr* aResourceMgr = SUIT_Session::session()->resourceMgr();
744     int type = aResourceMgr->integerValue( PARAVIS_MODULE_NAME, "tracestate_type", 2 );
745     trace->SetPropertiesToTraceOnCreate( type );
746     trace->SetFullyTraceSupplementalProxies( false );
747   }
748 }
749
750 /*!
751   \brief Stops Python trace.
752 */
753 void PVGUI_Module::stopTrace()
754 {
755   vtkSMTrace::StopTrace();
756 }
757
758 /*!
759   \brief Execute a Python script.
760 */
761 void PVGUI_Module::executeScript( const char* script )
762 {
763 #ifndef WNT
764   pqPythonManager* manager = qobject_cast<pqPythonManager*>(
765                              pqApplicationCore::instance()->manager( "PYTHON_MANAGER" ) );
766   if ( manager )  {
767     pqPythonDialog* pyDiag = manager->pythonShellDialog();
768     if ( pyDiag ) {
769       pyDiag->runString(script);  
770     }
771   }
772 #endif
773 }
774
775 ///**
776 // *  Debug function printing out the given interpreter's execution context
777 // */
778 //void printInterpContext(PyInterp_Interp * interp )
779 //{
780 //  // Extract __smtraceString from interpreter's context
781 //  const PyObject* ctxt = interp->getExecutionContext();
782 //
783 //  PyObject* lst = PyDict_Keys((PyObject *)ctxt);
784 //  Py_ssize_t siz = PyList_GET_SIZE(lst);
785 //  for (Py_ssize_t i = 0; i < siz; i++)
786 //    {
787 //      PyObject * elem = PyList_GetItem(lst, i);
788 //      if (PyString_Check(elem))
789 //        {
790 //          std::cout << "At pos:" << i << ", " << PyString_AsString(elem) << std::endl;
791 //        }
792 //      else
793 //        std::cout << "At pos:" << i << ", not a string!" << std::endl;
794 //    }
795 //  Py_XDECREF(lst);
796 //}
797
798 /*!
799   \brief Returns trace string
800 */
801 QString PVGUI_Module::getTraceString()
802 {
803   QString traceString = "";
804
805   static const QString replaceStr( "paraview.simple" );
806   std::stringstream nl;
807   nl << std::endl; // surely there is some Qt trick to do that in a portable way??
808   QString end_line( nl.str().c_str() );
809
810   vtkSMTrace* tracer = vtkSMTrace::GetActiveTracer();
811   if ( tracer ) {
812     traceString = tracer->GetCurrentTrace();
813     // 'import pvsimple' is necessary to fix the first call to DisableFirstRenderCamera in the paraview trace
814     // 'ShowParaviewView()' ensure there is an opened viewing window (otherwise SEGFAULT!)
815     traceString = "import pvsimple" + end_line +
816       "pvsimple.ShowParaviewView()" + end_line + traceString;
817
818     // Replace import "paraview.simple" by "pvsimple"
819     if ( !traceString.isEmpty() ) {
820       int aPos = traceString.indexOf( replaceStr );
821       while ( aPos != -1 ) {
822         traceString = traceString.replace( aPos, replaceStr.length(), "pvsimple" );
823         aPos = traceString.indexOf( replaceStr, aPos );
824       }
825     }
826   }
827
828   // Save camera position to, which is no longer output by the tracer ...
829   {
830     vtkPythonScopeGilEnsurer psge;
831     PyObject * mods(PySys_GetObject(const_cast<char*>("modules")));
832     PyObject * trace_mod(PyDict_GetItemString(mods, "paraview.smtrace"));  // module was already (really) imported by vtkSMTrace
833     if (PyModule_Check(trace_mod)) {
834         vtkSmartPyObject save_cam(PyObject_GetAttrString(trace_mod, const_cast<char*>("SaveCameras")));
835         vtkSmartPyObject camera_trace(PyObject_CallMethod(save_cam, const_cast<char*>("get_trace"), NULL));
836         // Convert to a single string
837         vtkSmartPyObject ret(PyString_FromString(end_line.toStdString().c_str()));
838         vtkSmartPyObject final_string(PyObject_CallMethod(ret, const_cast<char*>("join"),
839             const_cast<char*>("O"), (PyObject*)camera_trace));
840         if (PyString_CheckExact(final_string))
841           {
842             QString camera_qs(PyString_AsString(final_string));  // deep copy
843             traceString = traceString + end_line  + end_line + QString("#### saving camera placements for all active views")
844                 + end_line + end_line + camera_qs + end_line;
845           }
846       }
847   } 
848
849   return traceString;
850 }
851
852 /*!
853   \brief Saves trace string to disk file
854 */
855 void PVGUI_Module::saveTrace( const char* theName )
856 {
857   QFile file( theName );
858   if ( !file.open( QIODevice::WriteOnly | QIODevice::Text ) ) {
859     MESSAGE( "Could not open file:" << theName );
860     return;
861   }
862   QTextStream out( &file );
863   out << getTraceString();
864   file.close();
865 }
866
867 /*!
868   \brief Saves ParaView state to a disk file
869 */
870 void PVGUI_Module::saveParaviewState( const QString& theFileName )
871 {
872   pqApplicationCore::instance()->saveState( theFileName.toStdString().c_str() );
873 }
874
875 /*!
876   \brief Delete all objects for Paraview Pipeline Browser
877 */
878 void PVGUI_Module::clearParaviewState()
879 {
880   QAction* deleteAllAction = action( DeleteAllId );
881   if ( deleteAllAction ) {
882     deleteAllAction->activate( QAction::Trigger );
883   }
884 }
885
886 /*!
887   \brief Restores ParaView state from a disk file
888 */
889 void PVGUI_Module::loadParaviewState( const QString& theFileName )
890 {
891   pqApplicationCore::instance()->loadState( theFileName.toStdString().c_str(), getActiveServer() );
892 }
893
894 /*!
895   \brief Returns current active ParaView server
896 */
897 pqServer* PVGUI_Module::getActiveServer()
898 {
899   return pqApplicationCore::instance()->getActiveServer();
900 }
901
902
903 /*!
904   \brief Creates PARAVIS preferences panel.
905 */
906 void PVGUI_Module::createPreferences()
907 {
908   QList<QVariant> aIndices;
909   QStringList aStrings;
910
911   // Paraview settings tab
912   int aParaViewSettingsTab = addPreference( tr( "TIT_PVIEWSETTINGS" ) );
913
914   setPreferenceProperty(aParaViewSettingsTab, "stretch", false );
915   int aPanel = addPreference( QString(), aParaViewSettingsTab,
916                               LightApp_Preferences::UserDefined, PARAVIS_MODULE_NAME, "" );
917
918   setPreferenceProperty( aPanel, "content", (qint64)( new PVGUI_ParaViewSettingsPane( 0, getApp() ) ) );
919
920   // Paravis settings tab
921   int aParaVisSettingsTab = addPreference( tr( "TIT_PVISSETTINGS" ) );
922
923   addPreference( tr( "PREF_NO_EXT_PVSERVER" ), aParaVisSettingsTab, 
924                  LightApp_Preferences::Bool, PARAVIS_MODULE_NAME, "no_ext_pv_server" );
925
926   int aSaveType = addPreference( tr( "PREF_SAVE_TYPE_LBL" ), aParaVisSettingsTab,
927                                  LightApp_Preferences::Selector,
928                                  PARAVIS_MODULE_NAME, "savestate_type" );
929
930   aStrings.clear();
931   aIndices.clear();
932   aIndices << 0 << 1 << 2;
933   aStrings << tr("PREF_SAVE_TYPE_0") << tr("PREF_SAVE_TYPE_1") << tr("PREF_SAVE_TYPE_2");
934   setPreferenceProperty( aSaveType, "strings", aStrings );
935   setPreferenceProperty( aSaveType, "indexes", aIndices );
936
937   // ... "Language" group <<start>>
938   int traceGroup = addPreference( tr( "PREF_GROUP_TRACE" ), aParaVisSettingsTab );
939
940   int stopTrace = addPreference( tr( "PREF_STOP_TRACE" ), traceGroup, 
941                                  LightApp_Preferences::Bool, PARAVIS_MODULE_NAME, "stop_trace" );
942   setPreferenceProperty( stopTrace, "restart",  true );
943
944   int aTraceType = addPreference( tr( "PREF_TRACE_TYPE_LBL" ), traceGroup,
945                                  LightApp_Preferences::Selector,
946                                  PARAVIS_MODULE_NAME, "tracestate_type" );
947   aStrings.clear();
948   aIndices.clear();
949   aIndices << 0 << 1 << 2;
950   aStrings << tr("PREF_TRACE_TYPE_0") << tr("PREF_TRACE_TYPE_1") << tr("PREF_TRACE_TYPE_2");
951   setPreferenceProperty( aTraceType, "strings", aStrings );
952   setPreferenceProperty( aTraceType, "indexes", aIndices );
953   setPreferenceProperty( aTraceType, "restart",  true );
954 }
955
956 /*!
957   \brief. Show ParaView python trace.
958 */
959 void PVGUI_Module::onShowTrace()
960 {
961   if (!myTraceWindow) {
962     myTraceWindow = new pqPythonScriptEditor(getApp()->desktop());
963   }
964   myTraceWindow->setText(getTraceString());
965   myTraceWindow->show();
966   myTraceWindow->raise();
967   myTraceWindow->activateWindow();
968 }
969
970
971 /*!
972   \brief. Re-initialize ParaView python trace.
973 */
974 void PVGUI_Module::onRestartTrace()
975 {
976   stopTrace();
977   startTrace();
978 }
979
980 /*!
981   \brief. Close ParaView python trace.
982 */
983 void PVGUI_Module::onStopTrace()
984 {
985   stopTrace();
986 }
987 /*!
988   \brief Called when view manager is added
989 */
990 void PVGUI_Module::onViewManagerAdded( SUIT_ViewManager* vm )
991 {
992   if ( PVViewer_ViewManager* pvvm = dynamic_cast<PVViewer_ViewManager*>( vm ) ) {
993     connect( pvvm, SIGNAL( viewCreated( SUIT_ViewWindow* ) ), 
994              this, SLOT( onPVViewCreated( SUIT_ViewWindow* ) ) );
995     connect( pvvm, SIGNAL( deleteView( SUIT_ViewWindow* ) ),
996              this,  SLOT( onPVViewDelete( SUIT_ViewWindow* ) ) );
997   }
998 }
999
1000 /*!
1001   \brief Called when view manager is removed
1002 */
1003 void PVGUI_Module::onViewManagerRemoved( SUIT_ViewManager* vm )
1004 {
1005   if ( PVViewer_ViewManager* pvvm = dynamic_cast<PVViewer_ViewManager*>( vm ) )
1006     disconnect( pvvm, SIGNAL( viewCreated( SUIT_ViewWindow* ) ),
1007                 this, SLOT( onPVViewCreated( SUIT_ViewWindow* ) ) );
1008 }
1009
1010 /*!
1011   \brief Show toolbars at \a vw PV view window creating when PARAVIS is active.
1012 */
1013 void PVGUI_Module::onPVViewCreated( SUIT_ViewWindow* vw )
1014 {
1015   myGuiElements->setToolBarVisible( true );
1016   restoreDockWidgetsState();
1017 }
1018
1019 /*!
1020   \brief Save toolbars state at \a view view closing.
1021 */
1022 void PVGUI_Module::onPVViewDelete( SUIT_ViewWindow* view )
1023 {
1024   if ( dynamic_cast<PVViewer_ViewWindow*>( view ) )
1025     saveDockWidgetsState( false );
1026 }
1027
1028 /*!
1029   \fn CAM_Module* createModule();
1030   \brief Export module instance (factory function).
1031   \return new created instance of the module
1032 */
1033
1034 #ifdef WNT
1035 #define PVGUI_EXPORT __declspec(dllexport)
1036 #else   // WNT
1037 #define PVGUI_EXPORT
1038 #endif  // WNT
1039
1040 extern "C" {
1041
1042   bool flag = false;
1043   PVGUI_EXPORT CAM_Module* createModule() {
1044     return new PVGUI_Module();
1045   }
1046   
1047   PVGUI_EXPORT char* getModuleVersion() {
1048     return (char*)PARAVIS_VERSION_STR;
1049   }
1050 }