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