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