Salome HOME
0022847: [CEA 1408] Regression : in 7.5.1rc1 switching to Paravis to some other modul...
[modules/paravis.git] / src / PVGUI / PVGUI_Module.cxx
1 // PARAVIS : ParaView wrapper SALOME module
2 //
3 // Copyright (C) 2010-2014  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 #include "PVGUI_Module.h"
31
32 //#ifdef PARAVIS_WITH_FULL_CORBA
33 //# include "PARAVIS_Gen_i.hh"
34 //#endif
35
36 #include CORBA_SERVER_HEADER(SALOME_ModuleCatalog)
37 #include CORBA_SERVER_HEADER(SALOMEDS)
38
39 #include "PVViewer_ViewManager.h"
40 #include "PVViewer_ViewWindow.h"
41 #include "PVViewer_ViewModel.h"
42 #include "PVGUI_Tools.h"
43 #include "PVGUI_ParaViewSettingsPane.h"
44 #include "PVViewer_GUIElements.h"
45 #include "PVViewer_EngineWrapper.h"
46 #include "PVGUI_DataModel.h"
47
48 // SALOME Includes
49 #include <utilities.h>
50 #include <SUIT_DataBrowser.h>
51 #include <SUIT_Desktop.h>
52 #include <SUIT_MessageBox.h>
53 #include <SUIT_ResourceMgr.h>
54 #include <SUIT_Session.h>
55 #include <SUIT_OverrideCursor.h>
56 #include <SUIT_ExceptionHandler.h>
57
58 #include <SALOME_LifeCycleCORBA.hxx>
59 #include <SALOMEDS_SObject.hxx>
60
61 #include <LightApp_SelectionMgr.h>
62 #include <LightApp_NameDlg.h>
63 #include <LightApp_Application.h>
64 #include <SalomeApp_Application.h>  // should ultimately be a LightApp only
65 #include <SalomeApp_Study.h>
66 #include <SALOME_ListIO.hxx>
67 #include <SALOMEDS_Tool.hxx>
68 #include <Utils_ORB_INIT.hxx>
69 #include <Utils_SINGLETON.hxx>
70
71 #include <QtxActionMenuMgr.h>
72 #include <QtxActionToolMgr.h>
73
74 #include <PARAVIS_version.h>
75
76 // External includes
77 #include <sstream>
78
79 #include <QAction>
80 #include <QApplication>
81 #include <QCursor>
82 #include <QDir>
83 #include <QFile>
84 #include <QFileInfo>
85 #include <QIcon>
86 #include <QInputDialog>
87 #include <QMenu>
88 #include <QStatusBar>
89 #include <QString>
90 #include <QStringList>
91 #include <QTimer>
92 #include <QToolBar>
93 #include <QTextStream>
94 #include <QShortcut>
95 #include <QDockWidget>
96 #include <QHelpEngine>
97
98 // Paraview includes
99 #include <vtkPVConfig.h>  // for symbol PARAVIEW_VERSION
100 #include <vtkProcessModule.h>
101 #include <vtkPVSession.h>
102 #include <vtkPVProgressHandler.h>
103 #include <vtkOutputWindow.h>
104 #include <vtkEventQtSlotConnect.h>
105 #include <vtkNew.h>
106 #include <vtkSMProxy.h>
107 #include <vtkSmartPointer.h>
108 #include <vtkSMSession.h>
109 #include <vtkSMTrace.h>
110 #include <vtkSMSessionProxyManager.h>
111 #include <vtkSMParaViewPipelineController.h>
112
113 #include <pqApplicationCore.h>
114 #include <pqPVApplicationCore.h>
115 #include <pqActiveView.h>
116 #include <pqObjectBuilder.h>
117 #include <pqOptions.h>
118 #include <pqSettings.h>
119 #include <pqServer.h>
120 #include <pqUndoStack.h>
121 #include <pqTabbedMultiViewWidget.h>
122 #include <pqActiveObjects.h>
123 #include <pqHelpReaction.h>
124 #include <pqPluginManager.h>
125 #include <pqPythonDialog.h>
126 #include <pqPythonManager.h>
127 #include <pqLoadDataReaction.h>
128 #include <pqPythonScriptEditor.h>
129 #include <pqDataRepresentation.h>
130 #include <pqDisplayColorWidget.h>
131 #include <pqColorToolbar.h>
132 #include <pqScalarBarVisibilityReaction.h>
133 #include <pqServerResource.h>
134 #include <pqServerConnectReaction.h>
135 #include <pqPluginManager.h>
136 #include <pqVCRToolbar.h>
137 #include <pqAnimationScene.h>
138 #include <pqServerManagerModel.h>
139 #include <pqAnimationTimeToolbar.h>
140
141 //#include <PVViewer_EngineWrapper.h>
142
143
144 //----------------------------------------------------------------------------
145 PVGUI_Module* ParavisModule = 0;
146 PVSERVER_ORB::PVSERVER_Gen_var PVGUI_Module::MyEngine;
147
148 /*!
149   \mainpage
150   TODO TODO update this:
151
152   <h2>Building and installing PARAVIS</h2>
153   As any other SALOME module, PARAVIS requires PARAVIS_ROOT_DIR environment variable to be set to PARAVIS
154   installation directory.
155   Other variables needed for correct detection of ParaView location:
156   \li PVHOME - points at the ParaView installation directory tree
157   \li PVVERSION - number of ParaView version
158
159   It also requires common SALOME environment including GUI_ROOT_DIR and other prerequsites.
160
161
162   PARAVIS module can be launched using the following commands:
163   \li Full SALOME configuration
164   \code
165   runSalome --modules="PARAVIS"
166   \endcode
167
168   <h2>ParaView GUI integration</h2>
169   <h3>ParaView GUI integration overview</h3>
170
171   The main idea is to reuse ParaView GUI internal logic as much as possible, providing a layer 
172   between it and SALOME GUI that hides the following SALOME GUI implementation details from ParaView:
173
174   \li SALOME GUI executable and Qt event loop
175   \li SALOME GUI desktop
176   \li Dock windows areas
177   \li SALOME menu and toolbar managers
178
179   Major part of the integration is implemented in PVGUI_Module class.
180
181   <h3>ParaView client initalization</h3>
182
183   ParaView client initalization is performed when an instance of PVGUI_Module class has been created 
184   and \link PVGUI_Module::initialize() PVGUI_Module::initialize()\endlink method is called by SALOME GUI.
185   The actual client start-up is done in \link PVGUI_Module::pvInit() PVGUI_Module::pvInit()\endlink method. 
186   
187
188   <h3>Multi-view manager</h3>
189
190   SALOME GUI requires that each kind of view be implemnted with help of (at least) three classes. For ParaView multi-view manager 
191   these are:
192
193   \li PVGUI_ViewManager - view manager class
194   \li PVGUI_Viewer      - view model class
195   \li PVGUI_ViewWindow  - view window class that acts as a parent for %pqViewManager
196
197   Single instances of PVGUI_ViewManager and PVGUI_ViewWindow classes are created by \link PVGUI_Module::showView() 
198   PVGUI_Module::showView()\endlink method upon the first PARAVIS module activation. The same method hides the multi-view manager 
199   when the module is deactivated (the user switches to another module or a study is closed). 
200   A special trick is used to make PVGUI_ViewWindow the parent of %pqViewManager widget. It is created initally by %pqMainWindowCore
201   with the desktop as a parent, so when it is shown PVGUI_ViewWindow instance is passed to its setParent() method. In  
202   \link PVGUI_ViewWindow::~PVGUI_ViewWindow() PVGUI_ViewWindow::~PVGUI_ViewWindow()\endlink the parent is nullified to avoid deletion
203   of %pqViewManager widget that would break %pqMainWindowCore class.
204
205   <h3>ParaView plugins</h3>
206   ParaView server and client plugins are managed by %pqMainWindowCore slots that has full access to PARAVIS menus and toolbars. 
207   As a result they appears automatically in PARAVIS menus and toolbars if loaded successfully.
208 */
209
210 /*!
211   \class PVGUI_Module
212   \brief Implementation 
213          SALOME module wrapping ParaView GUI.
214 */
215
216 _PTR(SComponent)
217 ClientFindOrCreateParavisComponent(_PTR(Study) theStudyDocument)
218 {
219   _PTR(SComponent) aSComponent = theStudyDocument->FindComponent("PVSERVER");
220   if (!aSComponent) {
221     _PTR(StudyBuilder) aStudyBuilder = theStudyDocument->NewBuilder();
222     aStudyBuilder->NewCommand();
223     int aLocked = theStudyDocument->GetProperties()->IsLocked();
224     if (aLocked) theStudyDocument->GetProperties()->SetLocked(false);
225     aSComponent = aStudyBuilder->NewComponent("PVSERVER");
226     _PTR(GenericAttribute) anAttr =
227       aStudyBuilder->FindOrCreateAttribute(aSComponent, "AttributeName");
228     _PTR(AttributeName) aName (anAttr);
229
230     ORB_INIT& init = *SINGLETON_<ORB_INIT>::Instance();
231     CORBA::ORB_var anORB = init( qApp->argc(), qApp->argv() );
232
233     SALOME_NamingService *NamingService = new SALOME_NamingService( anORB );
234     CORBA::Object_var objVarN = NamingService->Resolve("/Kernel/ModulCatalog");
235     SALOME_ModuleCatalog::ModuleCatalog_var Catalogue =
236       SALOME_ModuleCatalog::ModuleCatalog::_narrow(objVarN);
237     SALOME_ModuleCatalog::Acomponent_var Comp = Catalogue->GetComponent( "PVSERVER" );
238     if (!Comp->_is_nil()) {
239       aName->SetValue(Comp->componentusername());
240     }
241
242     anAttr = aStudyBuilder->FindOrCreateAttribute(aSComponent, "AttributePixMap");
243     _PTR(AttributePixMap) aPixmap (anAttr);
244     aPixmap->SetPixMap( "pqAppIcon16.png" );
245
246     // Create Attribute parameters for future using
247     anAttr = aStudyBuilder->FindOrCreateAttribute(aSComponent, "AttributeParameter");
248
249     aStudyBuilder->DefineComponentInstance(aSComponent, PVGUI_Module::GetCPPEngine()->GetIOR());
250     if (aLocked) theStudyDocument->GetProperties()->SetLocked(true);
251     aStudyBuilder->CommitCommand();
252   }
253   return aSComponent;
254 }
255
256 /*!
257   Clean up function; used to stop ParaView progress events when
258   exception is caught by global exception handler.
259 */
260 void paravisCleanUp()
261 {
262   if ( pqApplicationCore::instance() ) {
263     pqServer* s = pqApplicationCore::instance()->getActiveServer();
264     if ( s ) s->session()->GetProgressHandler()->CleanupPendingProgress();
265   }
266 }
267
268 /*!
269   \brief Constructor. Sets the default name for the module.
270 */
271 PVGUI_Module::PVGUI_Module()
272     : SalomeApp_Module( PARAVIS_MODULE_NAME ),
273     mySelectionControlsTb( -1 ),
274     mySourcesMenuId( -1 ),
275     myFiltersMenuId( -1 ),
276     myMacrosMenuId(-1),
277     myToolbarsMenuId(-1),
278     myRecentMenuId(-1),
279     myOldMsgHandler(0),
280     myTraceWindow(0),
281     myStateCounter(0),
282     myInitTimer(0),
283     myPushTraceTimer(0),
284     myGuiElements(0)
285 {
286 #ifdef HAS_PV_DOC
287   Q_INIT_RESOURCE( PVGUI );
288 #endif
289   ParavisModule = this;
290
291   // Clear old copies of embedded macros files
292   QString aDestPath = QString( "%1/.config/%2/Macros" ).arg( QDir::homePath() ).arg( QApplication::applicationName() );
293   QStringList aFilter;
294   aFilter << "*.py";
295
296   QDir aDestDir(aDestPath);
297   QStringList aDestFiles = aDestDir.entryList(aFilter, QDir::Files);
298   foreach (QString aMacrosPath, getEmbeddedMacrosList()) {
299     QString aMacrosName = QFileInfo(aMacrosPath).fileName();
300     if (aDestFiles.contains(aMacrosName)) {
301       aDestDir.remove(aMacrosName);
302     }
303   }
304 }
305
306 /*!
307   \brief Destructor.
308 */
309 PVGUI_Module::~PVGUI_Module()
310 {
311   if (myPushTraceTimer)
312     delete myPushTraceTimer;
313   if (myInitTimer)
314     delete myInitTimer;
315 }
316
317 PVViewer_EngineWrapper * PVGUI_Module::GetEngine()
318 {
319   return PVViewer_EngineWrapper::GetInstance();
320 }
321
322 PVSERVER_ORB::PVSERVER_Gen_var PVGUI_Module::GetCPPEngine()
323 {
324   // initialize PARAVIS module engine (load, if necessary)
325   if ( CORBA::is_nil( MyEngine ) ) {
326       Engines::EngineComponent_var comp =
327           SalomeApp_Application::lcc()->FindOrLoad_Component( "FactoryServer", "PVSERVER" );
328       MyEngine = PVSERVER_ORB::PVSERVER_Gen::_narrow( comp );
329  }
330   return MyEngine;
331 }
332
333 /*!
334   \brief Create data model.
335   \return module specific data model
336 */
337 CAM_DataModel* PVGUI_Module::createDataModel()
338 {
339   return new PVGUI_DataModel( this );
340 }
341
342 pqPVApplicationCore * PVGUI_Module::GetPVApplication()
343 {
344   return PVViewer_ViewManager::GetPVApplication();
345 }
346
347 /*!
348   \brief Initialize module. Creates menus, prepares context menu, etc.
349   \param app SALOME GUI application instance
350 */
351 void PVGUI_Module::initialize( CAM_Application* app )
352 {
353   LightApp_Module::initialize( app );
354
355   createActions();
356   createMenus();
357
358   // Uncomment to debug ParaView initialization
359   // "aa" used instead of "i" as GDB doesn't like "i" variables :)
360   /*
361   int aa = 1;
362   while( aa ){
363     aa = aa;
364   }
365   */
366
367   LightApp_Application* anApp = getApp();
368   SUIT_Desktop* aDesktop = anApp->desktop();
369
370   // Remember current state of desktop toolbars
371   QList<QToolBar*> foreignToolbars = aDesktop->findChildren<QToolBar*>();
372
373   // Initialize ParaView client and associated behaviors
374   // and connect to externally launched pvserver
375   PVViewer_ViewManager::ParaviewInitApp(aDesktop, anApp->logWindow());
376   myGuiElements = PVViewer_GUIElements::GetInstance(aDesktop);
377
378   // [ABN]: careful with the order of the GUI element creation, the loading of the configuration
379   // and the connection to the server. This order is very sensitive if one wants to make
380   // sure all menus, etc ... are correctly populated.
381   // Reference points are: ParaViewMainWindow.cxx and branded_paraview_initializer.cxx.in
382   setupDockWidgets();
383
384   pvCreateActions();
385   pvCreateMenus();
386   pvCreateToolBars();
387
388   PVViewer_ViewManager::ParaviewInitBehaviors(true, aDesktop);
389
390   QList<QDockWidget*> activeDocks = aDesktop->findChildren<QDockWidget*>();
391   QList<QMenu*> activeMenus = aDesktop->findChildren<QMenu*>();
392
393   // Setup quick-launch shortcuts.
394   QShortcut *ctrlSpace = new QShortcut(Qt::CTRL + Qt::Key_Space, aDesktop);
395   QObject::connect(ctrlSpace, SIGNAL(activated()),
396     pqApplicationCore::instance(), SLOT(quickLaunch()));
397
398   // Find Plugin Dock Widgets
399   QList<QDockWidget*> currentDocks = aDesktop->findChildren<QDockWidget*>();
400   QList<QDockWidget*>::iterator i;
401   for (i = currentDocks.begin(); i != currentDocks.end(); ++i) {
402     if(!activeDocks.contains(*i)) {
403       myDockWidgets[*i] = false; // hidden by default
404       (*i)->hide();
405     }
406   }
407
408     // Find Plugin Menus
409     // [ABN] TODO: fix this - triggers a SEGFAULT at deactivation() time.
410 //    QList<QMenu*> currentMenus = aDesktop->findChildren<QMenu*>();
411 //    QList<QMenu*>::iterator im;
412 //    for (im = currentMenus.begin(); im != currentMenus.end(); ++im) {
413 //      if(!activeMenus.contains(*im)) {
414 //          QString s = (*im)->title();
415 //          std::cout << " MENU "<<  s.toStdString() << std::endl;
416 //          myMenus.append(*im);
417 //      }
418 //    }
419
420   // Connect after toolbar creation, etc ... as some activations of the toolbars is triggered
421   // by the ServerConnection event:
422   PVViewer_ViewManager::ParaviewLoadConfigurations(true);
423   PVViewer_ViewManager::ConnectToExternalPVServer(aDesktop);
424   updateObjBrowser();
425
426   // Find created toolbars
427   QCoreApplication::processEvents();
428
429   // process PVViewer toolbars (might be added by PVViewer created BEFORE activating ParaVis)
430   QList<QToolBar*> pvToolbars = myGuiElements->getToolbars();
431   foreach(QToolBar* aBar, pvToolbars) {
432     if (!myToolbars.contains(aBar)) {
433       myToolbars[aBar] = true;
434       myToolbarBreaks[aBar] = false;
435       aBar->setVisible(false);
436       aBar->toggleViewAction()->setVisible(false);
437     }
438   }
439
440   // process other toolbars (possibly added by Paraview)
441   QList<QToolBar*> allToolbars = aDesktop->findChildren<QToolBar*>();
442   foreach(QToolBar* aBar, allToolbars) {
443     if (!foreignToolbars.contains(aBar) && !myToolbars.contains(aBar)) {
444       myToolbars[aBar] = true;
445       myToolbarBreaks[aBar] = false;
446       aBar->setVisible(false);
447       aBar->toggleViewAction()->setVisible(false);
448     }
449   }
450
451   updateMacros();
452  
453   SUIT_ResourceMgr* aResourceMgr = SUIT_Session::session()->resourceMgr();
454   bool isStop = aResourceMgr->booleanValue( PARAVIS_MODULE_NAME, "stop_trace", false );
455   if(!isStop)
456     {
457       // Start a timer to schedule asap:
458       //  - the trace start
459       myInitTimer = new QTimer(aDesktop);
460       QObject::connect(myInitTimer, SIGNAL(timeout()), this, SLOT(onInitTimer()) );
461       myInitTimer->setSingleShot(true);
462       myInitTimer->start(0);
463
464       // Another timer to regularly push the trace onto the engine:
465       myPushTraceTimer = new QTimer(aDesktop);
466       QObject::connect(myPushTraceTimer, SIGNAL(timeout()), this, SLOT(onPushTraceTimer()) );
467       myPushTraceTimer->setSingleShot(false);
468       myPushTraceTimer->start(500);
469     }
470
471   this->VTKConnect = vtkEventQtSlotConnect::New();
472   
473   vtkProcessModule* pm = vtkProcessModule::GetProcessModule();
474   if(pm) {
475     vtkPVSession* pvs = dynamic_cast<vtkPVSession*>(pm->GetSession());
476     if(pvs) {
477       vtkPVProgressHandler* ph = pvs->GetProgressHandler();
478       if(ph) {
479           this->VTKConnect->Connect(ph, vtkCommand::StartEvent,
480                                     this, SLOT(onStartProgress()));
481           this->VTKConnect->Connect(ph, vtkCommand::EndEvent,
482                                     this, SLOT(onEndProgress()));
483       }
484     }
485   }
486   fixAnimationScene();
487
488 }
489
490 /**
491  * Little trick to force the proper update of the timesteps/time range when the module is initialized.
492  * This is otherwise not properly working when PARAVIS is activated after a PVViewer has already been
493  * instanciated.
494  */
495 void PVGUI_Module::fixAnimationScene()
496 {
497   pqServer* server = pqActiveObjects::instance().activeServer();
498   pqApplicationCore * app = pqApplicationCore::instance();
499   pqPipelineSource * src = app->getObjectBuilder()->createSource(QString("sources"), QString("TimeSource"),server);
500   app->getObjectBuilder()->destroy(src);
501 }
502
503 void PVGUI_Module::onStartProgress()
504 {
505   QApplication::setOverrideCursor(Qt::WaitCursor);
506 }
507
508 void PVGUI_Module::onEndProgress()
509 {
510   QApplication::restoreOverrideCursor();
511 }
512
513 void PVGUI_Module::onDataRepresentationUpdated() {
514   SalomeApp_Study* activeStudy = dynamic_cast<SalomeApp_Study*>(application()->activeStudy());
515   if(!activeStudy) return;
516   
517   activeStudy->Modified();
518 }
519
520 /*!
521   \brief Initialisation timer event - trace start up
522 */
523 void PVGUI_Module::onInitTimer()
524 {
525   startTrace();
526 }
527   
528 /*!
529   \brief Get list of embedded macros files
530 */
531 QStringList PVGUI_Module::getEmbeddedMacrosList()
532 {
533   QString aRootDir = getenv("PARAVIS_ROOT_DIR");
534
535   QString aSourcePath = aRootDir + "/bin/salome/Macro";
536
537   QStringList aFilter;
538   aFilter << "*.py";
539
540   QDir aSourceDir(aSourcePath);
541   QStringList aSourceFiles = aSourceDir.entryList(aFilter, QDir::Files);
542   QStringList aFullPathSourceFiles;
543   foreach (QString aMacrosName, aSourceFiles) {
544     aFullPathSourceFiles << aSourceDir.absoluteFilePath(aMacrosName);
545   }
546   return aFullPathSourceFiles;
547 }
548
549 void PVGUI_Module::updateMacros()
550 {
551   pqPythonManager* aPythonManager = pqPVApplicationCore::instance()->pythonManager();
552   if(!aPythonManager)  {
553     return;
554   }
555   
556   foreach (QString aStr, getEmbeddedMacrosList()) {
557     aPythonManager->addMacro(aStr);
558   }
559 }
560
561
562 /*!
563   \brief Get list of compliant dockable GUI elements
564   \param m map to be filled in ("type":"default_position")
565 */
566 void PVGUI_Module::windows( QMap<int, int>& m ) const
567 {
568   m.insert( LightApp_Application::WT_ObjectBrowser, Qt::LeftDockWidgetArea );
569   m.insert( LightApp_Application::WT_PyConsole, Qt::BottomDockWidgetArea );
570   // ParaView diagnostic output redirected here
571   m.insert( LightApp_Application::WT_LogWindow, Qt::BottomDockWidgetArea );
572 }
573
574 /*!
575   \brief Shows (toShow = true) or hides ParaView view window
576 */
577 void PVGUI_Module::showView( bool toShow )
578 {
579   LightApp_Application* anApp = getApp();
580   PVViewer_ViewManager* viewMgr =
581     dynamic_cast<PVViewer_ViewManager*>( anApp->getViewManager( PVViewer_Viewer::Type(), false ) );
582   if ( !viewMgr ) {
583     viewMgr = new PVViewer_ViewManager( anApp->activeStudy(), anApp->desktop(), anApp->logWindow() );
584     anApp->addViewManager( viewMgr );
585     connect( viewMgr, SIGNAL( lastViewClosed( SUIT_ViewManager* ) ),
586              anApp, SLOT( onCloseView( SUIT_ViewManager* ) ) );
587   }
588
589   PVViewer_ViewWindow* pvWnd = dynamic_cast<PVViewer_ViewWindow*>( viewMgr->getActiveView() );
590   if ( !pvWnd ) {
591     pvWnd = dynamic_cast<PVViewer_ViewWindow*>( viewMgr->createViewWindow() );
592     // this also connects to the pvserver and instantiates relevant PV behaviors
593   }
594
595   pvWnd->setShown( toShow );
596   if ( toShow ) pvWnd->setFocus();
597 }
598
599 /*!
600   \brief Slot to show help for proxy.
601 */
602 void PVGUI_Module::showHelpForProxy( const QString& groupname, const QString& proxyname )
603 {
604   pqHelpReaction::showProxyHelp(groupname, proxyname);
605 }
606
607
608 /*!
609   \brief Slot to show the waiting state.
610 */
611 void PVGUI_Module::onPreAccept()
612 {
613   getApp()->desktop()->statusBar()->showMessage(tr("STB_PREACCEPT"));
614   QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
615 }
616
617 /*!
618   \brief Slot to show the ready state.
619 */
620 void PVGUI_Module::onPostAccept()
621 {
622   getApp()->desktop()->statusBar()->showMessage(tr("STB_POSTACCEPT"), 2000);
623   QTimer::singleShot(0, this, SLOT(endWaitCursor()));
624 }
625
626 /*!
627   \brief Slot to switch off wait cursor.
628 */
629 void PVGUI_Module::endWaitCursor()
630 {
631   QApplication::restoreOverrideCursor();
632 }
633
634 static void ParavisMessageOutput(QtMsgType type, const char *msg)
635 {
636   switch(type)
637     {
638   case QtDebugMsg:
639     vtkOutputWindow::GetInstance()->DisplayText(msg);
640     break;
641   case QtWarningMsg:
642     vtkOutputWindow::GetInstance()->DisplayErrorText(msg);
643     break;
644   case QtCriticalMsg:
645     vtkOutputWindow::GetInstance()->DisplayErrorText(msg);
646     break;
647   case QtFatalMsg:
648     vtkOutputWindow::GetInstance()->DisplayErrorText(msg);
649     break;
650     }
651 }
652
653 /*!
654   \brief Activate module.
655   \param study current study
656   \return \c true if activaion is done successfully or 0 to prevent
657   activation on error
658 */
659 bool PVGUI_Module::activateModule( SUIT_Study* study )
660 {
661   myOldMsgHandler = qInstallMsgHandler(ParavisMessageOutput);
662   
663   SUIT_ExceptionHandler::addCleanUpRoutine( paravisCleanUp );
664
665   storeCommonWindowsState();
666
667   bool isDone = LightApp_Module::activateModule( study );
668   if ( !isDone ) return false;
669
670   showView( true );
671   if ( mySourcesMenuId != -1 ) menuMgr()->show(mySourcesMenuId);
672   if ( myFiltersMenuId != -1 ) menuMgr()->show(myFiltersMenuId);
673   if ( myMacrosMenuId != -1 ) menuMgr()->show(myMacrosMenuId);
674   if ( myToolbarsMenuId != -1 ) menuMgr()->show(myToolbarsMenuId);
675
676   // Update the various menus with the content pre-loaded in myGuiElements
677 //  QMenu* srcMenu = menuMgr()->findMenu( mySourcesMenuId );
678 //  myGuiElements->updateSourcesMenu(srcMenu);
679 //  QMenu* filtMenu = menuMgr()->findMenu( myFiltersMenuId );
680 //  myGuiElements->updateFiltersMenu(filtMenu);
681 //  QMenu* macMenu = menuMgr()->findMenu( myMacrosMenuId );
682 //  myGuiElements->updateMacrosMenu(macMenu);
683
684   setMenuShown( true );
685   setToolShown( true );
686
687   restoreDockWidgetsState();
688
689   QMenu* aMenu = menuMgr()->findMenu( myRecentMenuId );
690   if(aMenu) {
691     QList<QAction*> anActns = aMenu->actions();
692     for (int i = 0; i < anActns.size(); ++i) {
693       QAction* a = anActns.at(i);
694       if(a)
695         a->setVisible(true);
696     }
697   }
698
699   QList<QMenu*>::iterator it;
700   for (it = myMenus.begin(); it != myMenus.end(); ++it) {
701     QAction* a = (*it)->menuAction();
702     if(a)
703       a->setVisible(true);
704   }
705
706   if ( myRecentMenuId != -1 ) menuMgr()->show(myRecentMenuId);
707
708   ClientFindOrCreateParavisComponent(PARAVIS::GetCStudy(this));
709
710   return isDone;
711 }
712
713
714 /*!
715   \brief Deactivate module.
716   \param study current study
717   \return \c true if deactivaion is done successfully or 0 to prevent
718   deactivation on error
719 */
720 bool PVGUI_Module::deactivateModule( SUIT_Study* study )
721 {
722   MESSAGE("PARAVIS deactivation ...")
723
724   QMenu* aMenu = menuMgr()->findMenu( myRecentMenuId );
725   if(aMenu) {
726     QList<QAction*> anActns = aMenu->actions();
727     for (int i = 0; i < anActns.size(); ++i) {
728       QAction* a = anActns.at(i);
729       if(a)
730         a->setVisible(false);
731     }
732   }
733
734   QList<QMenu*>::iterator it;
735   for (it = myMenus.begin(); it != myMenus.end(); ++it) {
736     QAction* a = (*it)->menuAction();
737     if(a)
738       a->setVisible(false);
739   }
740
741   QList<QDockWidget*> aStreamingViews = application()->desktop()->findChildren<QDockWidget*>("pqStreamingControls");
742   foreach(QDockWidget* aView, aStreamingViews) {
743     if (!myDockWidgets.contains(aView))
744       myDockWidgets[aView] = aView->isVisible();
745   }
746
747   /*if (pqImplementation::helpWindow) {
748     pqImplementation::helpWindow->hide();
749     }*/
750   showView( false );
751   // hide menus
752   menuMgr()->hide(myRecentMenuId);
753   menuMgr()->hide(mySourcesMenuId);
754   menuMgr()->hide(myFiltersMenuId);
755   menuMgr()->hide(myMacrosMenuId);
756   menuMgr()->hide(myToolbarsMenuId);
757   setMenuShown( false );
758   setToolShown( false );
759
760   saveDockWidgetsState();
761
762   SUIT_ExceptionHandler::removeCleanUpRoutine( paravisCleanUp );
763
764   if (myOldMsgHandler)
765     qInstallMsgHandler(myOldMsgHandler);
766
767   restoreCommonWindowsState();
768   
769   return LightApp_Module::deactivateModule( study );
770 }
771
772
773 /*!
774   \brief Called when application is closed.
775
776   Process finalize application functionality from ParaView in order to save server settings
777   and nullify application pointer if the application is being closed.
778
779   \param theApp application
780 */
781 void PVGUI_Module::onApplicationClosed( SUIT_Application* theApp )
782 {
783   PVViewer_ViewManager::ParaviewCleanup();
784
785   int aAppsNb = SUIT_Session::session()->applications().size();
786   if (aAppsNb == 1) {
787     deleteTemporaryFiles();
788   }
789   CAM_Module::onApplicationClosed(theApp);
790 }
791
792
793 /*!
794   \brief Deletes temporary files created during import operation from VISU
795 */
796 void PVGUI_Module::deleteTemporaryFiles()
797 {
798   foreach(QString aFile, myTemporaryFiles) {
799     if (QFile::exists(aFile)) {
800       QFile::remove(aFile);
801     }
802   }
803 }
804
805
806 /*!
807   \brief Called when study is closed.
808
809   Removes data model from the \a study.
810
811   \param study study being closed
812 */
813 void PVGUI_Module::studyClosed(SUIT_Study* study)
814 {
815   clearParaviewState();
816
817   LightApp_Module::studyClosed(study);
818 }
819
820 /*!
821   \brief Called when study is opened.
822 */
823 void PVGUI_Module::onModelOpened()
824 {
825   _PTR(Study) studyDS = PARAVIS::GetCStudy(this);
826   if(!studyDS) {
827     return;
828   }
829
830   _PTR(SComponent) paravisComp =
831     studyDS->FindComponent(PARAVIS_MODULE_NAME);
832   if(!paravisComp) {
833     return;
834   }
835
836   _PTR(ChildIterator) anIter(studyDS->NewChildIterator(paravisComp));
837   for (; anIter->More(); anIter->Next()) {
838     _PTR(SObject) aSObj = anIter->Value();
839     _PTR(GenericAttribute) anAttr;
840     if (!aSObj->FindAttribute(anAttr, "AttributeLocalID")) {
841       continue;
842     }
843     _PTR(AttributeLocalID) anID(anAttr);
844     if (anID->Value() == PVSTATEID) {
845       myStateCounter++;
846     }
847   }
848 }
849
850 /*!
851 \brief Returns IOR of current engine
852 */
853 QString PVGUI_Module::engineIOR() const
854 {
855   CORBA::String_var anIOR = GetCPPEngine()->GetIOR();
856   return QString(anIOR.in());
857 }
858
859 /*!
860   \brief Open file of format supported by ParaView
861 */
862 void PVGUI_Module::openFile(const char* theName)
863 {
864   QStringList aFiles;
865   aFiles<<theName;
866   pqLoadDataReaction::loadData(aFiles);
867 }
868
869 /**!
870  * Start trace invoking the newly introduced C++ API (PV 4.2)
871  * (inspired from pqTraceReaction::start())
872  */
873 void PVGUI_Module::startTrace()
874 {
875   vtkSMSessionProxyManager* pxm = pqActiveObjects::instance().activeServer()->proxyManager();
876
877   vtkSmartPointer<vtkSMProxy> proxy;
878   proxy.TakeReference(pxm->NewProxy("pythontracing", "PythonTraceOptions"));
879   if (proxy)
880     {
881       vtkNew<vtkSMParaViewPipelineController> controller;
882       controller->InitializeProxy(proxy);
883     }
884   vtkSMTrace* trace = vtkSMTrace::StartTrace();
885   if (proxy)
886     {
887       // Set manually the properties entered via the dialog box poping-up when requiring
888       // a trace start in PV4.2 (trace options)
889       trace->SetPropertiesToTraceOnCreate(vtkSMTrace::RECORD_USER_MODIFIED_PROPERTIES);
890       trace->SetFullyTraceSupplementalProxies(false);
891     }
892 }
893
894 void PVGUI_Module::stopTrace()
895 {
896   vtkSMTrace::StopTrace();
897 }
898
899 void PVGUI_Module::executeScript(const char *script)
900 {
901 #ifndef WNT
902   pqPythonManager* manager = qobject_cast<pqPythonManager*>(
903                              pqApplicationCore::instance()->manager("PYTHON_MANAGER"));
904   if (manager)  {
905     pqPythonDialog* pyDiag = manager->pythonShellDialog();
906     if (pyDiag) {
907       pyDiag->runString(script);  
908       }
909     }
910 #endif
911 }
912
913 ///**
914 // *  Debug function printing out the given interpreter's execution context
915 // */
916 //void printInterpContext(PyInterp_Interp * interp )
917 //{
918 //  // Extract __smtraceString from interpreter's context
919 //  const PyObject* ctxt = interp->getExecutionContext();
920 //
921 //  PyObject* lst = PyDict_Keys((PyObject *)ctxt);
922 //  Py_ssize_t siz = PyList_GET_SIZE(lst);
923 //  for (Py_ssize_t i = 0; i < siz; i++)
924 //    {
925 //      PyObject * elem = PyList_GetItem(lst, i);
926 //      if (PyString_Check(elem))
927 //        {
928 //          std::cout << "At pos:" << i << ", " << PyString_AsString(elem) << std::endl;
929 //        }
930 //      else
931 //        std::cout << "At pos:" << i << ", not a string!" << std::endl;
932 //    }
933 //  Py_XDECREF(lst);
934 //}
935
936 /*!
937   \brief Returns trace string
938 */
939 static const QString MYReplaceStr("paraview.simple");
940 QString PVGUI_Module::getTraceString()
941 {
942   vtkSMTrace *tracer = vtkSMTrace::GetActiveTracer();
943   if (!tracer) // trace is not started
944     return QString("");
945
946   QString traceString(tracer->GetCurrentTrace());
947   std::stringstream nl; nl << std::endl; // surely there is some Qt trick to do that in a portable way??
948   QString end_line(nl.str().c_str());
949   // 'import pvsimple' is necessary to fix the first call to DisableFirstRenderCamera in the paraview trace
950   // 'ShowParaviewView()' ensure there is an opened viewing window (otherwise SEGFAULT!)
951   traceString = "import pvsimple" + end_line +
952                 "pvsimple.ShowParaviewView()" + end_line + traceString;
953
954   // Replace import "paraview.simple" by "pvsimple"
955   if ((!traceString.isNull()) && traceString.length() != 0) {
956     int aPos = traceString.indexOf(MYReplaceStr);
957     while (aPos != -1) {
958       traceString = traceString.replace(aPos, MYReplaceStr.length(), "pvsimple");
959       aPos = traceString.indexOf(MYReplaceStr, aPos);
960     }
961   }
962
963   return traceString;
964 }
965
966 /*!
967   \brief Saves trace string to disk file
968 */
969 void PVGUI_Module::saveTrace(const char* theName)
970 {
971   QFile file(theName);
972   if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
973     MESSAGE( "Could not open file:" << theName );
974     return;
975   }
976   QTextStream out(&file);
977   out << getTraceString();
978   file.close();
979 }
980
981 /*!
982   \brief Saves ParaView state to a disk file
983 */
984 void PVGUI_Module::saveParaviewState(const char* theFileName)
985 {
986   pqApplicationCore::instance()->saveState(theFileName);
987 }
988
989 /*!
990   \brief Delete all objects for Paraview Pipeline Browser
991 */
992 void PVGUI_Module::clearParaviewState()
993 {
994   QAction* deleteAllAction = action(DeleteAllId);
995   if (deleteAllAction) {
996     deleteAllAction->activate(QAction::Trigger);
997   }
998 }
999
1000 /*!
1001   \brief Restores ParaView state from a disk file
1002
1003   If toClear == true, the current ojects will be deleted
1004 */
1005 void PVGUI_Module::loadParaviewState(const char* theFileName)
1006 {
1007   pqApplicationCore::instance()->loadState(theFileName, getActiveServer());
1008 }
1009
1010 /*!
1011   \brief Returns current active ParaView server
1012 */
1013 pqServer* PVGUI_Module::getActiveServer()
1014 {
1015   return pqApplicationCore::instance()->getActiveServer();
1016 }
1017
1018
1019 /*!
1020   \brief Creates PARAVIS preference pane 
1021 */
1022 void PVGUI_Module::createPreferences()
1023 {
1024   // Paraview settings tab
1025   int aParaViewSettingsTab = addPreference( tr( "TIT_PVIEWSETTINGS" ) );
1026
1027   setPreferenceProperty(aParaViewSettingsTab, "stretch", false );
1028   int aPanel = addPreference(QString(), aParaViewSettingsTab, LightApp_Preferences::UserDefined, PARAVIS_MODULE_NAME, "");
1029
1030   setPreferenceProperty(aPanel, "content", (qint64)(new PVGUI_ParaViewSettingsPane(0, getApp())));
1031
1032   // Paravis settings tab
1033   int aParaVisSettingsTab = addPreference( tr( "TIT_PVISSETTINGS" ) );
1034   addPreference( tr( "PREF_STOP_TRACE" ), aParaVisSettingsTab, LightApp_Preferences::Bool, PARAVIS_MODULE_NAME, "stop_trace");
1035
1036   addPreference( tr( "PREF_NO_EXT_PVSERVER" ), aParaVisSettingsTab, LightApp_Preferences::Bool, PARAVIS_MODULE_NAME, "no_ext_pv_server");
1037
1038   int aSaveType = addPreference(tr( "PREF_SAVE_TYPE_LBL" ), aParaVisSettingsTab,
1039                                 LightApp_Preferences::Selector,
1040                                 PARAVIS_MODULE_NAME, "savestate_type");
1041   QList<QVariant> aIndices;
1042   QStringList aStrings;
1043   aIndices<<0<<1<<2;
1044   aStrings<<tr("PREF_SAVE_TYPE_0");
1045   aStrings<<tr("PREF_SAVE_TYPE_1");
1046   aStrings<<tr("PREF_SAVE_TYPE_2");
1047   setPreferenceProperty(aSaveType, "strings", aStrings);
1048   setPreferenceProperty(aSaveType, "indexes", aIndices);
1049 }
1050
1051 /*!
1052   \brief Creates ParaViS context menu popup
1053 */
1054 void PVGUI_Module::contextMenuPopup(const QString& theClient, QMenu* theMenu, QString& theTitle)
1055 {
1056   LightApp_Module::contextMenuPopup(theClient, theMenu, theTitle);
1057
1058   // Check if we are in Object Browser
1059   SUIT_DataBrowser* ob = getApp()->objectBrowser();
1060   bool isOBClient = (ob && theClient == ob->popupClientType());
1061   if (!isOBClient) {
1062     return;
1063   }
1064
1065   // Get list of selected objects
1066   LightApp_SelectionMgr* aSelectionMgr = getApp()->selectionMgr();
1067   SALOME_ListIO aListIO;
1068   aSelectionMgr->selectedObjects(aListIO);
1069   if (aListIO.Extent() == 1 && aListIO.First()->hasEntry()) {
1070     QString entry = QString(aListIO.First()->getEntry());
1071
1072     // Get active study
1073     SalomeApp_Study* activeStudy =
1074       dynamic_cast<SalomeApp_Study*>(getApp()->activeStudy());
1075     if(!activeStudy) {
1076       return;
1077     }
1078
1079     // Get SALOMEDS client study
1080     _PTR(Study) studyDS = activeStudy->studyDS();
1081     if(!studyDS) {
1082       return;
1083     }
1084
1085     QString paravisDataType(PARAVIS_MODULE_NAME);
1086     if(activeStudy && activeStudy->isComponent(entry) &&
1087        activeStudy->componentDataType(entry) == paravisDataType) {
1088       // ParaViS module object
1089       theMenu->addSeparator();
1090       theMenu->addAction(action(SaveStatePopupId));
1091     }
1092     else {
1093       // Try to get state object
1094       _PTR(SObject) stateSObj =
1095           studyDS->FindObjectID(entry.toLatin1().constData());
1096       if (!stateSObj) {
1097           return;
1098       }
1099
1100       // Check local id
1101       _PTR(GenericAttribute) anAttr;
1102       if (!stateSObj->FindAttribute(anAttr, "AttributeLocalID")) {
1103           return;
1104       }
1105
1106       _PTR(AttributeLocalID) anID(anAttr);
1107
1108       if (anID->Value() == PVSTATEID) {
1109         // Paraview state object
1110         theMenu->addSeparator();
1111         theMenu->addAction(action(AddStatePopupId));
1112         theMenu->addAction(action(CleanAndAddStatePopupId));
1113         theMenu->addSeparator();
1114         theMenu->addAction(action(ParaVisRenameId));
1115         theMenu->addAction(action(ParaVisDeleteId));
1116       }
1117     }
1118   }
1119 }
1120
1121 /*!
1122   \brief. Show ParaView python trace.
1123 */
1124 void PVGUI_Module::onShowTrace()
1125 {
1126   if (!myTraceWindow) {
1127     myTraceWindow = new pqPythonScriptEditor(getApp()->desktop());
1128   }
1129   myTraceWindow->setText(getTraceString());
1130   myTraceWindow->show();
1131   myTraceWindow->raise();
1132   myTraceWindow->activateWindow();
1133 }
1134
1135
1136 /*!
1137   \brief. Re-initialize ParaView python trace.
1138 */
1139 void PVGUI_Module::onRestartTrace()
1140 {
1141   stopTrace();
1142   startTrace();
1143 }
1144
1145 /*!
1146   \brief Save state under the module root object.
1147 */
1148 void PVGUI_Module::onSaveMultiState()
1149 {
1150   // Create state study object
1151   
1152   // Get SALOMEDS client study
1153   _PTR(Study) studyDS = PARAVIS::GetCStudy(this);
1154   if(!studyDS) {
1155     return;
1156   }
1157
1158   _PTR(SComponent) paravisComp = 
1159       studyDS->FindComponent(PARAVIS_MODULE_NAME);
1160   if(!paravisComp) {
1161     return;
1162   }
1163
1164   // Unlock the study if it is locked
1165   bool isLocked = studyDS->GetProperties()->IsLocked();
1166   if (isLocked) {
1167     studyDS->GetProperties()->SetLocked(false);
1168   }
1169   
1170   QString stateName = tr("SAVED_PARAVIEW_STATE_NAME") + 
1171     QString::number(myStateCounter + 1);
1172
1173   _PTR(StudyBuilder) studyBuilder = studyDS->NewBuilder();
1174   _PTR(SObject) newSObj = studyBuilder->NewObject(paravisComp);
1175
1176   // Set name
1177   _PTR(GenericAttribute) anAttr;
1178   anAttr = studyBuilder->FindOrCreateAttribute(newSObj, "AttributeName");
1179   _PTR(AttributeName) nameAttr(anAttr);
1180   
1181   nameAttr->SetValue(stateName.toLatin1().constData());
1182
1183   // Set local id
1184   anAttr = studyBuilder->FindOrCreateAttribute(newSObj, "AttributeLocalID");
1185   _PTR(AttributeLocalID) localIdAttr(anAttr);
1186   
1187   localIdAttr->SetValue(PVSTATEID);
1188
1189   // Set file name
1190   QString stateEntry = QString::fromStdString(newSObj->GetID());
1191  
1192   // File name for state saving
1193   QString tmpDir = QString::fromStdString(SALOMEDS_Tool::GetTmpDir());
1194   QString fileName = QString("%1_paravisstate:%2").arg(tmpDir, stateEntry);
1195
1196   anAttr = studyBuilder->FindOrCreateAttribute(newSObj, "AttributeString");
1197   _PTR(AttributeString) stringAttr(anAttr);
1198   
1199   stringAttr->SetValue(fileName.toLatin1().constData());
1200
1201   // Lock the study back if necessary
1202   if (isLocked) {
1203     studyDS->GetProperties()->SetLocked(true);
1204   }
1205   
1206   // Save state
1207   saveParaviewState(fileName.toLatin1().constData());
1208   myTemporaryFiles.append(fileName);
1209   
1210   // Increment the counter
1211   myStateCounter++;
1212
1213   updateObjBrowser();
1214 }
1215
1216 /*!
1217   \brief Restore the selected state by merging with the current one.
1218 */
1219 void PVGUI_Module::onAddState()
1220 {
1221   loadSelectedState(false);
1222 }
1223
1224 /*!
1225   \brief Clean the current state and restore the selected one.
1226 */
1227 void PVGUI_Module::onCleanAddState()
1228 {
1229   loadSelectedState(true);
1230 }
1231
1232 /*!
1233   \brief Rename the selected object.
1234 */
1235 void PVGUI_Module::onRename()
1236 {
1237   LightApp_SelectionMgr* aSelectionMgr = getApp()->selectionMgr();
1238   SALOME_ListIO aListIO;
1239   aSelectionMgr->selectedObjects(aListIO);
1240   
1241   if (aListIO.Extent() == 1 && aListIO.First()->hasEntry()) {
1242     std::string entry = aListIO.First()->getEntry();
1243     
1244     // Get SALOMEDS client study 
1245     _PTR(Study) studyDS = PARAVIS::GetCStudy(this);
1246     if(!studyDS) {
1247       return;
1248     }
1249     
1250     // Unlock the study if it is locked
1251     bool isLocked = studyDS->GetProperties()->IsLocked();
1252     if (isLocked) {
1253       studyDS->GetProperties()->SetLocked(false);
1254     }
1255     
1256     // Rename the selected state object
1257     _PTR(SObject) stateSObj = studyDS->FindObjectID(entry);
1258     if (!stateSObj) {
1259       return;
1260     }
1261     
1262     _PTR(GenericAttribute) anAttr;
1263     if (stateSObj->FindAttribute(anAttr, "AttributeName")) {
1264       _PTR(AttributeName) nameAttr (anAttr);
1265       QString newName = 
1266           LightApp_NameDlg::getName(getApp()->desktop(), nameAttr->Value().c_str());
1267       if (!newName.isEmpty()) {
1268         nameAttr->SetValue(newName.toLatin1().constData());
1269         aListIO.First()->setName(newName.toLatin1().constData());
1270       }
1271     }
1272     
1273     // Lock the study back if necessary
1274     if (isLocked) {
1275       studyDS->GetProperties()->SetLocked(true);
1276     }
1277     
1278     // Update object browser
1279     updateObjBrowser();
1280     
1281   }
1282 }
1283
1284 /*!
1285   \brief Delete the selected objects.
1286 */
1287 void PVGUI_Module::onDelete()
1288 {
1289   LightApp_SelectionMgr* aSelectionMgr = getApp()->selectionMgr();
1290   SALOME_ListIO aListIO;
1291   aSelectionMgr->selectedObjects(aListIO);
1292   
1293   if (aListIO.Extent() == 1 && aListIO.First()->hasEntry()) {
1294     std::string entry = aListIO.First()->getEntry();
1295     
1296     // Get SALOMEDS client study 
1297     _PTR(Study) studyDS = PARAVIS::GetCStudy(this);
1298     if(!studyDS) {
1299       return;
1300     }
1301     
1302     // Unlock the study if it is locked
1303     bool isLocked = studyDS->GetProperties()->IsLocked();
1304     if (isLocked) {
1305       studyDS->GetProperties()->SetLocked(false);
1306     }
1307     
1308     // Remove the selected state from the study
1309     _PTR(StudyBuilder) studyBuilder = studyDS->NewBuilder();
1310     _PTR(SObject) stateSObj = studyDS->FindObjectID(entry);
1311     studyBuilder->RemoveObject(stateSObj);
1312     
1313     // Lock the study back if necessary
1314     if (isLocked) {
1315       studyDS->GetProperties()->SetLocked(true);
1316     }
1317     
1318     // Update object browser
1319     updateObjBrowser();
1320   }
1321 }
1322
1323 void PVGUI_Module::onPushTraceTimer()
1324 {
1325   //MESSAGE("onPushTraceTimer(): Pushing trace to engine...");
1326   GetEngine()->PutPythonTraceStringToEngine(getTraceString().toStdString().c_str());
1327 }
1328
1329 /*!
1330   \brief Discover help project files from the resources.
1331   \return name of the help file. 
1332 */
1333 QString PVGUI_Module::getHelpFileName() {
1334   QString aPVHome(getenv("PVHOME"));
1335   if (aPVHome.isNull()) {
1336     qWarning("Wariable PVHOME is not defined");
1337     return QString();
1338   }
1339   QChar aSep = QDir::separator();
1340   //PARAVIEW_VERSION from the vtkPVConfig.h file
1341   QString aFileName =  aPVHome + aSep + "share" + aSep + "doc" + aSep + "paraview-"+ PARAVIEW_VERSION + aSep + "paraview.qch";
1342   return aFileName;
1343 }
1344
1345
1346 /*!
1347   \brief Load selected paraview state
1348
1349   If toClear == true, the current state will be cleared
1350 */
1351 void PVGUI_Module::loadSelectedState(bool toClear)
1352 {
1353   QString fileName;
1354
1355   LightApp_SelectionMgr* aSelectionMgr = getApp()->selectionMgr();
1356   SALOME_ListIO aListIO;
1357   aSelectionMgr->selectedObjects(aListIO);
1358   
1359   if (aListIO.Extent() == 1 && aListIO.First()->hasEntry()) {
1360     std::string entry = aListIO.First()->getEntry();
1361     
1362     // Get SALOMEDS client study 
1363     _PTR(Study) studyDS = PARAVIS::GetCStudy(this);
1364     if(!studyDS) {
1365       return;
1366     }
1367
1368     // Check local id
1369     _PTR(SObject) stateSObj = studyDS->FindObjectID(entry);
1370     _PTR(GenericAttribute) anAttr;
1371     if (!stateSObj->FindAttribute(anAttr, "AttributeLocalID")) {
1372       return;
1373     }
1374     _PTR(AttributeLocalID) anID(anAttr);
1375     if (!anID->Value() == PVSTATEID) {
1376       return;
1377     }
1378
1379     // Get state file name
1380     if (stateSObj->FindAttribute(anAttr, "AttributeString")) {
1381       _PTR(AttributeString) aStringAttr(anAttr);
1382       QString stringValue(aStringAttr->Value().c_str());
1383
1384       if (QFile::exists(stringValue)) {
1385           fileName = stringValue;
1386       }
1387     }
1388   }
1389   
1390   if (!fileName.isEmpty()) {
1391     if (toClear) {
1392       clearParaviewState();
1393     }
1394
1395     loadParaviewState(fileName.toLatin1().constData());
1396   } 
1397   else {
1398     SUIT_MessageBox::critical(getApp()->desktop(),
1399                               tr("ERR_ERROR"),
1400                               tr("ERR_STATE_CANNOT_BE_RESTORED"));
1401   }
1402 }
1403
1404 /*!
1405   \fn CAM_Module* createModule();
1406   \brief Export module instance (factory function).
1407   \return new created instance of the module
1408 */
1409
1410 #ifdef WNT
1411 #define PVGUI_EXPORT __declspec(dllexport)
1412 #else   // WNT
1413 #define PVGUI_EXPORT
1414 #endif  // WNT
1415
1416 extern "C" {
1417
1418   bool flag = false;
1419   PVGUI_EXPORT CAM_Module* createModule() {
1420     return new PVGUI_Module();
1421   }
1422   
1423   PVGUI_EXPORT char* getModuleVersion() {
1424     return (char*)PARAVIS_VERSION_STR;
1425   }
1426 }