]> SALOME platform Git repositories - modules/paravis.git/blob - src/PVGUI/PVGUI_Module.cxx
Salome HOME
ba47ba8cbcc4cbf739f64da53daae54e2e85d694
[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 #ifndef DISABLE_PYCONSOLE
446   m.insert( LightApp_Application::WT_PyConsole, Qt::BottomDockWidgetArea );
447 #endif
448   // ParaView diagnostic output redirected here
449   m.insert( LightApp_Application::WT_LogWindow, Qt::BottomDockWidgetArea );
450 }
451
452 /*!
453   \brief Shows (toShow = true) or hides ParaView view window
454 */
455 void PVGUI_Module::showView( bool toShow )
456 {
457   // VSR: TODO: all below is not needed, if we use standard approach
458   // that consists in implementing viewManagers() function properly
459   // This should be done after we decide what to do with Log window.
460   LightApp_Application* anApp = getApp();
461   PVViewer_ViewManager* viewMgr =
462     dynamic_cast<PVViewer_ViewManager*>( anApp->getViewManager( PVViewer_Viewer::Type(), false ) );
463   if ( !viewMgr ) {
464     viewMgr = new PVViewer_ViewManager( anApp->activeStudy(), anApp->desktop(), anApp->logWindow() );
465     anApp->addViewManager( viewMgr );
466     connect( viewMgr, SIGNAL( lastViewClosed( SUIT_ViewManager* ) ),
467              anApp, SLOT( onCloseView( SUIT_ViewManager* ) ) );
468   }
469
470   PVViewer_ViewWindow* pvWnd = dynamic_cast<PVViewer_ViewWindow*>( viewMgr->getActiveView() );
471   if ( !pvWnd ) {
472     pvWnd = dynamic_cast<PVViewer_ViewWindow*>( viewMgr->createViewWindow() );
473     // this also connects to the pvserver and instantiates relevant PV behaviors
474   }
475
476   pvWnd->setShown( toShow );
477   if ( toShow ) pvWnd->setFocus();
478 }
479
480 /*!
481   \brief Slot to show help for proxy.
482 */
483 void PVGUI_Module::showHelpForProxy( const QString& groupname, const QString& proxyname )
484 {
485   pqHelpReaction::showProxyHelp(groupname, proxyname);
486 }
487
488 /*!
489   \brief Slot to show the waiting state.
490 */
491 void PVGUI_Module::onPreAccept()
492 {
493   getApp()->desktop()->statusBar()->showMessage(tr("STB_PREACCEPT"));
494   QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
495 }
496
497 /*!
498   \brief Slot to show the ready state.
499 */
500 void PVGUI_Module::onPostAccept()
501 {
502   getApp()->desktop()->statusBar()->showMessage(tr("STB_POSTACCEPT"), 2000);
503   QTimer::singleShot(0, this, SLOT(endWaitCursor()));
504 }
505
506 /*!
507   \brief Slot to switch off wait cursor.
508 */
509 void PVGUI_Module::endWaitCursor()
510 {
511   QApplication::restoreOverrideCursor();
512 }
513
514 /*!
515   \brief Handler method for the output of messages.
516 */
517 static void ParavisMessageOutput(QtMsgType type, const char *msg)
518 {
519   switch(type)
520     {
521   case QtDebugMsg:
522     vtkOutputWindow::GetInstance()->DisplayText(msg);
523     break;
524   case QtWarningMsg:
525     vtkOutputWindow::GetInstance()->DisplayErrorText(msg);
526     break;
527   case QtCriticalMsg:
528     vtkOutputWindow::GetInstance()->DisplayErrorText(msg);
529     break;
530   case QtFatalMsg:
531     vtkOutputWindow::GetInstance()->DisplayErrorText(msg);
532     break;
533     }
534 }
535
536 /*!
537   \brief Activate module.
538   \param study current study
539   \return \c true if activaion is done successfully or 0 to prevent
540   activation on error
541 */
542 bool PVGUI_Module::activateModule( SUIT_Study* study )
543 {
544   myOldMsgHandler = qInstallMsgHandler(ParavisMessageOutput);
545   
546   SUIT_ExceptionHandler::addCleanUpRoutine( paravisCleanUp );
547
548   storeCommonWindowsState();
549
550   bool isDone = LightApp_Module::activateModule( study );
551   if ( !isDone ) return false;
552
553   showView( true );
554   if ( mySourcesMenuId != -1 ) menuMgr()->show(mySourcesMenuId);
555   if ( myFiltersMenuId != -1 ) menuMgr()->show(myFiltersMenuId);
556   if ( myMacrosMenuId != -1 ) menuMgr()->show(myMacrosMenuId);
557
558   // Update the various menus with the content pre-loaded in myGuiElements
559 //  QMenu* srcMenu = menuMgr()->findMenu( mySourcesMenuId );
560 //  myGuiElements->updateSourcesMenu(srcMenu);
561 //  QMenu* filtMenu = menuMgr()->findMenu( myFiltersMenuId );
562 //  myGuiElements->updateFiltersMenu(filtMenu);
563 //  QMenu* macMenu = menuMgr()->findMenu( myMacrosMenuId );
564 //  myGuiElements->updateMacrosMenu(macMenu);
565
566   setMenuShown( true );
567   setToolShown( true );
568
569   restoreDockWidgetsState();
570
571   QMenu* aMenu = menuMgr()->findMenu( myRecentMenuId );
572   if(aMenu) {
573     QList<QAction*> anActns = aMenu->actions();
574     for (int i = 0; i < anActns.size(); ++i) {
575       QAction* a = anActns.at(i);
576       if(a)
577         a->setVisible(true);
578     }
579   }
580
581   QList<QMenu*>::iterator it;
582   for (it = myMenus.begin(); it != myMenus.end(); ++it) {
583     QAction* a = (*it)->menuAction();
584     if(a)
585       a->setVisible(true);
586   }
587
588   if ( myRecentMenuId != -1 ) menuMgr()->show(myRecentMenuId);
589   
590   return isDone;
591 }
592
593
594 /*!
595   \brief Deactivate module.
596   \param study current study
597   \return \c true if deactivaion is done successfully or 0 to prevent
598   deactivation on error
599 */
600 bool PVGUI_Module::deactivateModule( SUIT_Study* study )
601 {
602   MESSAGE("PARAVIS deactivation ...")
603
604   QMenu* aMenu = menuMgr()->findMenu( myRecentMenuId );
605   if(aMenu) {
606     QList<QAction*> anActns = aMenu->actions();
607     for (int i = 0; i < anActns.size(); ++i) {
608       QAction* a = anActns.at(i);
609       if(a)
610         a->setVisible(false);
611     }
612   }
613
614   QList<QMenu*>::iterator it;
615   for (it = myMenus.begin(); it != myMenus.end(); ++it) {
616     QAction* a = (*it)->menuAction();
617     if(a)
618       a->setVisible(false);
619   }
620
621   QList<QDockWidget*> aStreamingViews = application()->desktop()->findChildren<QDockWidget*>("pqStreamingControls");
622   foreach(QDockWidget* aView, aStreamingViews) {
623     if (!myDockWidgets.contains(aView))
624       myDockWidgets[aView] = aView->isVisible();
625   }
626
627   /*if (pqImplementation::helpWindow) {
628     pqImplementation::helpWindow->hide();
629     }*/
630   // hide menus
631   menuMgr()->hide(myRecentMenuId);
632   menuMgr()->hide(mySourcesMenuId);
633   menuMgr()->hide(myFiltersMenuId);
634   menuMgr()->hide(myMacrosMenuId);
635   setMenuShown( false );
636   setToolShown( false );
637
638   saveDockWidgetsState();
639
640   SUIT_ExceptionHandler::removeCleanUpRoutine( paravisCleanUp );
641
642   if (myOldMsgHandler)
643     qInstallMsgHandler(myOldMsgHandler);
644
645   restoreCommonWindowsState();
646   
647   return LightApp_Module::deactivateModule( study );
648 }
649
650
651 /*!
652   \brief Called when application is closed.
653
654   Process finalize application functionality from ParaView in order to save server settings
655   and nullify application pointer if the application is being closed.
656
657   \param theApp application
658 */
659 void PVGUI_Module::onApplicationClosed( SUIT_Application* theApp )
660 {
661   PVViewer_ViewManager::ParaviewCleanup();
662   CAM_Module::onApplicationClosed(theApp);
663 }
664
665 /*!
666   \brief Called when study is closed.
667
668   Removes data model from the \a study.
669
670   \param study study being closed
671 */
672 void PVGUI_Module::studyClosed(SUIT_Study* study)
673 {
674   showView(false); // VSR: this seems to be not needed (all views are automatically closed)
675   clearParaviewState();
676   //Re-start trace 
677   onRestartTrace();
678
679   LightApp_Module::studyClosed(study);
680 }
681
682 /*!
683   \brief Open file of format supported by ParaView
684 */
685 void PVGUI_Module::openFile( const char* theName )
686 {
687   QStringList aFiles;
688   aFiles << theName;
689   pqLoadDataReaction::loadData( aFiles );
690 }
691
692 /*!
693   \brief Starts Python trace.
694  
695   Start trace invoking the newly introduced C++ API (PV 4.2)
696   (inspired from pqTraceReaction::start())
697 */
698 void PVGUI_Module::startTrace()
699 {
700   vtkSMSessionProxyManager* pxm = pqActiveObjects::instance().activeServer()->proxyManager();
701
702   vtkSmartPointer<vtkSMProxy> proxy;
703   proxy.TakeReference( pxm->NewProxy( "pythontracing", "PythonTraceOptions" ) );
704   if ( proxy ) {
705     vtkNew<vtkSMParaViewPipelineController> controller;
706     controller->InitializeProxy( proxy );
707   }
708   vtkSMTrace* trace = vtkSMTrace::StartTrace();
709   if ( proxy ) {
710     // Set manually the properties entered via the dialog box poping-up when requiring
711     // a trace start in PV4.2 (trace options)
712     SUIT_ResourceMgr* aResourceMgr = SUIT_Session::session()->resourceMgr();
713     int type = aResourceMgr->integerValue( PARAVIS_MODULE_NAME, "tracestate_type", 2 );
714     trace->SetPropertiesToTraceOnCreate( type );
715     trace->SetFullyTraceSupplementalProxies( false );
716   }
717 }
718
719 /*!
720   \brief Stops Python trace.
721 */
722 void PVGUI_Module::stopTrace()
723 {
724   vtkSMTrace::StopTrace();
725 }
726
727 /*!
728   \brief Execute a Python script.
729 */
730 void PVGUI_Module::executeScript( const char* script )
731 {
732 #ifndef WNT
733   pqPythonManager* manager = qobject_cast<pqPythonManager*>(
734                              pqApplicationCore::instance()->manager( "PYTHON_MANAGER" ) );
735   if ( manager )  {
736     pqPythonDialog* pyDiag = manager->pythonShellDialog();
737     if ( pyDiag ) {
738       pyDiag->runString(script);  
739     }
740   }
741 #endif
742 }
743
744 ///**
745 // *  Debug function printing out the given interpreter's execution context
746 // */
747 //void printInterpContext(PyInterp_Interp * interp )
748 //{
749 //  // Extract __smtraceString from interpreter's context
750 //  const PyObject* ctxt = interp->getExecutionContext();
751 //
752 //  PyObject* lst = PyDict_Keys((PyObject *)ctxt);
753 //  Py_ssize_t siz = PyList_GET_SIZE(lst);
754 //  for (Py_ssize_t i = 0; i < siz; i++)
755 //    {
756 //      PyObject * elem = PyList_GetItem(lst, i);
757 //      if (PyString_Check(elem))
758 //        {
759 //          std::cout << "At pos:" << i << ", " << PyString_AsString(elem) << std::endl;
760 //        }
761 //      else
762 //        std::cout << "At pos:" << i << ", not a string!" << std::endl;
763 //    }
764 //  Py_XDECREF(lst);
765 //}
766
767 /*!
768   \brief Returns trace string
769 */
770 QString PVGUI_Module::getTraceString()
771 {
772   QString traceString = "";
773
774   static const QString replaceStr( "paraview.simple" );
775   std::stringstream nl;
776   nl << std::endl; // surely there is some Qt trick to do that in a portable way??
777   QString end_line( nl.str().c_str() );
778
779   vtkSMTrace* tracer = vtkSMTrace::GetActiveTracer();
780   if ( tracer ) {
781     traceString = tracer->GetCurrentTrace();
782     // 'import pvsimple' is necessary to fix the first call to DisableFirstRenderCamera in the paraview trace
783     // 'ShowParaviewView()' ensure there is an opened viewing window (otherwise SEGFAULT!)
784     traceString = "import pvsimple" + end_line +
785       "pvsimple.ShowParaviewView()" + end_line + traceString;
786
787     // Replace import "paraview.simple" by "pvsimple"
788     if ( !traceString.isEmpty() ) {
789       int aPos = traceString.indexOf( replaceStr );
790       while ( aPos != -1 ) {
791         traceString = traceString.replace( aPos, replaceStr.length(), "pvsimple" );
792         aPos = traceString.indexOf( replaceStr, aPos );
793       }
794     }
795   }
796
797   // Save camera position to, which is no longer output by the tracer ...
798   VTK_PY_GIL_ENSURE
799   PyObject * mods(PySys_GetObject(const_cast<char*>("modules")));
800   PyObject * trace_mod(PyDict_GetItemString(mods, "paraview.smtrace"));  // module was already (really) imported by vtkSMTrace
801   if (PyModule_Check(trace_mod)) {
802       vtkSmartPyObject save_cam(PyObject_GetAttrString(trace_mod, const_cast<char*>("SaveCameras")));
803       vtkSmartPyObject camera_trace(PyObject_CallMethod(save_cam, const_cast<char*>("get_trace"), NULL));
804       // Convert to a single string
805       vtkSmartPyObject ret(PyString_FromString(end_line.toStdString().c_str()));
806       vtkSmartPyObject final_string(PyObject_CallMethod(ret, const_cast<char*>("join"),
807           const_cast<char*>("O"), (PyObject*)camera_trace));
808       if (PyString_CheckExact(final_string))
809         {
810           QString camera_qs(PyString_AsString(final_string));  // deep copy
811           traceString = traceString + end_line  + end_line + QString("#### saving camera placements for all active views")
812               + end_line + end_line + camera_qs + end_line;
813         }
814     }
815   VTK_PY_GIL_RELEASE
816
817   return traceString;
818 }
819
820 /*!
821   \brief Saves trace string to disk file
822 */
823 void PVGUI_Module::saveTrace( const char* theName )
824 {
825   QFile file( theName );
826   if ( !file.open( QIODevice::WriteOnly | QIODevice::Text ) ) {
827     MESSAGE( "Could not open file:" << theName );
828     return;
829   }
830   QTextStream out( &file );
831   out << getTraceString();
832   file.close();
833 }
834
835 /*!
836   \brief Saves ParaView state to a disk file
837 */
838 void PVGUI_Module::saveParaviewState( const char* theFileName )
839 {
840   pqApplicationCore::instance()->saveState( theFileName );
841 }
842
843 /*!
844   \brief Delete all objects for Paraview Pipeline Browser
845 */
846 void PVGUI_Module::clearParaviewState()
847 {
848   QAction* deleteAllAction = action( DeleteAllId );
849   if ( deleteAllAction ) {
850     deleteAllAction->activate( QAction::Trigger );
851   }
852 }
853
854 /*!
855   \brief Restores ParaView state from a disk file
856 */
857 void PVGUI_Module::loadParaviewState( const char* theFileName )
858 {
859   pqApplicationCore::instance()->loadState( theFileName, getActiveServer() );
860 }
861
862 /*!
863   \brief Returns current active ParaView server
864 */
865 pqServer* PVGUI_Module::getActiveServer()
866 {
867   return pqApplicationCore::instance()->getActiveServer();
868 }
869
870
871 /*!
872   \brief Creates PARAVIS preferences panel.
873 */
874 void PVGUI_Module::createPreferences()
875 {
876   // Paraview settings tab
877   int aParaViewSettingsTab = addPreference( tr( "TIT_PVIEWSETTINGS" ) );
878
879   setPreferenceProperty(aParaViewSettingsTab, "stretch", false );
880   int aPanel = addPreference( QString(), aParaViewSettingsTab,
881                               LightApp_Preferences::UserDefined, PARAVIS_MODULE_NAME, "" );
882
883   setPreferenceProperty( aPanel, "content", (qint64)( new PVGUI_ParaViewSettingsPane( 0, getApp() ) ) );
884
885   // Paravis settings tab
886   int aParaVisSettingsTab = addPreference( tr( "TIT_PVISSETTINGS" ) );
887   addPreference( tr( "PREF_STOP_TRACE" ), aParaVisSettingsTab, 
888                  LightApp_Preferences::Bool, PARAVIS_MODULE_NAME, "stop_trace" );
889
890   addPreference( tr( "PREF_NO_EXT_PVSERVER" ), aParaVisSettingsTab, 
891                  LightApp_Preferences::Bool, PARAVIS_MODULE_NAME, "no_ext_pv_server" );
892
893   int aSaveType = addPreference( tr( "PREF_SAVE_TYPE_LBL" ), aParaVisSettingsTab,
894                                  LightApp_Preferences::Selector,
895                                  PARAVIS_MODULE_NAME, "savestate_type" );
896
897   int aTraceType = addPreference( tr( "PREF_TRACE_TYPE_LBL" ), aParaVisSettingsTab,
898                                  LightApp_Preferences::Selector,
899                                  PARAVIS_MODULE_NAME, "tracestate_type" );
900   QList<QVariant> aIndices;
901   QStringList aStrings;
902   aIndices << 0 << 1 << 2;
903   aStrings << tr("PREF_SAVE_TYPE_0");
904   aStrings << tr("PREF_SAVE_TYPE_1");
905   aStrings << tr("PREF_SAVE_TYPE_2");
906   setPreferenceProperty( aSaveType, "strings", aStrings );
907   setPreferenceProperty( aSaveType, "indexes", aIndices );
908
909   aStrings.clear();
910   aStrings << tr("PREF_TRACE_TYPE_0");
911   aStrings << tr("PREF_TRACE_TYPE_1");
912   aStrings << tr("PREF_TRACE_TYPE_2");
913   setPreferenceProperty( aTraceType, "strings", aStrings );
914   setPreferenceProperty( aTraceType, "indexes", aIndices );
915 }
916
917 /*!
918   \brief. Show ParaView python trace.
919 */
920 void PVGUI_Module::onShowTrace()
921 {
922   if (!myTraceWindow) {
923     myTraceWindow = new pqPythonScriptEditor(getApp()->desktop());
924   }
925   myTraceWindow->setText(getTraceString());
926   myTraceWindow->show();
927   myTraceWindow->raise();
928   myTraceWindow->activateWindow();
929 }
930
931
932 /*!
933   \brief. Re-initialize ParaView python trace.
934 */
935 void PVGUI_Module::onRestartTrace()
936 {
937   stopTrace();
938   startTrace();
939 }
940
941 /*!
942   \brief Called when view manager is added
943 */
944 void PVGUI_Module::onViewManagerAdded( SUIT_ViewManager* vm )
945 {
946   if ( PVViewer_ViewManager* pvvm = dynamic_cast<PVViewer_ViewManager*>( vm ) ) {
947     connect( pvvm, SIGNAL( viewCreated( SUIT_ViewWindow* ) ), 
948              this, SLOT( onPVViewCreated( SUIT_ViewWindow* ) ) );
949     connect( pvvm, SIGNAL( deleteView( SUIT_ViewWindow* ) ),
950              this,  SLOT( onPVViewDelete( SUIT_ViewWindow* ) ) );
951   }
952 }
953
954 /*!
955   \brief Called when view manager is removed
956 */
957 void PVGUI_Module::onViewManagerRemoved( SUIT_ViewManager* vm )
958 {
959   if ( PVViewer_ViewManager* pvvm = dynamic_cast<PVViewer_ViewManager*>( vm ) )
960     disconnect( pvvm, SIGNAL( viewCreated( SUIT_ViewWindow* ) ),
961                 this, SLOT( onPVViewCreated( SUIT_ViewWindow* ) ) );
962 }
963
964 /*!
965   \brief Show toolbars at \a vw PV view window creating when PARAVIS is active.
966 */
967 void PVGUI_Module::onPVViewCreated( SUIT_ViewWindow* vw )
968 {
969   myGuiElements->setToolBarVisible( true );
970   restoreDockWidgetsState();
971 }
972
973 /*!
974   \brief Save toolbars state at \a view view closing.
975 */
976 void PVGUI_Module::onPVViewDelete( SUIT_ViewWindow* view )
977 {
978   if ( dynamic_cast<PVViewer_ViewWindow*>( view ) )
979     saveDockWidgetsState( false );
980 }
981
982 /*!
983   \fn CAM_Module* createModule();
984   \brief Export module instance (factory function).
985   \return new created instance of the module
986 */
987
988 #ifdef WNT
989 #define PVGUI_EXPORT __declspec(dllexport)
990 #else   // WNT
991 #define PVGUI_EXPORT
992 #endif  // WNT
993
994 extern "C" {
995
996   bool flag = false;
997   PVGUI_EXPORT CAM_Module* createModule() {
998     return new PVGUI_Module();
999   }
1000   
1001   PVGUI_EXPORT char* getModuleVersion() {
1002     return (char*)PARAVIS_VERSION_STR;
1003   }
1004 }