Salome HOME
Moved PVViewer code from PARAVIS into GUI
[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   traceString = "import pvsimple" + QString(nl.str().c_str()) + traceString;
897
898   // Replace import "paraview.simple" by "pvsimple"
899   if ((!traceString.isNull()) && traceString.length() != 0) {
900     int aPos = traceString.indexOf(MYReplaceStr);
901     while (aPos != -1) {
902       traceString = traceString.replace(aPos, MYReplaceStr.length(), "pvsimple");
903       aPos = traceString.indexOf(MYReplaceStr, aPos);
904     }
905   }
906
907   return traceString;
908 }
909
910 /*!
911   \brief Saves trace string to disk file
912 */
913 void PVGUI_Module::saveTrace(const char* theName)
914 {
915   QFile file(theName);
916   if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
917     MESSAGE( "Could not open file:" << theName );
918     return;
919   }
920   QTextStream out(&file);
921   out << getTraceString();
922   file.close();
923 }
924
925 /*!
926   \brief Saves ParaView state to a disk file
927 */
928 void PVGUI_Module::saveParaviewState(const char* theFileName)
929 {
930   pqApplicationCore::instance()->saveState(theFileName);
931 }
932
933 /*!
934   \brief Delete all objects for Paraview Pipeline Browser
935 */
936 void PVGUI_Module::clearParaviewState()
937 {
938   QAction* deleteAllAction = action(DeleteAllId);
939   if (deleteAllAction) {
940     deleteAllAction->activate(QAction::Trigger);
941   }
942 }
943
944 /*!
945   \brief Restores ParaView state from a disk file
946
947   If toClear == true, the current ojects will be deleted
948 */
949 void PVGUI_Module::loadParaviewState(const char* theFileName)
950 {
951   pqApplicationCore::instance()->loadState(theFileName, getActiveServer());
952 }
953
954 /*!
955   \brief Returns current active ParaView server
956 */
957 pqServer* PVGUI_Module::getActiveServer()
958 {
959   return pqApplicationCore::instance()->getActiveServer();
960 }
961
962
963 /*!
964   \brief Creates PARAVIS preference pane 
965 */
966 void PVGUI_Module::createPreferences()
967 {
968   // Paraview settings tab
969   int aParaViewSettingsTab = addPreference( tr( "TIT_PVIEWSETTINGS" ) );
970   int aPanel = addPreference(QString(), aParaViewSettingsTab, LightApp_Preferences::UserDefined, "PARAVIS", "");
971   setPreferenceProperty(aPanel, "content", (qint64)(new PVGUI_ParaViewSettingsPane()));
972
973   // Paravis settings tab
974   int aParaVisSettingsTab = addPreference( tr( "TIT_PVISSETTINGS" ) );
975   addPreference( tr( "PREF_STOP_TRACE" ), aParaVisSettingsTab, LightApp_Preferences::Bool, "PARAVIS", "stop_trace");
976
977   addPreference( tr( "PREF_NO_EXT_PVSERVER" ), aParaVisSettingsTab, LightApp_Preferences::Bool, "PARAVIS", "no_ext_pv_server");
978
979   int aSaveType = addPreference(tr( "PREF_SAVE_TYPE_LBL" ), aParaVisSettingsTab,
980                                 LightApp_Preferences::Selector,
981                                 "PARAVIS", "savestate_type");
982   QList<QVariant> aIndices;
983   QStringList aStrings;
984   aIndices<<0<<1<<2;
985   aStrings<<tr("PREF_SAVE_TYPE_0");
986   aStrings<<tr("PREF_SAVE_TYPE_1");
987   aStrings<<tr("PREF_SAVE_TYPE_2");
988   setPreferenceProperty(aSaveType, "strings", aStrings);
989   setPreferenceProperty(aSaveType, "indexes", aIndices);
990 }
991
992 /*!
993   \brief Creates ParaViS context menu popup
994 */
995 void PVGUI_Module::contextMenuPopup(const QString& theClient, QMenu* theMenu, QString& theTitle)
996 {
997   SalomeApp_Module::contextMenuPopup(theClient, theMenu, theTitle);
998   
999   // Check if we are in Object Browser
1000   SUIT_DataBrowser* ob = getApp()->objectBrowser();
1001   bool isOBClient = (ob && theClient == ob->popupClientType());
1002   if (!isOBClient) {
1003     return;
1004   }
1005
1006   // Get list of selected objects
1007   LightApp_SelectionMgr* aSelectionMgr = getApp()->selectionMgr();
1008   SALOME_ListIO aListIO;
1009   aSelectionMgr->selectedObjects(aListIO);
1010   if (aListIO.Extent() == 1 && aListIO.First()->hasEntry()) {
1011     QString entry = QString(aListIO.First()->getEntry());
1012     
1013     // Get active study
1014     SalomeApp_Study* activeStudy = 
1015       dynamic_cast<SalomeApp_Study*>(getApp()->activeStudy());
1016     if(!activeStudy) {
1017       return;
1018     }
1019
1020     // Get SALOMEDS client study 
1021     _PTR(Study) studyDS = activeStudy->studyDS();
1022     if(!studyDS) {
1023       return;
1024     }
1025
1026     QString paravisDataType(GetCPPEngine()->ComponentDataType());
1027     if(activeStudy && activeStudy->isComponent(entry) && 
1028        activeStudy->componentDataType(entry) == paravisDataType) {
1029       // ParaViS module object
1030       theMenu->addSeparator();
1031       theMenu->addAction(action(SaveStatePopupId));
1032     }
1033     else {
1034       // Try to get state object
1035       _PTR(SObject) stateSObj = 
1036           studyDS->FindObjectID(entry.toLatin1().constData());
1037       if (!stateSObj) {
1038           return;
1039       }
1040       
1041       // Check local id
1042       _PTR(GenericAttribute) anAttr;
1043       if (!stateSObj->FindAttribute(anAttr, "AttributeLocalID")) {
1044           return;
1045       }
1046
1047       _PTR(AttributeLocalID) anID(anAttr);
1048       
1049       if (anID->Value() == PVSTATEID) {
1050         // Paraview state object
1051         theMenu->addSeparator();
1052         theMenu->addAction(action(AddStatePopupId));
1053         theMenu->addAction(action(CleanAndAddStatePopupId));
1054         theMenu->addSeparator();
1055         theMenu->addAction(action(ParaVisRenameId));
1056         theMenu->addAction(action(ParaVisDeleteId));
1057       }
1058     }
1059   }
1060 }
1061
1062 /*!
1063   \brief. Show ParaView python trace.
1064 */
1065 void PVGUI_Module::onShowTrace()
1066 {
1067   if (!myTraceWindow) {
1068     myTraceWindow = new pqPythonScriptEditor(getApp()->desktop());
1069   }
1070   myTraceWindow->setText(getTraceString());
1071   myTraceWindow->show();
1072   myTraceWindow->raise();
1073   myTraceWindow->activateWindow();
1074 }
1075
1076
1077 /*!
1078   \brief. Re-initialize ParaView python trace.
1079 */
1080 void PVGUI_Module::onRestartTrace()
1081 {
1082   stopTrace();
1083   startTrace();
1084 }
1085
1086 /*!
1087   \brief Show ParaView view.
1088 */
1089 void PVGUI_Module::onNewParaViewWindow()
1090 {
1091   showView(true);
1092 }
1093
1094 /*!
1095   \brief Save state under the module root object.
1096 */
1097 void PVGUI_Module::onSaveMultiState()
1098 {
1099   // Create state study object
1100   
1101   // Get SALOMEDS client study
1102   _PTR(Study) studyDS = PARAVIS::GetCStudy(this);
1103   if(!studyDS) {
1104     return;
1105   }
1106   
1107   _PTR(SComponent) paravisComp = 
1108     studyDS->FindComponent(GetCPPEngine()->ComponentDataType());
1109   if(!paravisComp) {
1110     return;
1111   }
1112
1113   // Unlock the study if it is locked
1114   bool isLocked = studyDS->GetProperties()->IsLocked();
1115   if (isLocked) {
1116     studyDS->GetProperties()->SetLocked(false);
1117   }
1118   
1119   QString stateName = tr("SAVED_PARAVIEW_STATE_NAME") + 
1120     QString::number(myStateCounter + 1);
1121
1122   _PTR(StudyBuilder) studyBuilder = studyDS->NewBuilder();
1123   _PTR(SObject) newSObj = studyBuilder->NewObject(paravisComp);
1124
1125   // Set name
1126   _PTR(GenericAttribute) anAttr;
1127   anAttr = studyBuilder->FindOrCreateAttribute(newSObj, "AttributeName");
1128   _PTR(AttributeName) nameAttr(anAttr);
1129   
1130   nameAttr->SetValue(stateName.toLatin1().constData());
1131
1132   // Set local id
1133   anAttr = studyBuilder->FindOrCreateAttribute(newSObj, "AttributeLocalID");
1134   _PTR(AttributeLocalID) localIdAttr(anAttr);
1135   
1136   localIdAttr->SetValue(PVSTATEID);
1137
1138   // Set file name
1139   QString stateEntry = QString::fromStdString(newSObj->GetID());
1140  
1141   // File name for state saving
1142   QString tmpDir = QString::fromStdString(SALOMEDS_Tool::GetTmpDir());
1143   QString fileName = QString("%1_paravisstate:%2").arg(tmpDir, stateEntry);
1144
1145   anAttr = studyBuilder->FindOrCreateAttribute(newSObj, "AttributeString");
1146   _PTR(AttributeString) stringAttr(anAttr);
1147   
1148   stringAttr->SetValue(fileName.toLatin1().constData());
1149
1150   // Lock the study back if necessary
1151   if (isLocked) {
1152     studyDS->GetProperties()->SetLocked(true);
1153   }
1154   
1155   // Save state
1156   saveParaviewState(fileName.toLatin1().constData());
1157   myTemporaryFiles.append(fileName);
1158   
1159   // Increment the counter
1160   myStateCounter++;
1161
1162   updateObjBrowser();
1163 }
1164
1165 /*!
1166   \brief Restore the selected state by merging with the current one.
1167 */
1168 void PVGUI_Module::onAddState()
1169 {
1170   loadSelectedState(false);
1171 }
1172
1173 /*!
1174   \brief Clean the current state and restore the selected one.
1175 */
1176 void PVGUI_Module::onCleanAddState()
1177 {
1178   loadSelectedState(true);
1179 }
1180
1181 /*!
1182   \brief Rename the selected object.
1183 */
1184 void PVGUI_Module::onRename()
1185 {
1186   LightApp_SelectionMgr* aSelectionMgr = getApp()->selectionMgr();
1187   SALOME_ListIO aListIO;
1188   aSelectionMgr->selectedObjects(aListIO);
1189   
1190   if (aListIO.Extent() == 1 && aListIO.First()->hasEntry()) {
1191     std::string entry = aListIO.First()->getEntry();
1192     
1193     // Get SALOMEDS client study 
1194     _PTR(Study) studyDS = PARAVIS::GetCStudy(this);
1195     if(!studyDS) {
1196       return;
1197     }
1198     
1199     // Unlock the study if it is locked
1200     bool isLocked = studyDS->GetProperties()->IsLocked();
1201     if (isLocked) {
1202       studyDS->GetProperties()->SetLocked(false);
1203     }
1204     
1205     // Rename the selected state object
1206     _PTR(SObject) stateSObj = studyDS->FindObjectID(entry);
1207     if (!stateSObj) {
1208       return;
1209     }
1210     
1211     _PTR(GenericAttribute) anAttr;
1212     if (stateSObj->FindAttribute(anAttr, "AttributeName")) {
1213       _PTR(AttributeName) nameAttr (anAttr);
1214       QString newName = 
1215           LightApp_NameDlg::getName(getApp()->desktop(), nameAttr->Value().c_str());
1216       if (!newName.isEmpty()) {
1217         nameAttr->SetValue(newName.toLatin1().constData());
1218         aListIO.First()->setName(newName.toLatin1().constData());
1219       }
1220     }
1221     
1222     // Lock the study back if necessary
1223     if (isLocked) {
1224       studyDS->GetProperties()->SetLocked(true);
1225     }
1226     
1227     // Update object browser
1228     updateObjBrowser();
1229     
1230   }
1231 }
1232
1233 /*!
1234   \brief Delete the selected objects.
1235 */
1236 void PVGUI_Module::onDelete()
1237 {
1238   LightApp_SelectionMgr* aSelectionMgr = getApp()->selectionMgr();
1239   SALOME_ListIO aListIO;
1240   aSelectionMgr->selectedObjects(aListIO);
1241   
1242   if (aListIO.Extent() == 1 && aListIO.First()->hasEntry()) {
1243     std::string entry = aListIO.First()->getEntry();
1244     
1245     // Get SALOMEDS client study 
1246     _PTR(Study) studyDS = PARAVIS::GetCStudy(this);
1247     if(!studyDS) {
1248       return;
1249     }
1250     
1251     // Unlock the study if it is locked
1252     bool isLocked = studyDS->GetProperties()->IsLocked();
1253     if (isLocked) {
1254       studyDS->GetProperties()->SetLocked(false);
1255     }
1256     
1257     // Remove the selected state from the study
1258     _PTR(StudyBuilder) studyBuilder = studyDS->NewBuilder();
1259     _PTR(SObject) stateSObj = studyDS->FindObjectID(entry);
1260     studyBuilder->RemoveObject(stateSObj);
1261     
1262     // Lock the study back if necessary
1263     if (isLocked) {
1264       studyDS->GetProperties()->SetLocked(true);
1265     }
1266     
1267     // Update object browser
1268     updateObjBrowser();
1269   }
1270 }
1271
1272 void PVGUI_Module::onPushTraceTimer()
1273 {
1274 //  MESSAGE("onPushTraceTimer(): Pushing trace to engine...");
1275   GetCPPEngine()->PutPythonTraceStringToEngine(getTraceString().toStdString().c_str());
1276 }
1277
1278 /*!
1279   \brief Discover help project files from the resources.
1280   \return name of the help file. 
1281 */
1282 QString PVGUI_Module::getHelpFileName() {
1283   QString aPVHome(getenv("PVHOME"));
1284   if (aPVHome.isNull()) {
1285     qWarning("Wariable PVHOME is not defined");
1286     return QString();
1287   }
1288   QChar aSep = QDir::separator();
1289   //PARAVIEW_VERSION from the vtkPVConfig.h file
1290   QString aFileName =  aPVHome + aSep + "share" + aSep + "doc" + aSep + "paraview-"+ PARAVIEW_VERSION + aSep + "paraview.qch";
1291   return aFileName;
1292 }
1293
1294
1295 /*!
1296   \brief Load selected paraview state
1297
1298   If toClear == true, the current state will be cleared
1299 */
1300 void PVGUI_Module::loadSelectedState(bool toClear)
1301 {
1302   QString fileName;
1303
1304   LightApp_SelectionMgr* aSelectionMgr = getApp()->selectionMgr();
1305   SALOME_ListIO aListIO;
1306   aSelectionMgr->selectedObjects(aListIO);
1307   
1308   if (aListIO.Extent() == 1 && aListIO.First()->hasEntry()) {
1309     std::string entry = aListIO.First()->getEntry();
1310     
1311     // Get SALOMEDS client study 
1312     _PTR(Study) studyDS = PARAVIS::GetCStudy(this);
1313     if(!studyDS) {
1314       return;
1315     }
1316
1317     // Check local id
1318     _PTR(SObject) stateSObj = studyDS->FindObjectID(entry);
1319     _PTR(GenericAttribute) anAttr;
1320     if (!stateSObj->FindAttribute(anAttr, "AttributeLocalID")) {
1321       return;
1322     }
1323     _PTR(AttributeLocalID) anID(anAttr);
1324     if (!anID->Value() == PVSTATEID) {
1325       return;
1326     }
1327
1328     // Get state file name
1329     if (stateSObj->FindAttribute(anAttr, "AttributeString")) {
1330       _PTR(AttributeString) aStringAttr(anAttr);
1331       QString stringValue(aStringAttr->Value().c_str());
1332
1333       if (QFile::exists(stringValue)) {
1334           fileName = stringValue;
1335       }
1336     }
1337   }
1338   
1339   if (!fileName.isEmpty()) {
1340     if (toClear) {
1341       clearParaviewState();
1342     }
1343
1344     loadParaviewState(fileName.toLatin1().constData());
1345   } 
1346   else {
1347     SUIT_MessageBox::critical(getApp()->desktop(),
1348                               tr("ERR_ERROR"),
1349                               tr("ERR_STATE_CANNOT_BE_RESTORED"));
1350   }
1351 }
1352
1353 /*!
1354   \fn CAM_Module* createModule();
1355   \brief Export module instance (factory function).
1356   \return new created instance of the module
1357 */
1358
1359 #ifdef WNT
1360 #define PVGUI_EXPORT __declspec(dllexport)
1361 #else   // WNT
1362 #define PVGUI_EXPORT
1363 #endif  // WNT
1364
1365 extern "C" {
1366
1367   bool flag = false;
1368   PVGUI_EXPORT CAM_Module* createModule() {
1369     return new PVGUI_Module();
1370   }
1371   
1372   PVGUI_EXPORT char* getModuleVersion() {
1373     return (char*)PARAVIS_VERSION_STR;
1374   }
1375 }