]> SALOME platform Git repositories - modules/paravis.git/blob - src/PVGUI/PVGUI_Module.cxx
Salome HOME
8b57095616b160e65f6e3e3ca3921745d700b6c2
[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 // Author : Julia DOROVSKIKH
23
24 #include <Standard_math.hxx>  // E.A. must be included before Python.h to fix compilation on windows
25 #ifdef HAVE_FINITE
26 #undef HAVE_FINITE            // VSR: avoid compilation warning on Linux : "HAVE_FINITE" redefined
27 #endif
28 #include <vtkPython.h> // Python first
29 #include "PVGUI_Module.h"
30
31 #ifdef PARAVIS_WITH_FULL_CORBA
32 # include "PARAVIS_Gen_i.hh"
33 #endif
34
35 //#include "PV_Tools.h"
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 #include <SUIT_DataBrowser.h>
46 #include <SUIT_Desktop.h>
47 #include <SUIT_MessageBox.h>
48 #include <SUIT_ResourceMgr.h>
49 #include <SUIT_Session.h>
50 #include <SUIT_OverrideCursor.h>
51 #include <SUIT_ExceptionHandler.h>
52
53 // SALOME Includes
54 #include "SALOME_LifeCycleCORBA.hxx"
55 #include "SALOMEDS_SObject.hxx"
56
57 #include "LightApp_SelectionMgr.h"
58 #include "LightApp_NameDlg.h"
59
60 #include <SalomeApp_Application.h>
61 #include <SalomeApp_Study.h>
62 #include <SALOME_ListIO.hxx>
63 #include <SALOMEDS_Tool.hxx>
64 #include <PyInterp_Interp.h>
65 #include <PyInterp_Dispatcher.h>
66 #include <PyConsole_Console.h>
67 #include <PyConsole_Interp.h>
68
69 #include <sstream>
70
71 #include <QtxActionMenuMgr.h>
72 #include <QtxActionToolMgr.h>
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 #include <pqApplicationCore.h>
94 #include <pqPVApplicationCore.h>
95 #include <pqActiveView.h>
96 #include <pqObjectBuilder.h>
97 #include <pqOptions.h>
98 #include <pqRenderView.h>
99 #include <pqServer.h>
100 #include <pqUndoStack.h>
101 #include <pqVCRController.h>
102 #include <pqTabbedMultiViewWidget.h>
103 #include <pqPipelineSource.h>
104 #include <pqActiveObjects.h>
105 #include <vtkProcessModule.h>
106 #include <vtkSMSession.h>
107 #include <vtkPVSession.h>
108 #include <vtkPVProgressHandler.h>
109 #include <pqParaViewBehaviors.h>
110 #include <pqHelpReaction.h>
111 #include <vtkOutputWindow.h>
112 #include <pqPluginManager.h>
113 #include <pqSettings.h>
114 #include <pqPythonDialog.h>
115 #include <pqPythonManager.h>
116 #include <pqPythonShell.h>
117 #include <pqLoadDataReaction.h>
118 #include <vtkEventQtSlotConnect.h>
119 #include <pqPythonScriptEditor.h>
120 #include <pqDataRepresentation.h>
121 #include <pqPipelineRepresentation.h>
122 #include <pqLookupTableManager.h>
123 #include <pqDisplayColorWidget.h>
124 #include <pqColorToolbar.h>
125 #include <pqScalarBarVisibilityReaction.h>
126
127 #include <pqServerResource.h>
128 #include <pqServerConnectReaction.h>
129 #include <pqServerDisconnectReaction.h>
130
131 #include <pqApplicationCore.h>
132 #include <pqServerManagerObserver.h>
133 #include <vtkClientServerInterpreterInitializer.h>
134 #include <vtkPVConfig.h>
135
136 #include <PARAVIS_version.h>
137
138 #include CORBA_SERVER_HEADER(SALOME_ModuleCatalog)
139
140 //----------------------------------------------------------------------------
141 pqPVApplicationCore* PVGUI_Module::MyCoreApp = 0;
142
143 PVGUI_Module* ParavisModule = 0;
144
145 PARAVIS_ORB::PARAVIS_Gen_var PVGUI_Module::myEngine;
146
147 /*!
148   \mainpage
149
150   <h2>Building and installing PARAVIS</h2>
151   As any other SALOME module, PARAVIS requires PARAVIS_ROOT_DIR environment variable to be set to PARAVIS
152   installation directory.
153   Other variables needed for correct detection of ParaView location:
154   \li PVHOME - points at the ParaView installation directory tree
155   \li PVVERSION - number of ParaView version
156
157   It also requires common SALOME environment including GUI_ROOT_DIR and other prerequsites.
158
159
160   PARAVIS module can be launched using the following commands:
161   \li Full SALOME configuration
162   \code
163   runSalome --modules="PARAVIS"
164   \endcode
165
166   <h2>ParaView GUI integration</h2>
167   <h3>ParaView GUI integration overview</h3>
168
169   The main idea is to reuse ParaView GUI internal logic as much as possible, providing a layer 
170   between it and SALOME GUI that hides the following SALOME GUI implementation details from ParaView:
171
172   \li SALOME GUI executable and Qt event loop
173   \li SALOME GUI desktop
174   \li Dock windows areas
175   \li SALOME menu and toolbar managers
176
177   Major part of the integration is implemented in PVGUI_Module class.
178
179   <h3>ParaView client initalization</h3>
180
181   ParaView client initalization is performed when an instance of PVGUI_Module class has been created 
182   and \link PVGUI_Module::initialize() PVGUI_Module::initialize()\endlink method is called by SALOME GUI.
183   The actual client start-up is done in \link PVGUI_Module::pvInit() PVGUI_Module::pvInit()\endlink method. 
184   
185
186   <h3>Multi-view manager</h3>
187
188   SALOME GUI requires that each kind of view be implemnted with help of (at least) three classes. For ParaView multi-view manager 
189   these are:
190
191   \li PVGUI_ViewManager - view manager class
192   \li PVGUI_Viewer      - view model class
193   \li PVGUI_ViewWindow  - view window class that acts as a parent for %pqViewManager
194
195   Single instances of PVGUI_ViewManager and PVGUI_ViewWindow classes are created by \link PVGUI_Module::showView() 
196   PVGUI_Module::showView()\endlink method upon the first PARAVIS module activation. The same method hides the multi-view manager 
197   when the module is deactivated (the user switches to another module or a study is closed). 
198   A special trick is used to make PVGUI_ViewWindow the parent of %pqViewManager widget. It is created initally by %pqMainWindowCore
199   with the desktop as a parent, so when it is shown PVGUI_ViewWindow instance is passed to its setParent() method. In  
200   \link PVGUI_ViewWindow::~PVGUI_ViewWindow() PVGUI_ViewWindow::~PVGUI_ViewWindow()\endlink the parent is nullified to avoid deletion
201   of %pqViewManager widget that would break %pqMainWindowCore class.
202
203   <h3>ParaView plugins</h3>
204   ParaView server and client plugins are managed by %pqMainWindowCore slots that has full access to PARAVIS menus and toolbars. 
205   As a result they appears automatically in PARAVIS menus and toolbars if loaded successfully.
206 */
207
208 /*!
209   \class PVGUI_Module
210   \brief Implementation 
211          SALOME module wrapping ParaView GUI.
212 */
213
214
215 /*
216   Fix for the issue 21730: [CEA 596] Slice of polyhedron in PARAVIS returns no cell.
217   Wrap vtkEDFCutter filter.
218 */
219
220 extern "C" void vtkEDFCutterCS_Initialize(vtkClientServerInterpreter*);
221 static void vtkEDFHelperInit();
222
223 void vtkEDFHelperInit(vtkClientServerInterpreter* interp){
224     vtkEDFCutterCS_Initialize(interp);
225 }
226
227 void vtkEDFHelperInit() {
228     vtkClientServerInterpreterInitializer::GetInitializer()->
229         RegisterCallback(&vtkEDFHelperInit);
230 }
231
232
233   _PTR(SComponent)
234   ClientFindOrCreateParavisComponent(_PTR(Study) theStudyDocument)
235   {
236     _PTR(SComponent) aSComponent = theStudyDocument->FindComponent("PARAVIS");
237     if (!aSComponent) {
238       _PTR(StudyBuilder) aStudyBuilder = theStudyDocument->NewBuilder();
239       aStudyBuilder->NewCommand();
240       int aLocked = theStudyDocument->GetProperties()->IsLocked();
241       if (aLocked) theStudyDocument->GetProperties()->SetLocked(false);
242       aSComponent = aStudyBuilder->NewComponent("PARAVIS");
243       _PTR(GenericAttribute) anAttr =
244         aStudyBuilder->FindOrCreateAttribute(aSComponent, "AttributeName");
245       _PTR(AttributeName) aName (anAttr);
246
247       //CORBA::ORB_var anORB = PARAVIS::PARAVIS_Gen_i::GetORB();
248       int dnu;
249       CORBA::ORB_var anORB = CORBA::ORB_init(dnu, 0); // suppose ORB was already initialized
250       SALOME_NamingService *NamingService = new SALOME_NamingService( anORB );
251       CORBA::Object_var objVarN = NamingService->Resolve("/Kernel/ModulCatalog");
252       SALOME_ModuleCatalog::ModuleCatalog_var Catalogue =
253         SALOME_ModuleCatalog::ModuleCatalog::_narrow(objVarN);
254       SALOME_ModuleCatalog::Acomponent_var Comp = Catalogue->GetComponent( "PARAVIS" );
255       if (!Comp->_is_nil()) {
256         aName->SetValue(Comp->componentusername());
257       }
258
259       anAttr = aStudyBuilder->FindOrCreateAttribute(aSComponent, "AttributePixMap");
260       _PTR(AttributePixMap) aPixmap (anAttr);
261       aPixmap->SetPixMap( "pqAppIcon16.png" );
262
263       // Create Attribute parameters for future using
264       anAttr = aStudyBuilder->FindOrCreateAttribute(aSComponent, "AttributeParameter");
265
266       aStudyBuilder->DefineComponentInstance(aSComponent, PVGUI_Module::GetEngine()->GetIOR());
267       if (aLocked) theStudyDocument->GetProperties()->SetLocked(true);
268       aStudyBuilder->CommitCommand();
269     }
270     return aSComponent;
271   }
272
273 /*!
274   Clean up function; used to stop ParaView progress events when
275   exception is caught by global exception handler.
276 */
277 void paravisCleanUp()
278 {
279   if ( pqApplicationCore::instance() ) {
280     pqServer* s = pqApplicationCore::instance()->getActiveServer();
281     if ( s ) s->session()->GetProgressHandler()->CleanupPendingProgress();
282   }
283 }
284
285 /*!
286   \brief Constructor. Sets the default name for the module.
287 */
288 PVGUI_Module::PVGUI_Module()
289   : SalomeApp_Module( "PARAVIS" ),
290     mySelectionControlsTb( -1 ),
291     mySourcesMenuId( -1 ),
292     myFiltersMenuId( -1 ),
293     myMacrosMenuId(-1),
294     myToolbarsMenuId(-1),
295     myRecentMenuId(-1),
296     myOldMsgHandler(0),
297     myTraceWindow(0),
298     myStateCounter(0),
299     myInitTimer(0),
300     myPushTraceTimer(0)
301 {
302 #ifdef HAS_PV_DOC
303   Q_INIT_RESOURCE( PVGUI );
304 #endif
305   ParavisModule = this;
306
307   // Clear old copies of embedded macros files
308   QString aDestPath = QString( "%1/.config/%2/Macros" ).arg( QDir::homePath() ).arg( QApplication::applicationName() );
309   QStringList aFilter;
310   aFilter << "*.py";
311
312   QDir aDestDir(aDestPath);
313   QStringList aDestFiles = aDestDir.entryList(aFilter, QDir::Files);
314   foreach (QString aMacrosPath, getEmbeddedMacrosList()) {
315     QString aMacrosName = QFileInfo(aMacrosPath).fileName();
316     if (aDestFiles.contains(aMacrosName)) {
317       aDestDir.remove(aMacrosName);
318     }
319   }
320 }
321
322 /*!
323   \brief Destructor.
324 */
325 PVGUI_Module::~PVGUI_Module()
326 {
327   if (myPushTraceTimer)
328     delete myPushTraceTimer;
329   if (myInitTimer)
330     delete myInitTimer;
331   // Disconnect from server
332   pqServer* server = pqActiveObjects::instance().activeServer();
333   if (server && server->isRemote())
334     {
335       MESSAGE("~PVGUI_Module(): Disconnecting from remote server ...");
336       pqServerDisconnectReaction::disconnectFromServer();
337     }
338 }
339
340 PARAVIS_ORB::PARAVIS_Gen_var PVGUI_Module::GetEngine()
341 {
342   // initialize PARAVIS module engine (load, if necessary)
343   if ( CORBA::is_nil( myEngine ) ) {
344     Engines::EngineComponent_var comp =
345         SalomeApp_Application::lcc()->FindOrLoad_Component( "FactoryServer", "PARAVIS" );
346     myEngine = PARAVIS_ORB::PARAVIS_Gen::_narrow( comp );
347   }
348   return myEngine;
349 }
350
351 /*!
352   \brief Initialize module. Creates menus, prepares context menu, etc.
353   \param app SALOME GUI application instance
354 */
355 void PVGUI_Module::initialize( CAM_Application* app )
356 {
357   SalomeApp_Module::initialize( app );
358
359   // Create ParaViS actions
360   createActions();
361   // Create ParaViS menus
362   createMenus();
363
364   // Uncomment to debug ParaView initialization
365   // "aa" used instead of "i" as GDB doesn't like "i" variables :)
366   /*
367   int aa = 1;
368   while( aa ){
369     aa = aa;
370   }
371   */
372   
373   // Initialize ParaView client
374   pvInit();
375
376   // Create GUI elements (menus, toolbars, dock widgets)
377   SalomeApp_Application* anApp = getApp();
378   SUIT_Desktop* aDesktop = anApp->desktop();
379
380   // Remember current state of desktop toolbars
381   QList<QToolBar*> foreignToolbars = aDesktop->findChildren<QToolBar*>();
382
383   setupDockWidgets();
384
385   pvCreateActions();
386   pvCreateToolBars();
387   pvCreateMenus();
388
389   QList<QDockWidget*> activeDocks = aDesktop->findChildren<QDockWidget*>();
390   QList<QMenu*> activeMenus = aDesktop->findChildren<QMenu*>();
391
392   PVGUI_Behaviors * behav = new PVGUI_Behaviors(this);
393   behav->instanciateAllBehaviors(aDesktop);
394
395   // Setup quick-launch shortcuts.
396   QShortcut *ctrlSpace = new QShortcut(Qt::CTRL + Qt::Key_Space, aDesktop);
397   QObject::connect(ctrlSpace, SIGNAL(activated()),
398     pqApplicationCore::instance(), SLOT(quickLaunch()));
399
400   // Find Plugin Dock Widgets
401   QList<QDockWidget*> currentDocks = aDesktop->findChildren<QDockWidget*>();
402   QList<QDockWidget*>::iterator i;
403   for (i = currentDocks.begin(); i != currentDocks.end(); ++i) {
404     if(!activeDocks.contains(*i)) {
405       myDockWidgets[*i] = false; // hidden by default
406       (*i)->hide();
407     }
408   }
409
410   // Find Plugin Menus
411   QList<QMenu*> currentMenus = aDesktop->findChildren<QMenu*>();
412   QList<QMenu*>::iterator im;
413   for (im = currentMenus.begin(); im != currentMenus.end(); ++im) {
414     if(!activeMenus.contains(*im)) {
415         myMenus.append(*im);
416     }
417   }
418
419   SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr();
420   QString aPath = resMgr->stringValue("resources", "PARAVIS", QString());
421   if (!aPath.isNull()) {
422     MyCoreApp->loadConfiguration(aPath + QDir::separator() + "ParaViewFilters.xml");
423     MyCoreApp->loadConfiguration(aPath + QDir::separator() + "ParaViewReaders.xml");
424     MyCoreApp->loadConfiguration(aPath + QDir::separator() + "ParaViewSources.xml");
425     MyCoreApp->loadConfiguration(aPath + QDir::separator() + "ParaViewWriters.xml");
426   }
427
428   // Force creation of the PARAVIS engine
429   GetEngine();
430   updateObjBrowser();
431
432   // Find created toolbars
433   QCoreApplication::processEvents();
434
435   QList<QToolBar*> allToolbars = aDesktop->findChildren<QToolBar*>();
436   foreach(QToolBar* aBar, allToolbars) {
437     if (!foreignToolbars.contains(aBar)) {
438       myToolbars[aBar] = true;
439       myToolbarBreaks[aBar] = false;
440       aBar->setVisible(false);
441       aBar->toggleViewAction()->setVisible(false);
442     }
443   }
444
445   updateMacros();
446  
447   // we need to start trace after connection is done
448   connect(pqApplicationCore::instance()->getObjectBuilder(), SIGNAL(finishedAddingServer(pqServer*)), 
449           this, SLOT(onFinishedAddingServer(pqServer*)));
450
451   connect(pqApplicationCore::instance()->getObjectBuilder(), SIGNAL(dataRepresentationCreated(pqDataRepresentation*)), 
452           this, SLOT(onDataRepresentationCreated(pqDataRepresentation*)));
453
454   SUIT_ResourceMgr* aResourceMgr = SUIT_Session::session()->resourceMgr();
455   bool isStop = aResourceMgr->booleanValue( "PARAVIS", "stop_trace", false );
456   if(!isStop)
457     {
458       // Start a timer to schedule asap:
459       //  - the connection to the server
460       //  - the trace start
461       myInitTimer = new QTimer(aDesktop);
462       QObject::connect(myInitTimer, SIGNAL(timeout()), this, SLOT(onInitTimer()) );
463       myInitTimer->setSingleShot(true);
464       myInitTimer->start(0);
465
466       // Another timer to regularly push the trace onto the engine:
467       myPushTraceTimer = new QTimer(aDesktop);
468       QObject::connect(myPushTraceTimer, SIGNAL(timeout()), this, SLOT(onPushTraceTimer()) );
469       myPushTraceTimer->setSingleShot(false);
470       myPushTraceTimer->start(500);
471     }
472
473   this->VTKConnect = vtkEventQtSlotConnect::New();
474   
475   vtkProcessModule* pm = vtkProcessModule::GetProcessModule();
476   if(pm) {
477     vtkPVSession* pvs = dynamic_cast<vtkPVSession*>(pm->GetSession());
478     if(pvs) {
479       vtkPVProgressHandler* ph = pvs->GetProgressHandler();
480       if(ph) {
481           this->VTKConnect->Connect(ph, vtkCommand::StartEvent,
482                                     this, SLOT(onStartProgress()));
483           this->VTKConnect->Connect(ph, vtkCommand::EndEvent,
484                                     this, SLOT(onEndProgress()));
485       }
486     }
487   }
488   
489   connect(&pqActiveObjects::instance(),
490           SIGNAL(representationChanged(pqRepresentation*)),
491           this, SLOT(onRepresentationChanged(pqRepresentation*)));
492 }
493
494 bool PVGUI_Module::connectToExternalPVServer()
495 {
496   pqServer* server = pqActiveObjects::instance().activeServer();
497   if (server && server->isRemote())
498     {
499       // Already connected to an external server, do nothing
500       MESSAGE("connectToExternalPVServer(): Already connected to an external PVServer, won't reconnect.");
501       return false;
502     }
503
504   std::stringstream msg;
505
506   // Try to connect to the external PVServer - gives priority to an externally specified URL:
507   QString serverUrlEnv = getenv("PARAVIS_PVSERVER_URL");
508   std::string serverUrl;
509   if (!serverUrlEnv.isEmpty())
510     serverUrl = serverUrlEnv.toStdString();
511   else
512     {
513       // Get the URL from the engine (possibly starting the pvserver)
514       CORBA::String_var url = GetEngine()->FindOrStartPVServer(0);  // take the first free port
515       serverUrl = (char *)url;
516     }
517
518   msg << "connectToExternalPVServer(): Trying to connect to the external PVServer '" << serverUrl << "' ...";
519   MESSAGE(msg.str());
520
521   if (!pqServerConnectReaction::connectToServer(pqServerResource(serverUrl.c_str())))
522     {
523       std::stringstream msg2;
524       msg2 << "Error while connecting to the requested pvserver '" << serverUrl;
525       msg2 << "'. Might use default built-in connection instead!" << std::endl;
526       qWarning(msg2.str().c_str());  // will go to the ParaView console (see ParavisMessageOutput below)
527       SUIT_MessageBox::warning( getApp()->desktop(),
528                                 QString("Error connecting to PVServer"), QString(msg2.str().c_str()));
529       return false;
530     }
531   else
532     MESSAGE("connectToExternalPVServer(): Connected!");
533   return true;
534 }
535
536 void PVGUI_Module::onStartProgress()
537 {
538   QApplication::setOverrideCursor(Qt::WaitCursor);
539 }
540
541 void PVGUI_Module::onEndProgress()
542 {
543   QApplication::restoreOverrideCursor();
544 }
545
546 void PVGUI_Module::onFinishedAddingServer(pqServer* /*server*/)
547 {
548   SUIT_ResourceMgr* aResourceMgr = SUIT_Session::session()->resourceMgr();
549   bool isStop = aResourceMgr->booleanValue( "PARAVIS", "stop_trace", false );
550   if(!isStop) 
551     startTimer( 500 );
552 }
553
554 void PVGUI_Module::onDataRepresentationCreated(pqDataRepresentation* data) {
555   if(!data)
556     return;
557   
558   if(!data->getLookupTable())
559     return;
560   
561   SUIT_ResourceMgr* aResourceMgr = SUIT_Session::session()->resourceMgr();
562   if(!aResourceMgr)
563     return;
564
565   bool visible = aResourceMgr->booleanValue( "PARAVIS", "show_color_legend", false );
566   pqLookupTableManager* lut_mgr = pqApplicationCore::instance()->getLookupTableManager();
567   
568   if(lut_mgr) {
569     lut_mgr->setScalarBarVisibility(data,visible);
570   }
571
572   connect(data, SIGNAL(dataUpdated()), this, SLOT(onDataRepresentationUpdated()));
573 }
574
575 void PVGUI_Module::onDataRepresentationUpdated() {
576   SalomeApp_Study* activeStudy = dynamic_cast<SalomeApp_Study*>(application()->activeStudy());
577   if(!activeStudy) return;
578   
579   activeStudy->Modified();
580 }
581
582 void PVGUI_Module::onVariableChanged(pqVariableType t, const QString) {
583   
584   pqDisplayColorWidget* colorWidget = qobject_cast<pqDisplayColorWidget*>(sender());
585   if( !colorWidget )
586     return;
587
588   if( t == VARIABLE_TYPE_NONE )
589     return;
590
591   SUIT_ResourceMgr* aResourceMgr = SUIT_Session::session()->resourceMgr();
592   
593   if(!aResourceMgr)
594     return;
595
596   bool visible = aResourceMgr->booleanValue( "PARAVIS", "show_color_legend", false );
597   
598   if(!visible)
599     return;
600   
601   /*//VTN: getRepresentation is protected
602   pqDataRepresentation* data  = colorWidget->getRepresentation();
603
604   if( !data->getLookupTable() )
605     return;
606
607   pqLookupTableManager* lut_mgr = pqApplicationCore::instance()->getLookupTableManager();
608
609   if(lut_mgr) {
610     lut_mgr->setScalarBarVisibility(data,visible);
611   }
612   */
613   pqColorToolbar* colorTooBar = qobject_cast<pqColorToolbar*>(colorWidget->parent());
614   if( !colorTooBar )
615     return;
616
617   pqScalarBarVisibilityReaction* scalarBarVisibility = colorTooBar->findChild<pqScalarBarVisibilityReaction *>();
618   if(scalarBarVisibility) {
619     scalarBarVisibility->setScalarBarVisibility(visible);
620   }
621 }
622
623 void PVGUI_Module::execPythonCommand(const QString& cmd, bool inSalomeConsole)
624 {
625   if ( inSalomeConsole ) {
626     if ( PyInterp_Dispatcher::Get()->IsBusy() ) return;
627     SalomeApp_Application* app =
628       dynamic_cast< SalomeApp_Application* >(SUIT_Session::session()->activeApplication());
629     PyConsole_Console* pyConsole = app->pythonConsole();
630     if (pyConsole)
631       pyConsole->exec(cmd);
632   }
633   else
634     {
635       SalomeApp_Application* app =
636             dynamic_cast< SalomeApp_Application* >(SUIT_Session::session()->activeApplication());
637       PyConsole_Interp* pyInterp = app->pythonConsole()->getInterp();
638       PyLockWrapper aGil;
639       pyInterp->run(cmd.toStdString().c_str());
640 //      pqPythonManager* manager = qobject_cast<pqPythonManager*>
641 //      ( pqApplicationCore::instance()->manager( "PYTHON_MANAGER" ) );
642 //      if ( manager )
643 //        {
644 //          pqPythonDialog* pyDiag = manager->pythonShellDialog();
645 //          if ( pyDiag )
646 //            {
647 //              pqPythonShell* shell = pyDiag->shell();
648 //              if ( shell ) {
649 //                  shell->executeScript(cmd);
650 //              }
651 //            }
652 //        }
653     }
654 }
655
656 /*!
657   \brief Initialisation timer event - fired only once, after the GUI loop is ready.
658   See creation in initialize().
659 */
660 void PVGUI_Module::onInitTimer()
661 {
662 #ifndef PARAVIS_WITH_FULL_CORBA
663   connectToExternalPVServer();
664 #endif
665
666 #ifndef WNT
667 //  if ( PyInterp_Dispatcher::Get()->IsBusy() )
668 //    {
669 //      // Reschedule for later
670 //      MESSAGE("interpreter busy -> rescheduling trace start.");
671 //      startTimer(500);
672 //    }
673 //  else
674 //    {
675       MESSAGE("timerEvent(): About to start trace....");
676       execPythonCommand("from paraview import smtrace;smtrace.start_trace()", false);
677       MESSAGE("timerEvent(): Trace STARTED....");
678 //    }
679 #endif
680
681   MESSAGE("initialize(): Initializing PARAVIS's Python context ...");
682   execPythonCommand("import paraview.servermanager as sm; sm.fromGUI=True", false);
683   MESSAGE("initialize(): Initialized.");
684 }
685   
686 /*!
687   \brief Get list of embedded macros files
688 */
689 QStringList PVGUI_Module::getEmbeddedMacrosList()
690 {
691   QString aRootDir = getenv("PARAVIS_ROOT_DIR");
692
693   QString aSourcePath = aRootDir + "/bin/salome/Macro";
694
695   QStringList aFilter;
696   aFilter << "*.py";
697
698   QDir aSourceDir(aSourcePath);
699   QStringList aSourceFiles = aSourceDir.entryList(aFilter, QDir::Files);
700   QStringList aFullPathSourceFiles;
701   foreach (QString aMacrosName, aSourceFiles) {
702     aFullPathSourceFiles << aSourceDir.absoluteFilePath(aMacrosName);
703   }
704   return aFullPathSourceFiles;
705 }
706
707 void PVGUI_Module::updateMacros()
708 {
709   pqPythonManager* aPythonManager = pqPVApplicationCore::instance()->pythonManager();
710   if(!aPythonManager)  {
711     return;
712   }
713   
714   foreach (QString aStr, getEmbeddedMacrosList()) {
715     aPythonManager->addMacro(aStr);
716   }
717 }
718
719
720 /*!
721   \brief Get list of compliant dockable GUI elements
722   \param m map to be filled in ("type":"default_position")
723 */
724 void PVGUI_Module::windows( QMap<int, int>& m ) const
725 {
726   m.insert( LightApp_Application::WT_ObjectBrowser, Qt::LeftDockWidgetArea );
727   m.insert( LightApp_Application::WT_PyConsole, Qt::BottomDockWidgetArea );
728   // ParaView diagnostic output redirected here
729   m.insert( LightApp_Application::WT_LogWindow, Qt::BottomDockWidgetArea );
730 }
731
732 /*!
733   \brief Static method, performs initialization of ParaView session.
734   \return \c true if ParaView has been initialized successfully, otherwise false
735 */
736 bool PVGUI_Module::pvInit()
737 {
738   //  if ( !pqImplementation::Core ){
739   if ( ! MyCoreApp) {
740     // Obtain command-line arguments
741     int argc = 0;
742     char** argv = 0;
743     QString aOptions = getenv("PARAVIS_OPTIONS");
744     QStringList aOptList = aOptions.split(":", QString::SkipEmptyParts);
745     argv = new char*[aOptList.size() + 1];
746     QStringList args = QApplication::arguments();
747     argv[0] = (args.size() > 0)? strdup(args[0].toLatin1().constData()) : strdup("paravis");
748     argc++;
749
750     foreach (QString aStr, aOptList) {
751       argv[argc] = strdup( aStr.toLatin1().constData() );
752       argc++;
753     }
754     MyCoreApp = new pqPVApplicationCore (argc, argv);
755     if (MyCoreApp->getOptions()->GetHelpSelected() ||
756         MyCoreApp->getOptions()->GetUnknownArgument() ||
757         MyCoreApp->getOptions()->GetErrorMessage() ||
758         MyCoreApp->getOptions()->GetTellVersion()) {
759       return false;
760       }
761
762     /* VTN: Looks like trash. For porting see branded_paraview_initializer.cxx.in
763     // Not sure why this is needed. Andy added this ages ago with comment saying
764     // needed for Mac apps. Need to check that it's indeed still required.
765     QDir dir(QApplication::applicationDirPath());
766     dir.cdUp();
767     dir.cd("Plugins");
768     QApplication::addLibraryPath(dir.absolutePath());
769     // Load required application plugins.
770     QString plugin_string = "";
771     QStringList plugin_list = plugin_string.split(';',QString::SkipEmptyParts);
772     pqBrandPluginsLoader loader;
773     if (loader.loadPlugins(plugin_list) == false) {
774       printf("Failed to load required plugins for this application\n");
775       return false;
776     }
777
778     // Load optional plugins.
779     plugin_string = "";
780     plugin_list = plugin_string.split(';',QString::SkipEmptyParts);
781     loader.loadPlugins(plugin_list, true); //quietly skip not-found plugins.
782     */
783     // End of Initializer code
784
785     vtkOutputWindow::SetInstance(PVGUI_OutputWindowAdapter::New());
786     
787     new pqTabbedMultiViewWidget(); // it registers as "MULTIVIEW_WIDGET on creation
788     
789     for (int i = 0; i < argc; i++)
790       free(argv[i]);
791     delete[] argv;
792   }
793   
794   return true;
795 }
796  
797 /*!
798   \brief Shows (toShow = true) or hides ParaView view window
799 */
800 void PVGUI_Module::showView( bool toShow )
801 {
802   SalomeApp_Application* anApp = getApp();
803   PVGUI_ViewManager* viewMgr =
804     dynamic_cast<PVGUI_ViewManager*>( anApp->getViewManager( PVGUI_Viewer::Type(), false ) );
805   if ( !viewMgr ) {
806     viewMgr = new PVGUI_ViewManager( anApp->activeStudy(), anApp->desktop() );
807     anApp->addViewManager( viewMgr );
808     connect( viewMgr, SIGNAL( lastViewClosed( SUIT_ViewManager* ) ),
809              anApp, SLOT( onCloseView( SUIT_ViewManager* ) ) );
810   }
811
812   PVGUI_ViewWindow* pvWnd = dynamic_cast<PVGUI_ViewWindow*>( viewMgr->getActiveView() );
813   if ( !pvWnd ) {
814     pvWnd = dynamic_cast<PVGUI_ViewWindow*>( viewMgr->createViewWindow() );
815   }
816
817   pvWnd->setShown( toShow );
818   if ( toShow ) pvWnd->setFocus();
819 }
820
821 /*!
822   \brief Slot to show help for proxy.
823 */
824 void PVGUI_Module::showHelpForProxy( const QString& groupname, const QString& proxyname )
825 {
826   pqHelpReaction::showProxyHelp(groupname, proxyname);
827 }
828
829
830 /*!
831   \brief Slot to show the waiting state.
832 */
833 void PVGUI_Module::onPreAccept()
834 {
835   getApp()->desktop()->statusBar()->showMessage(tr("STB_PREACCEPT"));
836   QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
837 }
838
839 /*!
840   \brief Slot to show the ready state.
841 */
842 void PVGUI_Module::onPostAccept()
843 {
844   getApp()->desktop()->statusBar()->showMessage(tr("STB_POSTACCEPT"), 2000);
845   QTimer::singleShot(0, this, SLOT(endWaitCursor()));
846 }
847
848 /*!
849   \brief Slot to switch off wait cursor.
850 */
851 void PVGUI_Module::endWaitCursor()
852 {
853   QApplication::restoreOverrideCursor();
854 }
855
856 /*!
857   \brief Returns the ParaView multi-view manager.
858 */
859 pqTabbedMultiViewWidget* PVGUI_Module::getMultiViewManager() const
860 {
861   return qobject_cast<pqTabbedMultiViewWidget*>(pqApplicationCore::instance()->manager("MULTIVIEW_WIDGET"));
862 }
863
864
865 static void ParavisMessageOutput(QtMsgType type, const char *msg)
866 {
867   switch(type)
868     {
869   case QtDebugMsg:
870     vtkOutputWindow::GetInstance()->DisplayText(msg);
871     break;
872   case QtWarningMsg:
873     vtkOutputWindow::GetInstance()->DisplayErrorText(msg);
874     break;
875   case QtCriticalMsg:
876     vtkOutputWindow::GetInstance()->DisplayErrorText(msg);
877     break;
878   case QtFatalMsg:
879     vtkOutputWindow::GetInstance()->DisplayErrorText(msg);
880     break;
881     }
882 }
883
884
885
886 /*!
887   \brief Activate module.
888   \param study current study
889   \return \c true if activaion is done successfully or 0 to prevent
890   activation on error
891 */
892 bool PVGUI_Module::activateModule( SUIT_Study* study )
893 {
894   myOldMsgHandler = qInstallMsgHandler(ParavisMessageOutput);
895   
896   SUIT_ExceptionHandler::addCleanUpRoutine( paravisCleanUp );
897
898   storeCommonWindowsState();
899
900   bool isDone = SalomeApp_Module::activateModule( study );
901   if ( !isDone ) return false;
902
903   showView( true );
904   if ( mySourcesMenuId != -1 ) menuMgr()->show(mySourcesMenuId);
905   if ( myFiltersMenuId != -1 ) menuMgr()->show(myFiltersMenuId);
906   if ( myFiltersMenuId != -1 ) menuMgr()->show(myMacrosMenuId);
907   if ( myFiltersMenuId != -1 ) menuMgr()->show(myToolbarsMenuId);
908   setMenuShown( true );
909   setToolShown( true );
910
911   restoreDockWidgetsState();
912
913   QMenu* aMenu = menuMgr()->findMenu( myRecentMenuId );
914   if(aMenu) {
915     QList<QAction*> anActns = aMenu->actions();
916     for (int i = 0; i < anActns.size(); ++i) {
917       QAction* a = anActns.at(i);
918       if(a)
919         a->setVisible(true);
920     }
921   }
922
923   QList<QMenu*>::iterator it;
924   for (it = myMenus.begin(); it != myMenus.end(); ++it) {
925     QAction* a = (*it)->menuAction();
926     if(a)
927       a->setVisible(true);
928   }
929
930   if ( myRecentMenuId != -1 ) menuMgr()->show(myRecentMenuId);
931
932   ClientFindOrCreateParavisComponent(PARAVIS::GetCStudy(this));
933
934   return isDone;
935 }
936
937
938 /*!
939   \brief Deactivate module.
940   \param study current study
941   \return \c true if deactivaion is done successfully or 0 to prevent
942   deactivation on error
943 */
944 bool PVGUI_Module::deactivateModule( SUIT_Study* study )
945 {
946   MESSAGE("PARAVIS deactivation ...")
947
948   QMenu* aMenu = menuMgr()->findMenu( myRecentMenuId );
949   if(aMenu) {
950     QList<QAction*> anActns = aMenu->actions();
951     for (int i = 0; i < anActns.size(); ++i) {
952       QAction* a = anActns.at(i);
953       if(a)
954         a->setVisible(false);
955     }
956   }
957
958   QList<QMenu*>::iterator it;
959   for (it = myMenus.begin(); it != myMenus.end(); ++it) {
960     QAction* a = (*it)->menuAction();
961     if(a)
962       a->setVisible(false);
963   }
964
965   QList<QDockWidget*> aStreamingViews = application()->desktop()->findChildren<QDockWidget*>("pqStreamingControls");
966   foreach(QDockWidget* aView, aStreamingViews) {
967     if (!myDockWidgets.contains(aView))
968       myDockWidgets[aView] = aView->isVisible();
969   }
970
971   /*if (pqImplementation::helpWindow) {
972     pqImplementation::helpWindow->hide();
973     }*/
974   showView( false );
975   // hide menus
976   menuMgr()->hide(myRecentMenuId);
977   menuMgr()->hide(mySourcesMenuId);
978   menuMgr()->hide(myFiltersMenuId);
979   menuMgr()->hide(myMacrosMenuId);
980   menuMgr()->hide(myToolbarsMenuId);
981   setMenuShown( false );
982   setToolShown( false );
983
984   saveDockWidgetsState();
985
986   SUIT_ExceptionHandler::removeCleanUpRoutine( paravisCleanUp );
987
988   if (myOldMsgHandler)
989     qInstallMsgHandler(myOldMsgHandler);
990
991   restoreCommonWindowsState();
992   
993   return SalomeApp_Module::deactivateModule( study );
994 }
995
996
997 /*!
998   \brief Called when application is closed.
999
1000   Process finalize application functionality from ParaView in order to save server settings
1001   and nullify application pointer if the application is being closed.
1002
1003   \param theApp application
1004 */
1005 void PVGUI_Module::onApplicationClosed( SUIT_Application* theApp )
1006 {
1007   pqApplicationCore::instance()->settings()->sync();
1008   int aAppsNb = SUIT_Session::session()->applications().size();
1009   if (aAppsNb == 1) {
1010     deleteTemporaryFiles();
1011     MyCoreApp->deleteLater();
1012   }
1013   CAM_Module::onApplicationClosed(theApp);
1014 }
1015
1016
1017 /*!
1018   \brief Deletes temporary files created during import operation from VISU
1019 */
1020 void PVGUI_Module::deleteTemporaryFiles()
1021 {
1022   foreach(QString aFile, myTemporaryFiles) {
1023     if (QFile::exists(aFile)) {
1024       QFile::remove(aFile);
1025     }
1026   }
1027 }
1028
1029
1030 /*!
1031   \brief Called when study is closed.
1032
1033   Removes data model from the \a study.
1034
1035   \param study study being closed
1036 */
1037 void PVGUI_Module::studyClosed(SUIT_Study* study)
1038 {
1039   clearParaviewState();
1040
1041   SalomeApp_Module::studyClosed(study);
1042 }
1043
1044 /*!
1045   \brief Called when study is opened.
1046 */
1047 void PVGUI_Module::onModelOpened()
1048 {
1049   _PTR(Study) studyDS = PARAVIS::GetCStudy(this);
1050   if(!studyDS) {
1051     return;
1052   }
1053   
1054   _PTR(SComponent) paravisComp = 
1055     studyDS->FindComponent(GetEngine()->ComponentDataType());
1056   if(!paravisComp) {
1057     return;
1058   }
1059
1060   _PTR(ChildIterator) anIter(studyDS->NewChildIterator(paravisComp));
1061   for (; anIter->More(); anIter->Next()) {
1062     _PTR(SObject) aSObj = anIter->Value();
1063     _PTR(GenericAttribute) anAttr;
1064     if (!aSObj->FindAttribute(anAttr, "AttributeLocalID")) {
1065       continue;
1066     }
1067     _PTR(AttributeLocalID) anID(anAttr);
1068     if (anID->Value() == PVSTATEID) {
1069       myStateCounter++;
1070     }
1071   }
1072 }
1073
1074 /*!
1075   \brief Returns IOR of current engine
1076 */
1077 QString PVGUI_Module::engineIOR() const
1078 {
1079   CORBA::String_var anIOR = GetEngine()->GetIOR();
1080   return QString(anIOR.in());
1081 }
1082
1083
1084 /*!
1085   \brief Open file of format supported by ParaView
1086 */
1087 void PVGUI_Module::openFile(const char* theName)
1088 {
1089   QStringList aFiles;
1090   aFiles<<theName;
1091   pqLoadDataReaction::loadData(aFiles);
1092 }
1093
1094 void PVGUI_Module::executeScript(const char *script)
1095 {
1096 #ifndef WNT
1097   pqPythonManager* manager = qobject_cast<pqPythonManager*>(
1098                              pqApplicationCore::instance()->manager("PYTHON_MANAGER"));
1099   if (manager)  {
1100     pqPythonDialog* pyDiag = manager->pythonShellDialog();
1101     if (pyDiag) {
1102       pyDiag->runString(script);  
1103       }
1104     }
1105 #endif
1106 }
1107
1108 ///**
1109 // *  Debug function printing out the given interpreter's execution context
1110 // */
1111 //void printInterpContext(PyInterp_Interp * interp )
1112 //{
1113 //  // Extract __smtraceString from interpreter's context
1114 //  const PyObject* ctxt = interp->getExecutionContext();
1115 //
1116 //  PyObject* lst = PyDict_Keys((PyObject *)ctxt);
1117 //  Py_ssize_t siz = PyList_GET_SIZE(lst);
1118 //  for (Py_ssize_t i = 0; i < siz; i++)
1119 //    {
1120 //      PyObject * elem = PyList_GetItem(lst, i);
1121 //      if (PyString_Check(elem))
1122 //        {
1123 //          std::cout << "At pos:" << i << ", " << PyString_AsString(elem) << std::endl;
1124 //        }
1125 //      else
1126 //        std::cout << "At pos:" << i << ", not a string!" << std::endl;
1127 //    }
1128 //  Py_XDECREF(lst);
1129 //}
1130
1131 /*!
1132   \brief Returns trace string
1133 */
1134 static const QString MYReplaceStr("paraview.simple");
1135 static const QString MYReplaceImportStr("except: from pvsimple import *");
1136 QString PVGUI_Module::getTraceString()
1137 {
1138   QString traceString;
1139 #ifndef WNT
1140   {
1141     PyLockWrapper lck; // Acquire GIL
1142
1143     const char * code = "from paraview import smtrace;"
1144                         "__smtraceString = smtrace.get_trace_string()";
1145     PyRun_SimpleString(code);
1146     // Now get the value of __smtraceString
1147     PyObject* main_module = PyImport_AddModule((char*)"__main__");
1148     PyObject* global_dict = PyModule_GetDict(main_module);
1149     PyObject* string_object = PyDict_GetItemString(global_dict, "__smtraceString");
1150     char* string_ptr = string_object ? PyString_AsString(string_object) : 0;
1151     if (string_ptr)  {
1152         traceString = string_ptr;
1153     }
1154   } // release GIL
1155
1156   if ((!traceString.isNull()) && traceString.length() != 0) {
1157     int aPos = traceString.indexOf(MYReplaceStr);
1158     while (aPos != -1) {
1159       traceString = traceString.replace(aPos, MYReplaceStr.length(), "pvsimple");
1160       aPos = traceString.indexOf(MYReplaceStr, aPos);
1161     }
1162     int aImportPos = traceString.indexOf(MYReplaceImportStr);
1163     if(aImportPos != -1)
1164       {
1165       traceString = traceString.replace(aImportPos, MYReplaceImportStr.length(), "except:\n  import pvsimple\n  from pvsimple import *");
1166       }
1167   }
1168 #endif
1169   return traceString;
1170 }
1171
1172 /*!
1173   \brief Saves trace string to disk file
1174 */
1175 void PVGUI_Module::saveTrace(const char* theName)
1176 {
1177   QFile file(theName);
1178   if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
1179     MESSAGE( "Could not open file:" << theName );
1180     return;
1181   }
1182   QTextStream out(&file);
1183   out << getTraceString();
1184   file.close();
1185 }
1186
1187 /*!
1188   \brief Saves ParaView state to a disk file
1189 */
1190 void PVGUI_Module::saveParaviewState(const char* theFileName)
1191 {
1192   pqApplicationCore::instance()->saveState(theFileName);
1193 }
1194
1195 /*!
1196   \brief Delete all objects for Paraview Pipeline Browser
1197 */
1198 void PVGUI_Module::clearParaviewState()
1199 {
1200   QAction* deleteAllAction = action(DeleteAllId);
1201   if (deleteAllAction) {
1202     deleteAllAction->activate(QAction::Trigger);
1203   }
1204 }
1205
1206 /*!
1207   \brief Restores ParaView state from a disk file
1208
1209   If toClear == true, the current ojects will be deleted
1210 */
1211 void PVGUI_Module::loadParaviewState(const char* theFileName)
1212 {
1213   pqApplicationCore::instance()->loadState(theFileName, getActiveServer());
1214 }
1215
1216 /*!
1217   \brief Returns current active ParaView server
1218 */
1219 pqServer* PVGUI_Module::getActiveServer()
1220 {
1221   return pqApplicationCore::instance()->getActiveServer();
1222 }
1223
1224
1225 /*!
1226   \brief Creates PARAVIS preference pane 
1227 */
1228 void PVGUI_Module::createPreferences()
1229 {
1230   // Paraview settings tab
1231   int aParaViewSettingsTab = addPreference( tr( "TIT_PVIEWSETTINGS" ) );
1232   int aPanel = addPreference(QString(), aParaViewSettingsTab, LightApp_Preferences::UserDefined, "PARAVIS", "");
1233   setPreferenceProperty(aPanel, "content", (qint64)(new PVGUI_ParaViewSettingsPane()));
1234
1235   // Paravis settings tab
1236   int aParaVisSettingsTab = addPreference( tr( "TIT_PVISSETTINGS" ) );
1237   addPreference( tr( "PREF_STOP_TRACE" ), aParaVisSettingsTab, LightApp_Preferences::Bool, "PARAVIS", "stop_trace");
1238
1239   int aSaveType = addPreference(tr( "PREF_SAVE_TYPE_LBL" ), aParaVisSettingsTab,
1240                                 LightApp_Preferences::Selector,
1241                                 "PARAVIS", "savestate_type");
1242   QList<QVariant> aIndices;
1243   QStringList aStrings;
1244   aIndices<<0<<1<<2;
1245   aStrings<<tr("PREF_SAVE_TYPE_0");
1246   aStrings<<tr("PREF_SAVE_TYPE_1");
1247   aStrings<<tr("PREF_SAVE_TYPE_2");
1248   setPreferenceProperty(aSaveType, "strings", aStrings);
1249   setPreferenceProperty(aSaveType, "indexes", aIndices);
1250
1251   //rnv: imp 21712: [CEA 581] Preference to display legend by default 
1252   int aDispColoreLegend = addPreference( tr( "PREF_SHOW_COLOR_LEGEND" ), aParaVisSettingsTab,
1253                                         LightApp_Preferences::Bool, "PARAVIS", "show_color_legend");
1254 }
1255
1256 /*!
1257   \brief Creates ParaViS context menu popup
1258 */
1259 void PVGUI_Module::contextMenuPopup(const QString& theClient, QMenu* theMenu, QString& theTitle)
1260 {
1261   SalomeApp_Module::contextMenuPopup(theClient, theMenu, theTitle);
1262   
1263   // Check if we are in Object Browser
1264   SUIT_DataBrowser* ob = getApp()->objectBrowser();
1265   bool isOBClient = (ob && theClient == ob->popupClientType());
1266   if (!isOBClient) {
1267     return;
1268   }
1269
1270   // Get list of selected objects
1271   LightApp_SelectionMgr* aSelectionMgr = getApp()->selectionMgr();
1272   SALOME_ListIO aListIO;
1273   aSelectionMgr->selectedObjects(aListIO);
1274   if (aListIO.Extent() == 1 && aListIO.First()->hasEntry()) {
1275     QString entry = QString(aListIO.First()->getEntry());
1276     
1277     // Get active study
1278     SalomeApp_Study* activeStudy = 
1279       dynamic_cast<SalomeApp_Study*>(getApp()->activeStudy());
1280     if(!activeStudy) {
1281       return;
1282     }
1283
1284     // Get SALOMEDS client study 
1285     _PTR(Study) studyDS = activeStudy->studyDS();
1286     if(!studyDS) {
1287       return;
1288     }
1289
1290     QString paravisDataType(GetEngine()->ComponentDataType());
1291     if(activeStudy && activeStudy->isComponent(entry) && 
1292        activeStudy->componentDataType(entry) == paravisDataType) {
1293       // ParaViS module object
1294       theMenu->addSeparator();
1295       theMenu->addAction(action(SaveStatePopupId));
1296     }
1297     else {
1298       // Try to get state object
1299       _PTR(SObject) stateSObj = 
1300           studyDS->FindObjectID(entry.toLatin1().constData());
1301       if (!stateSObj) {
1302           return;
1303       }
1304       
1305       // Check local id
1306       _PTR(GenericAttribute) anAttr;
1307       if (!stateSObj->FindAttribute(anAttr, "AttributeLocalID")) {
1308           return;
1309       }
1310
1311       _PTR(AttributeLocalID) anID(anAttr);
1312       
1313       if (anID->Value() == PVSTATEID) {
1314         // Paraview state object
1315         theMenu->addSeparator();
1316         theMenu->addAction(action(AddStatePopupId));
1317         theMenu->addAction(action(CleanAndAddStatePopupId));
1318         theMenu->addSeparator();
1319         theMenu->addAction(action(ParaVisRenameId));
1320         theMenu->addAction(action(ParaVisDeleteId));
1321       }
1322     }
1323   }
1324 }
1325
1326 /*!
1327   \brief. Show ParaView python trace.
1328 */
1329 void PVGUI_Module::onShowTrace()
1330 {
1331   if (!myTraceWindow) {
1332     myTraceWindow = new pqPythonScriptEditor(getApp()->desktop());
1333   }
1334   myTraceWindow->setText(getTraceString());
1335   myTraceWindow->show();
1336   myTraceWindow->raise();
1337   myTraceWindow->activateWindow();
1338 }
1339
1340
1341 /*!
1342   \brief. Re-initialize ParaView python trace.
1343 */
1344 void PVGUI_Module::onRestartTrace()
1345 {
1346   QString script = "from paraview import smtrace\n";
1347   script += "smtrace.stop_trace()\n";
1348   script += "smtrace.start_trace()\n";
1349   execPythonCommand(script, false);
1350 }
1351
1352 /*!
1353   \brief Show ParaView view.
1354 */
1355 void PVGUI_Module::onNewParaViewWindow()
1356 {
1357   showView(true);
1358 }
1359
1360 /*!
1361   \brief Save state under the module root object.
1362 */
1363 void PVGUI_Module::onSaveMultiState()
1364 {
1365   // Create state study object
1366   
1367   // Get SALOMEDS client study
1368   _PTR(Study) studyDS = PARAVIS::GetCStudy(this);
1369   if(!studyDS) {
1370     return;
1371   }
1372   
1373   _PTR(SComponent) paravisComp = 
1374     studyDS->FindComponent(GetEngine()->ComponentDataType());
1375   if(!paravisComp) {
1376     return;
1377   }
1378
1379   // Unlock the study if it is locked
1380   bool isLocked = studyDS->GetProperties()->IsLocked();
1381   if (isLocked) {
1382     studyDS->GetProperties()->SetLocked(false);
1383   }
1384   
1385   QString stateName = tr("SAVED_PARAVIEW_STATE_NAME") + 
1386     QString::number(myStateCounter + 1);
1387
1388   _PTR(StudyBuilder) studyBuilder = studyDS->NewBuilder();
1389   _PTR(SObject) newSObj = studyBuilder->NewObject(paravisComp);
1390
1391   // Set name
1392   _PTR(GenericAttribute) anAttr;
1393   anAttr = studyBuilder->FindOrCreateAttribute(newSObj, "AttributeName");
1394   _PTR(AttributeName) nameAttr(anAttr);
1395   
1396   nameAttr->SetValue(stateName.toLatin1().constData());
1397
1398   // Set local id
1399   anAttr = studyBuilder->FindOrCreateAttribute(newSObj, "AttributeLocalID");
1400   _PTR(AttributeLocalID) localIdAttr(anAttr);
1401   
1402   localIdAttr->SetValue(PVSTATEID);
1403
1404   // Set file name
1405   QString stateEntry = QString::fromStdString(newSObj->GetID());
1406  
1407   // File name for state saving
1408   QString tmpDir = QString::fromStdString(SALOMEDS_Tool::GetTmpDir());
1409   QString fileName = QString("%1_paravisstate:%2").arg(tmpDir, stateEntry);
1410
1411   anAttr = studyBuilder->FindOrCreateAttribute(newSObj, "AttributeString");
1412   _PTR(AttributeString) stringAttr(anAttr);
1413   
1414   stringAttr->SetValue(fileName.toLatin1().constData());
1415
1416   // Lock the study back if necessary
1417   if (isLocked) {
1418     studyDS->GetProperties()->SetLocked(true);
1419   }
1420   
1421   // Save state
1422   saveParaviewState(fileName.toLatin1().constData());
1423   myTemporaryFiles.append(fileName);
1424   
1425   // Increment the counter
1426   myStateCounter++;
1427
1428   updateObjBrowser();
1429 }
1430
1431 /*!
1432   \brief Restore the selected state by merging with the current one.
1433 */
1434 void PVGUI_Module::onAddState()
1435 {
1436   loadSelectedState(false);
1437 }
1438
1439 /*!
1440   \brief Clean the current state and restore the selected one.
1441 */
1442 void PVGUI_Module::onCleanAddState()
1443 {
1444   loadSelectedState(true);
1445 }
1446
1447 /*!
1448   \brief Rename the selected object.
1449 */
1450 void PVGUI_Module::onRename()
1451 {
1452   LightApp_SelectionMgr* aSelectionMgr = getApp()->selectionMgr();
1453   SALOME_ListIO aListIO;
1454   aSelectionMgr->selectedObjects(aListIO);
1455   
1456   if (aListIO.Extent() == 1 && aListIO.First()->hasEntry()) {
1457     std::string entry = aListIO.First()->getEntry();
1458     
1459     // Get SALOMEDS client study 
1460     _PTR(Study) studyDS = PARAVIS::GetCStudy(this);
1461     if(!studyDS) {
1462       return;
1463     }
1464     
1465     // Unlock the study if it is locked
1466     bool isLocked = studyDS->GetProperties()->IsLocked();
1467     if (isLocked) {
1468       studyDS->GetProperties()->SetLocked(false);
1469     }
1470     
1471     // Rename the selected state object
1472     _PTR(SObject) stateSObj = studyDS->FindObjectID(entry);
1473     if (!stateSObj) {
1474       return;
1475     }
1476     
1477     _PTR(GenericAttribute) anAttr;
1478     if (stateSObj->FindAttribute(anAttr, "AttributeName")) {
1479       _PTR(AttributeName) nameAttr (anAttr);
1480       QString newName = 
1481           LightApp_NameDlg::getName(getApp()->desktop(), nameAttr->Value().c_str());
1482       if (!newName.isEmpty()) {
1483         nameAttr->SetValue(newName.toLatin1().constData());
1484         aListIO.First()->setName(newName.toLatin1().constData());
1485       }
1486     }
1487     
1488     // Lock the study back if necessary
1489     if (isLocked) {
1490       studyDS->GetProperties()->SetLocked(true);
1491     }
1492     
1493     // Update object browser
1494     updateObjBrowser();
1495     
1496   }
1497 }
1498
1499 /*!
1500   \brief Delete the selected objects.
1501 */
1502 void PVGUI_Module::onDelete()
1503 {
1504   LightApp_SelectionMgr* aSelectionMgr = getApp()->selectionMgr();
1505   SALOME_ListIO aListIO;
1506   aSelectionMgr->selectedObjects(aListIO);
1507   
1508   if (aListIO.Extent() == 1 && aListIO.First()->hasEntry()) {
1509     std::string entry = aListIO.First()->getEntry();
1510     
1511     // Get SALOMEDS client study 
1512     _PTR(Study) studyDS = PARAVIS::GetCStudy(this);
1513     if(!studyDS) {
1514       return;
1515     }
1516     
1517     // Unlock the study if it is locked
1518     bool isLocked = studyDS->GetProperties()->IsLocked();
1519     if (isLocked) {
1520       studyDS->GetProperties()->SetLocked(false);
1521     }
1522     
1523     // Remove the selected state from the study
1524     _PTR(StudyBuilder) studyBuilder = studyDS->NewBuilder();
1525     _PTR(SObject) stateSObj = studyDS->FindObjectID(entry);
1526     studyBuilder->RemoveObject(stateSObj);
1527     
1528     // Lock the study back if necessary
1529     if (isLocked) {
1530       studyDS->GetProperties()->SetLocked(true);
1531     }
1532     
1533     // Update object browser
1534     updateObjBrowser();
1535   }
1536 }
1537
1538 void PVGUI_Module::onPushTraceTimer()
1539 {
1540 //  MESSAGE("onPushTraceTimer(): Pushing trace to engine...");
1541   GetEngine()->PutPythonTraceStringToEngine(getTraceString().toStdString().c_str());
1542 }
1543
1544 /*!
1545   \brief Discover help project files from the resources.
1546   \return name of the help file. 
1547 */
1548 QString PVGUI_Module::getHelpFileName() {
1549   QString aPVHome(getenv("PVHOME"));
1550   if (aPVHome.isNull()) {
1551     qWarning("Wariable PVHOME is not defined");
1552     return QString();
1553   }
1554   QChar aSep = QDir::separator();
1555   //PARAVIEW_VERSION from the vtkPVConfig.h file
1556   QString aFileName =  aPVHome + aSep + "share" + aSep + "doc" + aSep + "paraview-"+ PARAVIEW_VERSION + aSep + "paraview.qch";
1557   return aFileName;
1558 }
1559
1560
1561 /*!
1562   \brief Load selected paraview state
1563
1564   If toClear == true, the current state will be cleared
1565 */
1566 void PVGUI_Module::loadSelectedState(bool toClear)
1567 {
1568   QString fileName;
1569
1570   LightApp_SelectionMgr* aSelectionMgr = getApp()->selectionMgr();
1571   SALOME_ListIO aListIO;
1572   aSelectionMgr->selectedObjects(aListIO);
1573   
1574   if (aListIO.Extent() == 1 && aListIO.First()->hasEntry()) {
1575     std::string entry = aListIO.First()->getEntry();
1576     
1577     // Get SALOMEDS client study 
1578     _PTR(Study) studyDS = PARAVIS::GetCStudy(this);
1579     if(!studyDS) {
1580       return;
1581     }
1582
1583     // Check local id
1584     _PTR(SObject) stateSObj = studyDS->FindObjectID(entry);
1585     _PTR(GenericAttribute) anAttr;
1586     if (!stateSObj->FindAttribute(anAttr, "AttributeLocalID")) {
1587       return;
1588     }
1589     _PTR(AttributeLocalID) anID(anAttr);
1590     if (!anID->Value() == PVSTATEID) {
1591       return;
1592     }
1593
1594     // Get state file name
1595     if (stateSObj->FindAttribute(anAttr, "AttributeString")) {
1596       _PTR(AttributeString) aStringAttr(anAttr);
1597       QString stringValue(aStringAttr->Value().c_str());
1598
1599       if (QFile::exists(stringValue)) {
1600           fileName = stringValue;
1601       }
1602     }
1603   }
1604   
1605   if (!fileName.isEmpty()) {
1606     if (toClear) {
1607       clearParaviewState();
1608     }
1609
1610     loadParaviewState(fileName.toLatin1().constData());
1611   } 
1612   else {
1613     SUIT_MessageBox::critical(getApp()->desktop(),
1614                               tr("ERR_ERROR"),
1615                               tr("ERR_STATE_CANNOT_BE_RESTORED"));
1616   }
1617 }
1618
1619 void PVGUI_Module::onRepresentationChanged(pqRepresentation*) {
1620
1621
1622   //rnv: to fix the issue "21712: [CEA 581] Preference to display legend by default"
1623   //     find the pqDisplayColorWidget instances and connect the variableChanged SIGNAL on the 
1624   //     onVariableChanged slot of this class. This connection needs to change visibility 
1625   //     of the "Colored Legend" after change the "Color By" array.
1626   QList<pqDisplayColorWidget*> aWidget = getApp()->desktop()->findChildren<pqDisplayColorWidget*>();
1627   
1628   for (int i = 0; i < aWidget.size() ; i++ ) {
1629     if( aWidget[i] ) {
1630       connect( aWidget[i], SIGNAL ( variableChanged ( pqVariableType, const QString ) ), 
1631               this, SLOT(onVariableChanged( pqVariableType, const QString) ), Qt::UniqueConnection );
1632     }    
1633   }
1634 }
1635
1636
1637 /*!
1638   \fn CAM_Module* createModule();
1639   \brief Export module instance (factory function).
1640   \return new created instance of the module
1641 */
1642
1643 #ifdef WNT
1644 #define PVGUI_EXPORT __declspec(dllexport)
1645 #else   // WNT
1646 #define PVGUI_EXPORT
1647 #endif  // WNT
1648
1649 extern "C" {
1650
1651   bool flag = false;
1652   PVGUI_EXPORT CAM_Module* createModule() {
1653     if(!flag) {
1654         vtkEDFHelperInit();
1655         flag = true;
1656     }      
1657     return new PVGUI_Module();
1658   }
1659   
1660   PVGUI_EXPORT char* getModuleVersion() {
1661     return (char*)PARAVIS_VERSION_STR;
1662   }
1663 }