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