]> SALOME platform Git repositories - modules/paravis.git/blob - src/PVGUI/PVGUI_Module.cxx
Salome HOME
Documentation.
[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   fixAnimationScene();
445 }
446
447 /*!
448  * Little trick to force the proper update of the timesteps/time range when the module is initialized.
449  * This is otherwise not properly working when PARAVIS is activated after a PVViewer has already been
450  * instanciated.
451  */
452 void PVGUI_Module::fixAnimationScene()
453 {
454   pqServer* server = pqActiveObjects::instance().activeServer();
455   pqApplicationCore * app = pqApplicationCore::instance();
456   pqPipelineSource * src = app->getObjectBuilder()->createSource(QString("sources"), QString("TimeSource"),server);
457   app->getObjectBuilder()->destroy(src);
458 }
459
460 /*!
461  * \brief Slot called when the progress bar starts.
462  */
463 void PVGUI_Module::onStartProgress()
464 {
465   QApplication::setOverrideCursor(Qt::WaitCursor);
466 }
467
468 /*!
469  * \brief Slot called when the progress bar is done.
470  */
471 void PVGUI_Module::onEndProgress()
472 {
473   QApplication::restoreOverrideCursor();
474 }
475
476 void PVGUI_Module::onDataRepresentationUpdated() {
477   SalomeApp_Study* activeStudy = dynamic_cast<SalomeApp_Study*>(application()->activeStudy());
478   if(!activeStudy) return;
479   
480   activeStudy->Modified();
481 }
482
483 /*!
484   \brief Initialisation timer event - Starts up the Python trace
485 */
486 void PVGUI_Module::onInitTimer()
487 {
488   startTrace();
489 }
490   
491 /*!
492   \brief Get list of embedded macros files
493 */
494 QStringList PVGUI_Module::getEmbeddedMacrosList()
495 {
496   QString aRootDir = getenv("PARAVIS_ROOT_DIR");
497
498   QString aSourcePath = aRootDir + "/bin/salome/Macro";
499
500   QStringList aFilter;
501   aFilter << "*.py";
502
503   QDir aSourceDir(aSourcePath);
504   QStringList aSourceFiles = aSourceDir.entryList(aFilter, QDir::Files);
505   QStringList aFullPathSourceFiles;
506   foreach (QString aMacrosName, aSourceFiles) {
507     aFullPathSourceFiles << aSourceDir.absoluteFilePath(aMacrosName);
508   }
509   return aFullPathSourceFiles;
510 }
511
512 /*!
513   \brief Update the list of embedded macros
514 */
515 void PVGUI_Module::updateMacros()
516 {
517   pqPythonManager* aPythonManager = pqPVApplicationCore::instance()->pythonManager();
518   if(!aPythonManager)  {
519     return;
520   }
521   
522   foreach (QString aStr, getEmbeddedMacrosList()) {
523     aPythonManager->addMacro(aStr);
524   }
525 }
526
527
528 /*!
529   \brief Get list of compliant dockable GUI elements
530   \param m map to be filled in ("type":"default_position")
531 */
532 void PVGUI_Module::windows( QMap<int, int>& m ) const
533 {
534   m.insert( LightApp_Application::WT_ObjectBrowser, Qt::LeftDockWidgetArea );
535   m.insert( LightApp_Application::WT_PyConsole, Qt::BottomDockWidgetArea );
536   // ParaView diagnostic output redirected here
537   m.insert( LightApp_Application::WT_LogWindow, Qt::BottomDockWidgetArea );
538 }
539
540 /*!
541   \brief Shows (toShow = true) or hides ParaView view window
542 */
543 void PVGUI_Module::showView( bool toShow )
544 {
545   LightApp_Application* anApp = getApp();
546   PVViewer_ViewManager* viewMgr =
547     dynamic_cast<PVViewer_ViewManager*>( anApp->getViewManager( PVViewer_Viewer::Type(), false ) );
548   if ( !viewMgr ) {
549     viewMgr = new PVViewer_ViewManager( anApp->activeStudy(), anApp->desktop(), anApp->logWindow() );
550     anApp->addViewManager( viewMgr );
551     connect( viewMgr, SIGNAL( lastViewClosed( SUIT_ViewManager* ) ),
552              anApp, SLOT( onCloseView( SUIT_ViewManager* ) ) );
553   }
554
555   PVViewer_ViewWindow* pvWnd = dynamic_cast<PVViewer_ViewWindow*>( viewMgr->getActiveView() );
556   if ( !pvWnd ) {
557     pvWnd = dynamic_cast<PVViewer_ViewWindow*>( viewMgr->createViewWindow() );
558     // this also connects to the pvserver and instantiates relevant PV behaviors
559   }
560
561   pvWnd->setShown( toShow );
562   if ( toShow ) pvWnd->setFocus();
563 }
564
565 /*!
566   \brief Slot to show help for proxy.
567 */
568 void PVGUI_Module::showHelpForProxy( const QString& groupname, const QString& proxyname )
569 {
570   pqHelpReaction::showProxyHelp(groupname, proxyname);
571 }
572
573
574 /*!
575   \brief Slot to show the waiting state.
576 */
577 void PVGUI_Module::onPreAccept()
578 {
579   getApp()->desktop()->statusBar()->showMessage(tr("STB_PREACCEPT"));
580   QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
581 }
582
583 /*!
584   \brief Slot to show the ready state.
585 */
586 void PVGUI_Module::onPostAccept()
587 {
588   getApp()->desktop()->statusBar()->showMessage(tr("STB_POSTACCEPT"), 2000);
589   QTimer::singleShot(0, this, SLOT(endWaitCursor()));
590 }
591
592 /*!
593   \brief Slot to switch off wait cursor.
594 */
595 void PVGUI_Module::endWaitCursor()
596 {
597   QApplication::restoreOverrideCursor();
598 }
599
600 /*!
601   \brief Handler method for the output of messages.
602 */
603 static void ParavisMessageOutput(QtMsgType type, const char *msg)
604 {
605   switch(type)
606     {
607   case QtDebugMsg:
608     vtkOutputWindow::GetInstance()->DisplayText(msg);
609     break;
610   case QtWarningMsg:
611     vtkOutputWindow::GetInstance()->DisplayErrorText(msg);
612     break;
613   case QtCriticalMsg:
614     vtkOutputWindow::GetInstance()->DisplayErrorText(msg);
615     break;
616   case QtFatalMsg:
617     vtkOutputWindow::GetInstance()->DisplayErrorText(msg);
618     break;
619     }
620 }
621
622 /*!
623   \brief Activate module.
624   \param study current study
625   \return \c true if activaion is done successfully or 0 to prevent
626   activation on error
627 */
628 bool PVGUI_Module::activateModule( SUIT_Study* study )
629 {
630   myOldMsgHandler = qInstallMsgHandler(ParavisMessageOutput);
631   
632   SUIT_ExceptionHandler::addCleanUpRoutine( paravisCleanUp );
633
634   storeCommonWindowsState();
635
636   bool isDone = LightApp_Module::activateModule( study );
637   if ( !isDone ) return false;
638
639   showView( true );
640   if ( mySourcesMenuId != -1 ) menuMgr()->show(mySourcesMenuId);
641   if ( myFiltersMenuId != -1 ) menuMgr()->show(myFiltersMenuId);
642   if ( myMacrosMenuId != -1 ) menuMgr()->show(myMacrosMenuId);
643   if ( myToolbarsMenuId != -1 ) menuMgr()->show(myToolbarsMenuId);
644
645   // Update the various menus with the content pre-loaded in myGuiElements
646 //  QMenu* srcMenu = menuMgr()->findMenu( mySourcesMenuId );
647 //  myGuiElements->updateSourcesMenu(srcMenu);
648 //  QMenu* filtMenu = menuMgr()->findMenu( myFiltersMenuId );
649 //  myGuiElements->updateFiltersMenu(filtMenu);
650 //  QMenu* macMenu = menuMgr()->findMenu( myMacrosMenuId );
651 //  myGuiElements->updateMacrosMenu(macMenu);
652
653   setMenuShown( true );
654   setToolShown( true );
655
656   restoreDockWidgetsState();
657
658   QMenu* aMenu = menuMgr()->findMenu( myRecentMenuId );
659   if(aMenu) {
660     QList<QAction*> anActns = aMenu->actions();
661     for (int i = 0; i < anActns.size(); ++i) {
662       QAction* a = anActns.at(i);
663       if(a)
664         a->setVisible(true);
665     }
666   }
667
668   QList<QMenu*>::iterator it;
669   for (it = myMenus.begin(); it != myMenus.end(); ++it) {
670     QAction* a = (*it)->menuAction();
671     if(a)
672       a->setVisible(true);
673   }
674
675   if ( myRecentMenuId != -1 ) menuMgr()->show(myRecentMenuId);
676
677   ClientFindOrCreateParavisComponent(PARAVIS::GetCStudy(this));
678
679   return isDone;
680 }
681
682
683 /*!
684   \brief Deactivate module.
685   \param study current study
686   \return \c true if deactivaion is done successfully or 0 to prevent
687   deactivation on error
688 */
689 bool PVGUI_Module::deactivateModule( SUIT_Study* study )
690 {
691   MESSAGE("PARAVIS deactivation ...")
692
693   QMenu* aMenu = menuMgr()->findMenu( myRecentMenuId );
694   if(aMenu) {
695     QList<QAction*> anActns = aMenu->actions();
696     for (int i = 0; i < anActns.size(); ++i) {
697       QAction* a = anActns.at(i);
698       if(a)
699         a->setVisible(false);
700     }
701   }
702
703   QList<QMenu*>::iterator it;
704   for (it = myMenus.begin(); it != myMenus.end(); ++it) {
705     QAction* a = (*it)->menuAction();
706     if(a)
707       a->setVisible(false);
708   }
709
710   QList<QDockWidget*> aStreamingViews = application()->desktop()->findChildren<QDockWidget*>("pqStreamingControls");
711   foreach(QDockWidget* aView, aStreamingViews) {
712     if (!myDockWidgets.contains(aView))
713       myDockWidgets[aView] = aView->isVisible();
714   }
715
716   /*if (pqImplementation::helpWindow) {
717     pqImplementation::helpWindow->hide();
718     }*/
719   showView( false );
720   // hide menus
721   menuMgr()->hide(myRecentMenuId);
722   menuMgr()->hide(mySourcesMenuId);
723   menuMgr()->hide(myFiltersMenuId);
724   menuMgr()->hide(myMacrosMenuId);
725   menuMgr()->hide(myToolbarsMenuId);
726   setMenuShown( false );
727   setToolShown( false );
728
729   saveDockWidgetsState();
730
731   SUIT_ExceptionHandler::removeCleanUpRoutine( paravisCleanUp );
732
733   if (myOldMsgHandler)
734     qInstallMsgHandler(myOldMsgHandler);
735
736   restoreCommonWindowsState();
737   
738   return LightApp_Module::deactivateModule( study );
739 }
740
741
742 /*!
743   \brief Called when application is closed.
744
745   Process finalize application functionality from ParaView in order to save server settings
746   and nullify application pointer if the application is being closed.
747
748   \param theApp application
749 */
750 void PVGUI_Module::onApplicationClosed( SUIT_Application* theApp )
751 {
752   PVViewer_ViewManager::ParaviewCleanup();
753
754   int aAppsNb = SUIT_Session::session()->applications().size();
755   if (aAppsNb == 1) {
756     deleteTemporaryFiles();
757   }
758   CAM_Module::onApplicationClosed(theApp);
759 }
760
761
762 /*!
763   \brief Deletes temporary files created during import operation from VISU
764 */
765 void PVGUI_Module::deleteTemporaryFiles()
766 {
767   foreach(QString aFile, myTemporaryFiles) {
768     if (QFile::exists(aFile)) {
769       QFile::remove(aFile);
770     }
771   }
772 }
773
774
775 /*!
776   \brief Called when study is closed.
777
778   Removes data model from the \a study.
779
780   \param study study being closed
781 */
782 void PVGUI_Module::studyClosed(SUIT_Study* study)
783 {
784   clearParaviewState();
785
786   LightApp_Module::studyClosed(study);
787 }
788
789 /*!
790   \brief Called when study is opened.
791 */
792 void PVGUI_Module::onModelOpened()
793 {
794   _PTR(Study) studyDS = PARAVIS::GetCStudy(this);
795   if(!studyDS) {
796     return;
797   }
798
799   _PTR(SComponent) paravisComp =
800     studyDS->FindComponent(PARAVIS_MODULE_NAME);
801   if(!paravisComp) {
802     return;
803   }
804
805   _PTR(ChildIterator) anIter(studyDS->NewChildIterator(paravisComp));
806   for (; anIter->More(); anIter->Next()) {
807     _PTR(SObject) aSObj = anIter->Value();
808     _PTR(GenericAttribute) anAttr;
809     if (!aSObj->FindAttribute(anAttr, "AttributeLocalID")) {
810       continue;
811     }
812     _PTR(AttributeLocalID) anID(anAttr);
813     if (anID->Value() == PVSTATEID) {
814       myStateCounter++;
815     }
816   }
817 }
818
819 /*!
820 \brief Returns IOR of current engine
821 */
822 QString PVGUI_Module::engineIOR() const
823 {
824   CORBA::String_var anIOR = GetCPPEngine()->GetIOR();
825   return QString(anIOR.in());
826 }
827
828 /*!
829   \brief Open file of format supported by ParaView
830 */
831 void PVGUI_Module::openFile(const char* theName)
832 {
833   QStringList aFiles;
834   aFiles<<theName;
835   pqLoadDataReaction::loadData(aFiles);
836 }
837
838 /**!
839  * \brief Starts Python trace.
840  *
841  * Start trace invoking the newly introduced C++ API (PV 4.2)
842  * (inspired from pqTraceReaction::start())
843  */
844 void PVGUI_Module::startTrace()
845 {
846   vtkSMSessionProxyManager* pxm = pqActiveObjects::instance().activeServer()->proxyManager();
847
848   vtkSmartPointer<vtkSMProxy> proxy;
849   proxy.TakeReference(pxm->NewProxy("pythontracing", "PythonTraceOptions"));
850   if (proxy)
851     {
852       vtkNew<vtkSMParaViewPipelineController> controller;
853       controller->InitializeProxy(proxy);
854     }
855   vtkSMTrace* trace = vtkSMTrace::StartTrace();
856   if (proxy)
857     {
858       // Set manually the properties entered via the dialog box poping-up when requiring
859       // a trace start in PV4.2 (trace options)
860       trace->SetPropertiesToTraceOnCreate(vtkSMTrace::RECORD_USER_MODIFIED_PROPERTIES);
861       trace->SetFullyTraceSupplementalProxies(false);
862     }
863 }
864
865 /**!
866  * \brief Stops Python trace.
867  */
868 void PVGUI_Module::stopTrace()
869 {
870   vtkSMTrace::StopTrace();
871 }
872
873 /**!
874  * \brief Execute a Python script.
875  */
876 void PVGUI_Module::executeScript(const char *script)
877 {
878 #ifndef WNT
879   pqPythonManager* manager = qobject_cast<pqPythonManager*>(
880                              pqApplicationCore::instance()->manager("PYTHON_MANAGER"));
881   if (manager)  {
882     pqPythonDialog* pyDiag = manager->pythonShellDialog();
883     if (pyDiag) {
884       pyDiag->runString(script);  
885       }
886     }
887 #endif
888 }
889
890 ///**
891 // *  Debug function printing out the given interpreter's execution context
892 // */
893 //void printInterpContext(PyInterp_Interp * interp )
894 //{
895 //  // Extract __smtraceString from interpreter's context
896 //  const PyObject* ctxt = interp->getExecutionContext();
897 //
898 //  PyObject* lst = PyDict_Keys((PyObject *)ctxt);
899 //  Py_ssize_t siz = PyList_GET_SIZE(lst);
900 //  for (Py_ssize_t i = 0; i < siz; i++)
901 //    {
902 //      PyObject * elem = PyList_GetItem(lst, i);
903 //      if (PyString_Check(elem))
904 //        {
905 //          std::cout << "At pos:" << i << ", " << PyString_AsString(elem) << std::endl;
906 //        }
907 //      else
908 //        std::cout << "At pos:" << i << ", not a string!" << std::endl;
909 //    }
910 //  Py_XDECREF(lst);
911 //}
912
913 /*!
914   \brief Returns trace string
915 */
916 static const QString MYReplaceStr("paraview.simple");
917 QString PVGUI_Module::getTraceString()
918 {
919   vtkSMTrace *tracer = vtkSMTrace::GetActiveTracer();
920   if (!tracer) // trace is not started
921     return QString("");
922
923   QString traceString(tracer->GetCurrentTrace());
924   std::stringstream nl; nl << std::endl; // surely there is some Qt trick to do that in a portable way??
925   QString end_line(nl.str().c_str());
926   // 'import pvsimple' is necessary to fix the first call to DisableFirstRenderCamera in the paraview trace
927   // 'ShowParaviewView()' ensure there is an opened viewing window (otherwise SEGFAULT!)
928   traceString = "import pvsimple" + end_line +
929                 "pvsimple.ShowParaviewView()" + end_line + traceString;
930
931   // Replace import "paraview.simple" by "pvsimple"
932   if ((!traceString.isNull()) && traceString.length() != 0) {
933     int aPos = traceString.indexOf(MYReplaceStr);
934     while (aPos != -1) {
935       traceString = traceString.replace(aPos, MYReplaceStr.length(), "pvsimple");
936       aPos = traceString.indexOf(MYReplaceStr, aPos);
937     }
938   }
939
940   return traceString;
941 }
942
943 /*!
944   \brief Saves trace string to disk file
945 */
946 void PVGUI_Module::saveTrace(const char* theName)
947 {
948   QFile file(theName);
949   if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
950     MESSAGE( "Could not open file:" << theName );
951     return;
952   }
953   QTextStream out(&file);
954   out << getTraceString();
955   file.close();
956 }
957
958 /*!
959   \brief Saves ParaView state to a disk file
960 */
961 void PVGUI_Module::saveParaviewState(const char* theFileName)
962 {
963   pqApplicationCore::instance()->saveState(theFileName);
964 }
965
966 /*!
967   \brief Delete all objects for Paraview Pipeline Browser
968 */
969 void PVGUI_Module::clearParaviewState()
970 {
971   QAction* deleteAllAction = action(DeleteAllId);
972   if (deleteAllAction) {
973     deleteAllAction->activate(QAction::Trigger);
974   }
975 }
976
977 /*!
978   \brief Restores ParaView state from a disk file
979
980   If toClear == true, the current ojects will be deleted
981 */
982 void PVGUI_Module::loadParaviewState(const char* theFileName)
983 {
984   pqApplicationCore::instance()->loadState(theFileName, getActiveServer());
985 }
986
987 /*!
988   \brief Returns current active ParaView server
989 */
990 pqServer* PVGUI_Module::getActiveServer()
991 {
992   return pqApplicationCore::instance()->getActiveServer();
993 }
994
995
996 /*!
997   \brief Creates PARAVIS preferences panel.
998 */
999 void PVGUI_Module::createPreferences()
1000 {
1001   // Paraview settings tab
1002   int aParaViewSettingsTab = addPreference( tr( "TIT_PVIEWSETTINGS" ) );
1003
1004   setPreferenceProperty(aParaViewSettingsTab, "stretch", false );
1005   int aPanel = addPreference(QString(), aParaViewSettingsTab, LightApp_Preferences::UserDefined, PARAVIS_MODULE_NAME, "");
1006
1007   setPreferenceProperty(aPanel, "content", (qint64)(new PVGUI_ParaViewSettingsPane(0, getApp())));
1008
1009   // Paravis settings tab
1010   int aParaVisSettingsTab = addPreference( tr( "TIT_PVISSETTINGS" ) );
1011   addPreference( tr( "PREF_STOP_TRACE" ), aParaVisSettingsTab, LightApp_Preferences::Bool, PARAVIS_MODULE_NAME, "stop_trace");
1012
1013   addPreference( tr( "PREF_NO_EXT_PVSERVER" ), aParaVisSettingsTab, LightApp_Preferences::Bool, PARAVIS_MODULE_NAME, "no_ext_pv_server");
1014
1015   int aSaveType = addPreference(tr( "PREF_SAVE_TYPE_LBL" ), aParaVisSettingsTab,
1016                                 LightApp_Preferences::Selector,
1017                                 PARAVIS_MODULE_NAME, "savestate_type");
1018   QList<QVariant> aIndices;
1019   QStringList aStrings;
1020   aIndices<<0<<1<<2;
1021   aStrings<<tr("PREF_SAVE_TYPE_0");
1022   aStrings<<tr("PREF_SAVE_TYPE_1");
1023   aStrings<<tr("PREF_SAVE_TYPE_2");
1024   setPreferenceProperty(aSaveType, "strings", aStrings);
1025   setPreferenceProperty(aSaveType, "indexes", aIndices);
1026 }
1027
1028 /*!
1029   \brief Creates ParaViS context menu popup
1030 */
1031 void PVGUI_Module::contextMenuPopup(const QString& theClient, QMenu* theMenu, QString& theTitle)
1032 {
1033   LightApp_Module::contextMenuPopup(theClient, theMenu, theTitle);
1034
1035   // Check if we are in Object Browser
1036   SUIT_DataBrowser* ob = getApp()->objectBrowser();
1037   bool isOBClient = (ob && theClient == ob->popupClientType());
1038   if (!isOBClient) {
1039     return;
1040   }
1041
1042   // Get list of selected objects
1043   LightApp_SelectionMgr* aSelectionMgr = getApp()->selectionMgr();
1044   SALOME_ListIO aListIO;
1045   aSelectionMgr->selectedObjects(aListIO);
1046   if (aListIO.Extent() == 1 && aListIO.First()->hasEntry()) {
1047     QString entry = QString(aListIO.First()->getEntry());
1048
1049     // Get active study
1050     SalomeApp_Study* activeStudy =
1051       dynamic_cast<SalomeApp_Study*>(getApp()->activeStudy());
1052     if(!activeStudy) {
1053       return;
1054     }
1055
1056     // Get SALOMEDS client study
1057     _PTR(Study) studyDS = activeStudy->studyDS();
1058     if(!studyDS) {
1059       return;
1060     }
1061
1062     QString paravisDataType(PARAVIS_MODULE_NAME);
1063     if(activeStudy && activeStudy->isComponent(entry) &&
1064        activeStudy->componentDataType(entry) == paravisDataType) {
1065       // ParaViS module object
1066       theMenu->addSeparator();
1067       theMenu->addAction(action(SaveStatePopupId));
1068     }
1069     else {
1070       // Try to get state object
1071       _PTR(SObject) stateSObj =
1072           studyDS->FindObjectID(entry.toLatin1().constData());
1073       if (!stateSObj) {
1074           return;
1075       }
1076
1077       // Check local id
1078       _PTR(GenericAttribute) anAttr;
1079       if (!stateSObj->FindAttribute(anAttr, "AttributeLocalID")) {
1080           return;
1081       }
1082
1083       _PTR(AttributeLocalID) anID(anAttr);
1084
1085       if (anID->Value() == PVSTATEID) {
1086         // Paraview state object
1087         theMenu->addSeparator();
1088         theMenu->addAction(action(AddStatePopupId));
1089         theMenu->addAction(action(CleanAndAddStatePopupId));
1090         theMenu->addSeparator();
1091         theMenu->addAction(action(ParaVisRenameId));
1092         theMenu->addAction(action(ParaVisDeleteId));
1093       }
1094     }
1095   }
1096 }
1097
1098 /*!
1099   \brief. Show ParaView python trace.
1100 */
1101 void PVGUI_Module::onShowTrace()
1102 {
1103   if (!myTraceWindow) {
1104     myTraceWindow = new pqPythonScriptEditor(getApp()->desktop());
1105   }
1106   myTraceWindow->setText(getTraceString());
1107   myTraceWindow->show();
1108   myTraceWindow->raise();
1109   myTraceWindow->activateWindow();
1110 }
1111
1112
1113 /*!
1114   \brief. Re-initialize ParaView python trace.
1115 */
1116 void PVGUI_Module::onRestartTrace()
1117 {
1118   stopTrace();
1119   startTrace();
1120 }
1121
1122 /*!
1123   \brief Save state under the module root object.
1124 */
1125 void PVGUI_Module::onSaveMultiState()
1126 {
1127   // Create state study object
1128   
1129   // Get SALOMEDS client study
1130   _PTR(Study) studyDS = PARAVIS::GetCStudy(this);
1131   if(!studyDS) {
1132     return;
1133   }
1134
1135   _PTR(SComponent) paravisComp = 
1136       studyDS->FindComponent(PARAVIS_MODULE_NAME);
1137   if(!paravisComp) {
1138     return;
1139   }
1140
1141   // Unlock the study if it is locked
1142   bool isLocked = studyDS->GetProperties()->IsLocked();
1143   if (isLocked) {
1144     studyDS->GetProperties()->SetLocked(false);
1145   }
1146   
1147   QString stateName = tr("SAVED_PARAVIEW_STATE_NAME") + 
1148     QString::number(myStateCounter + 1);
1149
1150   _PTR(StudyBuilder) studyBuilder = studyDS->NewBuilder();
1151   _PTR(SObject) newSObj = studyBuilder->NewObject(paravisComp);
1152
1153   // Set name
1154   _PTR(GenericAttribute) anAttr;
1155   anAttr = studyBuilder->FindOrCreateAttribute(newSObj, "AttributeName");
1156   _PTR(AttributeName) nameAttr(anAttr);
1157   
1158   nameAttr->SetValue(stateName.toLatin1().constData());
1159
1160   // Set local id
1161   anAttr = studyBuilder->FindOrCreateAttribute(newSObj, "AttributeLocalID");
1162   _PTR(AttributeLocalID) localIdAttr(anAttr);
1163   
1164   localIdAttr->SetValue(PVSTATEID);
1165
1166   // Set file name
1167   QString stateEntry = QString::fromStdString(newSObj->GetID());
1168  
1169   // File name for state saving
1170   QString tmpDir = QString::fromStdString(SALOMEDS_Tool::GetTmpDir());
1171   QString fileName = QString("%1_paravisstate:%2").arg(tmpDir, stateEntry);
1172
1173   anAttr = studyBuilder->FindOrCreateAttribute(newSObj, "AttributeString");
1174   _PTR(AttributeString) stringAttr(anAttr);
1175   
1176   stringAttr->SetValue(fileName.toLatin1().constData());
1177
1178   // Lock the study back if necessary
1179   if (isLocked) {
1180     studyDS->GetProperties()->SetLocked(true);
1181   }
1182   
1183   // Save state
1184   saveParaviewState(fileName.toLatin1().constData());
1185   myTemporaryFiles.append(fileName);
1186   
1187   // Increment the counter
1188   myStateCounter++;
1189
1190   updateObjBrowser();
1191 }
1192
1193 /*!
1194   \brief Restore the selected state by merging with the current one.
1195 */
1196 void PVGUI_Module::onAddState()
1197 {
1198   loadSelectedState(false);
1199 }
1200
1201 /*!
1202   \brief Clean the current state and restore the selected one.
1203 */
1204 void PVGUI_Module::onCleanAddState()
1205 {
1206   loadSelectedState(true);
1207 }
1208
1209 /*!
1210   \brief Rename the selected object.
1211 */
1212 void PVGUI_Module::onRename()
1213 {
1214   LightApp_SelectionMgr* aSelectionMgr = getApp()->selectionMgr();
1215   SALOME_ListIO aListIO;
1216   aSelectionMgr->selectedObjects(aListIO);
1217   
1218   if (aListIO.Extent() == 1 && aListIO.First()->hasEntry()) {
1219     std::string entry = aListIO.First()->getEntry();
1220     
1221     // Get SALOMEDS client study 
1222     _PTR(Study) studyDS = PARAVIS::GetCStudy(this);
1223     if(!studyDS) {
1224       return;
1225     }
1226     
1227     // Unlock the study if it is locked
1228     bool isLocked = studyDS->GetProperties()->IsLocked();
1229     if (isLocked) {
1230       studyDS->GetProperties()->SetLocked(false);
1231     }
1232     
1233     // Rename the selected state object
1234     _PTR(SObject) stateSObj = studyDS->FindObjectID(entry);
1235     if (!stateSObj) {
1236       return;
1237     }
1238     
1239     _PTR(GenericAttribute) anAttr;
1240     if (stateSObj->FindAttribute(anAttr, "AttributeName")) {
1241       _PTR(AttributeName) nameAttr (anAttr);
1242       QString newName = 
1243           LightApp_NameDlg::getName(getApp()->desktop(), nameAttr->Value().c_str());
1244       if (!newName.isEmpty()) {
1245         nameAttr->SetValue(newName.toLatin1().constData());
1246         aListIO.First()->setName(newName.toLatin1().constData());
1247       }
1248     }
1249     
1250     // Lock the study back if necessary
1251     if (isLocked) {
1252       studyDS->GetProperties()->SetLocked(true);
1253     }
1254     
1255     // Update object browser
1256     updateObjBrowser();
1257     
1258   }
1259 }
1260
1261 /*!
1262   \brief Delete the selected objects.
1263 */
1264 void PVGUI_Module::onDelete()
1265 {
1266   LightApp_SelectionMgr* aSelectionMgr = getApp()->selectionMgr();
1267   SALOME_ListIO aListIO;
1268   aSelectionMgr->selectedObjects(aListIO);
1269   
1270   if (aListIO.Extent() == 1 && aListIO.First()->hasEntry()) {
1271     std::string entry = aListIO.First()->getEntry();
1272     
1273     // Get SALOMEDS client study 
1274     _PTR(Study) studyDS = PARAVIS::GetCStudy(this);
1275     if(!studyDS) {
1276       return;
1277     }
1278     
1279     // Unlock the study if it is locked
1280     bool isLocked = studyDS->GetProperties()->IsLocked();
1281     if (isLocked) {
1282       studyDS->GetProperties()->SetLocked(false);
1283     }
1284     
1285     // Remove the selected state from the study
1286     _PTR(StudyBuilder) studyBuilder = studyDS->NewBuilder();
1287     _PTR(SObject) stateSObj = studyDS->FindObjectID(entry);
1288     studyBuilder->RemoveObject(stateSObj);
1289     
1290     // Lock the study back if necessary
1291     if (isLocked) {
1292       studyDS->GetProperties()->SetLocked(true);
1293     }
1294     
1295     // Update object browser
1296     updateObjBrowser();
1297   }
1298 }
1299
1300 /*!
1301  * \brief Slot called everytime the Python trace is pushed onto the CORBA engine.
1302  */
1303 void PVGUI_Module::onPushTraceTimer()
1304 {
1305   //MESSAGE("onPushTraceTimer(): Pushing trace to engine...");
1306   GetEngine()->PutPythonTraceStringToEngine(getTraceString().toStdString().c_str());
1307 }
1308
1309 /*!
1310   \brief Discover help project files from the resources.
1311   \return name of the help file. 
1312 */
1313 QString PVGUI_Module::getHelpFileName() {
1314   QString aPVHome(getenv("PVHOME"));
1315   if (aPVHome.isNull()) {
1316     qWarning("Wariable PVHOME is not defined");
1317     return QString();
1318   }
1319   QChar aSep = QDir::separator();
1320   //PARAVIEW_VERSION from the vtkPVConfig.h file
1321   QString aFileName =  aPVHome + aSep + "share" + aSep + "doc" + aSep + "paraview-"+ PARAVIEW_VERSION + aSep + "paraview.qch";
1322   return aFileName;
1323 }
1324
1325
1326 /*!
1327   \brief Load selected paraview state
1328
1329   If toClear == true, the current state will be cleared
1330 */
1331 void PVGUI_Module::loadSelectedState(bool toClear)
1332 {
1333   QString fileName;
1334
1335   LightApp_SelectionMgr* aSelectionMgr = getApp()->selectionMgr();
1336   SALOME_ListIO aListIO;
1337   aSelectionMgr->selectedObjects(aListIO);
1338   
1339   if (aListIO.Extent() == 1 && aListIO.First()->hasEntry()) {
1340     std::string entry = aListIO.First()->getEntry();
1341     
1342     // Get SALOMEDS client study 
1343     _PTR(Study) studyDS = PARAVIS::GetCStudy(this);
1344     if(!studyDS) {
1345       return;
1346     }
1347
1348     // Check local id
1349     _PTR(SObject) stateSObj = studyDS->FindObjectID(entry);
1350     _PTR(GenericAttribute) anAttr;
1351     if (!stateSObj->FindAttribute(anAttr, "AttributeLocalID")) {
1352       return;
1353     }
1354     _PTR(AttributeLocalID) anID(anAttr);
1355     if (!anID->Value() == PVSTATEID) {
1356       return;
1357     }
1358
1359     // Get state file name
1360     if (stateSObj->FindAttribute(anAttr, "AttributeString")) {
1361       _PTR(AttributeString) aStringAttr(anAttr);
1362       QString stringValue(aStringAttr->Value().c_str());
1363
1364       if (QFile::exists(stringValue)) {
1365           fileName = stringValue;
1366       }
1367     }
1368   }
1369   
1370   if (!fileName.isEmpty()) {
1371     if (toClear) {
1372       clearParaviewState();
1373     }
1374
1375     loadParaviewState(fileName.toLatin1().constData());
1376   } 
1377   else {
1378     SUIT_MessageBox::critical(getApp()->desktop(),
1379                               tr("ERR_ERROR"),
1380                               tr("ERR_STATE_CANNOT_BE_RESTORED"));
1381   }
1382 }
1383
1384 /*!
1385   \fn CAM_Module* createModule();
1386   \brief Export module instance (factory function).
1387   \return new created instance of the module
1388 */
1389
1390 #ifdef WNT
1391 #define PVGUI_EXPORT __declspec(dllexport)
1392 #else   // WNT
1393 #define PVGUI_EXPORT
1394 #endif  // WNT
1395
1396 extern "C" {
1397
1398   bool flag = false;
1399   PVGUI_EXPORT CAM_Module* createModule() {
1400     return new PVGUI_Module();
1401   }
1402   
1403   PVGUI_EXPORT char* getModuleVersion() {
1404     return (char*)PARAVIS_VERSION_STR;
1405   }
1406 }