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