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