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