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