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