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