Salome HOME
[PVViewer] Add Catalyst menu
[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 //----------------------------------------------------------------------------
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 #ifdef PVCATALYST_ENABLED
170     myCatalystMenuId(-1),
171 #endif
172     myMacrosMenuId(-1),
173     myRecentMenuId(-1),
174     myOldMsgHandler(0),
175     myTraceWindow(0),
176     myInitTimer(0),
177     myGuiElements(0)
178 {
179 #ifdef HAS_PV_DOC
180   Q_INIT_RESOURCE( PVGUI );
181 #endif
182   ParavisModule = this;
183
184   // Clear old copies of embedded macros files
185   QString aDestPath = QString( "%1/.config/%2/Macros" ).arg( QDir::homePath() ).arg( QApplication::applicationName() );
186   QStringList aFilter;
187   aFilter << "*.py";
188
189   QDir aDestDir(aDestPath);
190   QStringList aDestFiles = aDestDir.entryList(aFilter, QDir::Files);
191   foreach (QString aMacrosPath, getEmbeddedMacrosList()) {
192     QString aMacrosName = QFileInfo(aMacrosPath).fileName();
193     if (aDestFiles.contains(aMacrosName)) {
194       aDestDir.remove(aMacrosName);
195     }
196   }
197 }
198
199 /*!
200   \brief Destructor.
201 */
202 PVGUI_Module::~PVGUI_Module()
203 {
204   if (myInitTimer)
205     delete myInitTimer;
206 }
207
208 /*!
209   \brief Retrieve the PVSERVER CORBA engine.
210   This uses the Python wrapper provided
211   by the PVViewer code in GUI (class PVViewer_EngineWrapper).
212   \sa GetCPPEngine()
213 */
214 PVServer_ServiceWrapper* PVGUI_Module::GetEngine()
215 {
216   return PVServer_ServiceWrapper::GetInstance();
217 }
218
219 /*!
220   \brief Create data model.
221   \return module specific data model
222 */
223 CAM_DataModel* PVGUI_Module::createDataModel()
224 {
225   return new PVGUI_DataModel( this );
226 }
227
228 /*!
229   \brief Get the ParaView application singleton.
230 */
231 pqPVApplicationCore* PVGUI_Module::GetPVApplication()
232 {
233   return PVViewer_Core::GetPVApplication();
234 }
235
236 /*!
237   \brief Initialize module. Creates menus, prepares context menu, etc.
238   \param app SALOME GUI application instance
239 */
240 void PVGUI_Module::initialize( CAM_Application* app )
241 {
242   LightApp_Module::initialize( app );
243
244   // Uncomment to debug ParaView initialization
245   // "aa" used instead of "i" as GDB doesn't like "i" variables :)
246   /*
247   int aa = 1;
248   while( aa ){
249     aa = aa;
250   }
251   */
252
253   LightApp_Application* anApp = getApp();
254   SUIT_Desktop* aDesktop = anApp->desktop();
255
256   // Remember current state of desktop toolbars
257   QList<QToolBar*> foreignToolbars = aDesktop->findChildren<QToolBar*>();
258
259   // Initialize ParaView client and associated behaviors
260   // and connect to externally launched pvserver
261   PVViewer_Core::ParaviewInitApp(aDesktop, anApp->logWindow());
262   myGuiElements = PVViewer_GUIElements::GetInstance(aDesktop);
263
264   // [ABN]: careful with the order of the GUI element creation, the loading of the configuration
265   // and the connection to the server. This order is very sensitive if one wants to make
266   // sure all menus, etc ... are correctly populated.
267   // Reference points are: ParaViewMainWindow.cxx and branded_paraview_initializer.cxx.in
268   setupDockWidgets();
269
270   pvCreateActions();
271   pvCreateMenus();
272   pvCreateToolBars();
273
274   PVViewer_Core::ParaviewInitBehaviors(true, aDesktop);
275
276   QList<QDockWidget*> activeDocks = aDesktop->findChildren<QDockWidget*>();
277   QList<QMenu*> activeMenus = aDesktop->findChildren<QMenu*>();
278
279   // Setup quick-launch shortcuts.
280   QShortcut *ctrlSpace = new QShortcut(Qt::CTRL + Qt::Key_Space, aDesktop);
281   QObject::connect(ctrlSpace, SIGNAL(activated()),
282     pqApplicationCore::instance(), SLOT(quickLaunch()));
283
284   // Find Plugin Dock Widgets
285   QList<QDockWidget*> currentDocks = aDesktop->findChildren<QDockWidget*>();
286   QList<QDockWidget*>::iterator i;
287   for (i = currentDocks.begin(); i != currentDocks.end(); ++i) {
288     if(!activeDocks.contains(*i)) {
289       myDockWidgets[*i] = false; // hidden by default
290       (*i)->hide();
291     }
292   }
293
294     // Find Plugin Menus
295     // [ABN] TODO: fix this - triggers a SEGFAULT at deactivation() time.
296 //    QList<QMenu*> currentMenus = aDesktop->findChildren<QMenu*>();
297 //    QList<QMenu*>::iterator im;
298 //    for (im = currentMenus.begin(); im != currentMenus.end(); ++im) {
299 //      if(!activeMenus.contains(*im)) {
300 //          QString s = (*im)->title();
301 //          std::cout << " MENU "<<  s.toStdString() << std::endl;
302 //          myMenus.append(*im);
303 //      }
304 //    }
305
306   // Connect after toolbar creation, etc ... as some activations of the toolbars is triggered
307   // by the ServerConnection event:
308   const QString configPath(PVViewer_ViewManager::GetPVConfigPath());
309   PVViewer_Core::ParaviewLoadConfigurations(configPath, true);
310   PVViewer_ViewManager::ConnectToExternalPVServer(aDesktop);
311   updateObjBrowser();
312
313   // Find created toolbars
314   QCoreApplication::processEvents();
315
316   // process PVViewer toolbars (might be added by PVViewer created BEFORE activating ParaVis)
317   QList<QToolBar*> pvToolbars = myGuiElements->getToolbars();
318   foreach(QToolBar* aBar, pvToolbars) {
319     if (!myToolbars.contains(aBar)) {
320       myToolbars[aBar] = true;
321       myToolbarBreaks[aBar] = false;
322       aBar->setVisible(false);
323       aBar->toggleViewAction()->setVisible(false);
324     }
325   }
326
327   // process other toolbars (possibly added by Paraview)
328   QList<QToolBar*> allToolbars = aDesktop->findChildren<QToolBar*>();
329   foreach(QToolBar* aBar, allToolbars) {
330     if (!foreignToolbars.contains(aBar) && !myToolbars.contains(aBar)) {
331       myToolbars[aBar] = true;
332       myToolbarBreaks[aBar] = false;
333       aBar->setVisible(false);
334       aBar->toggleViewAction()->setVisible(false);
335     }
336   }
337
338   updateMacros();
339
340   SUIT_ResourceMgr* aResourceMgr = SUIT_Session::session()->resourceMgr();
341   bool isStop = aResourceMgr->booleanValue( PARAVIS_MODULE_NAME, "stop_trace", false );
342   if(!isStop)
343     {
344       // Start a timer to schedule asap:
345       //  - the trace start
346       myInitTimer = new QTimer(aDesktop);
347       QObject::connect(myInitTimer, SIGNAL(timeout()), this, SLOT(onInitTimer()) );
348       myInitTimer->setSingleShot(true);
349       myInitTimer->start(0);
350     }
351
352   this->VTKConnect = vtkEventQtSlotConnect::New();
353
354   vtkProcessModule* pm = vtkProcessModule::GetProcessModule();
355   if(pm) {
356     vtkPVSession* pvs = dynamic_cast<vtkPVSession*>(pm->GetSession());
357     if(pvs) {
358       vtkPVProgressHandler* ph = pvs->GetProgressHandler();
359       if(ph) {
360           this->VTKConnect->Connect(ph, vtkCommand::StartEvent,
361                                     this, SLOT(onStartProgress()));
362           this->VTKConnect->Connect(ph, vtkCommand::EndEvent,
363                                     this, SLOT(onEndProgress()));
364       }
365     }
366   }
367   connect( application(), SIGNAL( appClosed() ), this, SLOT( onStopTrace() ) );
368 }
369
370 /*!
371  * \brief Slot called when the progress bar starts.
372  */
373 void PVGUI_Module::onStartProgress()
374 {
375   // VSR 19/03/2015, issue 0023025
376   // next line is commented: it is bad idea to show wait cursor on ANY vtk event
377   // moreover, it does not work when running pvserver with --multi-client mode
378   //QApplication::setOverrideCursor(Qt::WaitCursor);
379 }
380
381 /*!
382  * \brief Slot called when the progress bar is done.
383  */
384 void PVGUI_Module::onEndProgress()
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::restoreOverrideCursor();
390 }
391
392 void PVGUI_Module::onDataRepresentationUpdated() {
393   LightApp_Study* activeStudy = dynamic_cast<LightApp_Study*>(application()->activeStudy());
394   if(!activeStudy) return;
395
396   activeStudy->Modified();
397 }
398
399 /*!
400   \brief Initialisation timer event - Starts up the Python trace
401 */
402 void PVGUI_Module::onInitTimer()
403 {
404   startTrace();
405 }
406
407 /*!
408   \brief Get list of embedded macros files
409 */
410 QStringList PVGUI_Module::getEmbeddedMacrosList()
411 {
412   QString aRootDir = getenv("PARAVIS_ROOT_DIR");
413
414   QString aSourcePath = aRootDir + "/bin/salome/Macro";
415
416   QStringList aFilter;
417   aFilter << "*.py";
418
419   QDir aSourceDir(aSourcePath);
420   QStringList aSourceFiles = aSourceDir.entryList(aFilter, QDir::Files);
421   QStringList aFullPathSourceFiles;
422   foreach (QString aMacrosName, aSourceFiles) {
423     aFullPathSourceFiles << aSourceDir.absoluteFilePath(aMacrosName);
424   }
425   return aFullPathSourceFiles;
426 }
427
428 /*!
429   \brief Update the list of embedded macros
430 */
431 void PVGUI_Module::updateMacros()
432 {
433   pqPythonManager* aPythonManager = pqPVApplicationCore::instance()->pythonManager();
434   if(!aPythonManager)  {
435     return;
436   }
437
438   foreach (QString aStr, getEmbeddedMacrosList()) {
439     aPythonManager->addMacro(aStr);
440   }
441 }
442
443
444 /*!
445   \brief Get list of compliant dockable GUI elements
446   \param m map to be filled in ("type":"default_position")
447 */
448 void PVGUI_Module::windows( QMap<int, int>& m ) const
449 {
450   m.insert( LightApp_Application::WT_ObjectBrowser, Qt::LeftDockWidgetArea );
451 #ifndef DISABLE_PYCONSOLE
452   m.insert( LightApp_Application::WT_PyConsole, Qt::BottomDockWidgetArea );
453 #endif
454   // ParaView diagnostic output redirected here
455   m.insert( LightApp_Application::WT_LogWindow, Qt::BottomDockWidgetArea );
456 }
457
458 /*!
459   \brief Shows (toShow = true) or hides ParaView view window
460 */
461 void PVGUI_Module::showView( bool toShow )
462 {
463   // VSR: TODO: all below is not needed, if we use standard approach
464   // that consists in implementing viewManagers() function properly
465   // This should be done after we decide what to do with Log window.
466   LightApp_Application* anApp = getApp();
467   PVViewer_ViewManager* viewMgr =
468     dynamic_cast<PVViewer_ViewManager*>( anApp->getViewManager( PVViewer_Viewer::Type(), false ) );
469   if ( !viewMgr ) {
470     viewMgr = new PVViewer_ViewManager( anApp->activeStudy(), anApp->desktop(), anApp->logWindow() );
471     anApp->addViewManager( viewMgr );
472     connect( viewMgr, SIGNAL( lastViewClosed( SUIT_ViewManager* ) ),
473              anApp, SLOT( onCloseView( SUIT_ViewManager* ) ) );
474   }
475
476   PVViewer_ViewWindow* pvWnd = dynamic_cast<PVViewer_ViewWindow*>( viewMgr->getActiveView() );
477   if ( !pvWnd ) {
478     pvWnd = dynamic_cast<PVViewer_ViewWindow*>( viewMgr->createViewWindow() );
479     // this also connects to the pvserver and instantiates relevant PV behaviors
480   }
481
482   pvWnd->setVisible( toShow );
483   if ( toShow ) pvWnd->setFocus();
484 }
485
486 /*!
487   \brief Slot to show help for proxy.
488 */
489 void PVGUI_Module::showHelpForProxy( const QString& groupname, const QString& proxyname )
490 {
491   pqHelpReaction::showProxyHelp(groupname, proxyname);
492 }
493
494 /*!
495   \brief Slot to show the waiting state.
496 */
497 void PVGUI_Module::onPreAccept()
498 {
499   getApp()->desktop()->statusBar()->showMessage(tr("STB_PREACCEPT"));
500   QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
501 }
502
503 /*!
504   \brief Slot to show the ready state.
505 */
506 void PVGUI_Module::onPostAccept()
507 {
508   getApp()->desktop()->statusBar()->showMessage(tr("STB_POSTACCEPT"), 2000);
509   QTimer::singleShot(0, this, SLOT(endWaitCursor()));
510 }
511
512 /*!
513   \brief Slot to switch off wait cursor.
514 */
515 void PVGUI_Module::endWaitCursor()
516 {
517   QApplication::restoreOverrideCursor();
518 }
519 #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
520 /*!
521   \brief Handler method for the output of messages.
522 */
523 static void ParavisMessageOutput(QtMsgType type, const char *msg)
524 {
525   switch(type)
526     {
527   case QtDebugMsg:
528     vtkOutputWindow::GetInstance()->DisplayText(msg);
529     break;
530   case QtWarningMsg:
531     vtkOutputWindow::GetInstance()->DisplayErrorText(msg);
532     break;
533   case QtCriticalMsg:
534     vtkOutputWindow::GetInstance()->DisplayErrorText(msg);
535     break;
536   case QtFatalMsg:
537     vtkOutputWindow::GetInstance()->DisplayErrorText(msg);
538     break;
539     }
540 }
541 #else
542 /*!
543   \brief Handler method for the output of messages.
544 */
545 static void ParavisMessageOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg)
546 {
547   switch(type)
548     {
549   case QtDebugMsg:
550     vtkOutputWindow::GetInstance()->DisplayText(msg.toLatin1().constData());
551     break;
552   case QtWarningMsg:
553     vtkOutputWindow::GetInstance()->DisplayErrorText(msg.toLatin1().constData());
554     break;
555   case QtCriticalMsg:
556     vtkOutputWindow::GetInstance()->DisplayErrorText(msg.toLatin1().constData());
557     break;
558   case QtFatalMsg:
559     vtkOutputWindow::GetInstance()->DisplayErrorText(msg.toLatin1().constData());
560     break;
561     }
562 }
563 #endif
564 /*!
565   \brief Activate module.
566   \param study current study
567   \return \c true if activaion is done successfully or 0 to prevent
568   activation on error
569 */
570 bool PVGUI_Module::activateModule( SUIT_Study* study )
571 {
572 #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
573   myOldMsgHandler = qInstallMsgHandler(ParavisMessageOutput);
574 #else
575   myOldMsgHandler = qInstallMessageHandler(ParavisMessageOutput);
576 #endif
577   SUIT_ExceptionHandler::addCleanUpRoutine( paravisCleanUp );
578
579   storeCommonWindowsState();
580
581   bool isDone = LightApp_Module::activateModule( study );
582   if ( !isDone ) return false;
583
584   showView( true );
585   if ( mySourcesMenuId != -1 ) menuMgr()->show(mySourcesMenuId);
586   if ( myFiltersMenuId != -1 ) menuMgr()->show(myFiltersMenuId);
587 #ifdef PVCATALYST_ENABLED
588   if ( myCatalystMenuId != -1 ) menuMgr()->show(myCatalystMenuId);
589 #endif
590   if ( myMacrosMenuId != -1 ) menuMgr()->show(myMacrosMenuId);
591
592   // Update the various menus with the content pre-loaded in myGuiElements
593 //  QMenu* srcMenu = menuMgr()->findMenu( mySourcesMenuId );
594 //  myGuiElements->updateSourcesMenu(srcMenu);
595 //  QMenu* filtMenu = menuMgr()->findMenu( myFiltersMenuId );
596 //  myGuiElements->updateFiltersMenu(filtMenu);
597 //#ifdef PVCATALYST_ENABLED
598 //  QMenu* catalystMenu = menuMgr()->findMenu( myCatalystMenuId );
599 //  myGuiElements->updateCatalystMenu(catalystMenu);
600 //#endif
601 //  QMenu* macMenu = menuMgr()->findMenu( myMacrosMenuId );
602 //  myGuiElements->updateMacrosMenu(macMenu);
603
604   setMenuShown( true );
605   setToolShown( true );
606
607   restoreDockWidgetsState();
608
609   QMenu* aMenu = menuMgr()->findMenu( myRecentMenuId );
610   if(aMenu) {
611     QList<QAction*> anActns = aMenu->actions();
612     for (int i = 0; i < anActns.size(); ++i) {
613       QAction* a = anActns.at(i);
614       if(a)
615         a->setVisible(true);
616     }
617   }
618
619   QList<QMenu*>::iterator it;
620   for (it = myMenus.begin(); it != myMenus.end(); ++it) {
621     QAction* a = (*it)->menuAction();
622     if(a)
623       a->setVisible(true);
624   }
625
626   if ( myRecentMenuId != -1 ) menuMgr()->show(myRecentMenuId);
627
628   return isDone;
629 }
630
631
632 /*!
633   \brief Deactivate module.
634   \param study current study
635   \return \c true if deactivaion is done successfully or 0 to prevent
636   deactivation on error
637 */
638 bool PVGUI_Module::deactivateModule( SUIT_Study* study )
639 {
640   MESSAGE("PARAVIS deactivation ...")
641
642   QMenu* aMenu = menuMgr()->findMenu( myRecentMenuId );
643   if(aMenu) {
644     QList<QAction*> anActns = aMenu->actions();
645     for (int i = 0; i < anActns.size(); ++i) {
646       QAction* a = anActns.at(i);
647       if(a)
648         a->setVisible(false);
649     }
650   }
651
652   QList<QMenu*>::iterator it;
653   for (it = myMenus.begin(); it != myMenus.end(); ++it) {
654     QAction* a = (*it)->menuAction();
655     if(a)
656       a->setVisible(false);
657   }
658
659   QList<QDockWidget*> aStreamingViews = application()->desktop()->findChildren<QDockWidget*>("pqStreamingControls");
660   foreach(QDockWidget* aView, aStreamingViews) {
661     if (!myDockWidgets.contains(aView))
662       myDockWidgets[aView] = aView->isVisible();
663   }
664
665   /*if (pqImplementation::helpWindow) {
666     pqImplementation::helpWindow->hide();
667     }*/
668   // hide menus
669   menuMgr()->hide(myRecentMenuId);
670   menuMgr()->hide(mySourcesMenuId);
671   menuMgr()->hide(myFiltersMenuId);
672 #ifdef PVCATALYST_ENABLED
673   menuMgr()->hide(myCatalystMenuId);
674 #endif
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 << ", " << PyString_AsString(elem) << 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(PyString_FromString(end_line.toStdString().c_str()));
851         vtkSmartPyObject final_string(PyObject_CallMethod(ret, const_cast<char*>("join"),
852             const_cast<char*>("O"), (PyObject*)camera_trace));
853         if (PyString_CheckExact(final_string))
854           {
855             QString camera_qs(PyString_AsString(final_string));  // 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 }