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