Salome HOME
Merge from BR_PARAVIS_DEV 29Dec09
[modules/paravis.git] / src / PVGUI / PVGUI_Module.cxx
1 // PARAVIS : ParaView wrapper SALOME module
2 //
3 // Copyright (C) 2003  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License.
10 //
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 // Lesser General Public License for more details.
15 //
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22 // File   : PVGUI_Module.cxx
23 // Author : Julia DOROVSKIKH
24 //
25
26 #include "PVGUI_Module.h"
27
28 #include "SALOMEconfig.h"
29 #include CORBA_CLIENT_HEADER(VISU_Gen)
30 #include CORBA_SERVER_HEADER(SALOMEDS)
31
32
33 #include "PARAVIS_Gen_i.hh"
34
35 #include "PVGUI_Module_impl.h"
36 #include "PVGUI_ProcessModuleHelper.h"
37 #include "PVGUI_ViewModel.h"
38 #include "PVGUI_ViewManager.h"
39 #include "PVGUI_ViewWindow.h"
40 #include "PVGUI_Tools.h"
41 #include "PVGUI_Trace.h"
42
43 #include <SUIT_Desktop.h>
44 #include <SUIT_MessageBox.h>
45 #include <SUIT_ResourceMgr.h>
46 #include <SUIT_Session.h>
47 #include <SUIT_OverrideCursor.h>
48
49 // SALOME Includes
50 #include "SALOME_LifeCycleCORBA.hxx"
51 #include "SALOME_ListIteratorOfListIO.hxx"
52 #include "SALOMEDS_SObject.hxx"
53
54 //#include <LightApp_Application.h>
55 #include <LightApp_SelectionMgr.h>
56 #include <SalomeApp_Application.h>
57 #include <SalomeApp_Study.h>
58 #include <SALOME_ListIO.hxx>
59 #include <SALOMEDS_Tool.hxx>
60
61 #include <QtxActionMenuMgr.h>
62 #include <QtxActionToolMgr.h>
63
64 #include <QAction>
65 #include <QApplication>
66 #include <QCursor>
67 #include <QDir>
68 #include <QFile>
69 #include <QFileInfo>
70 #include <QIcon>
71 #include <QInputDialog>
72 #include <QStatusBar>
73 #include <QString>
74 #include <QStringList>
75 #include <QTimer>
76 #include <QToolBar>
77
78 #include <pqApplicationCore.h>
79 #include <pqActiveView.h>
80 #include <pqClientAboutDialog.h>
81 #include <pqObjectBuilder.h>
82 #include <pqOptions.h>
83 #include <pqRenderView.h>
84 #include <pqRubberBandHelper.h>
85 #include <pqServer.h>
86 //#include <pqServerManagerModel.h>
87 //#include <pqServerResource.h>
88 #include <pqUndoStack.h>
89 #include <pqVCRController.h>
90 #include <pqViewManager.h>
91 #include <pqPipelineSource.h>
92 #include <vtkPVMain.h>
93 #include <vtkProcessModule.h>
94
95 /*
96  * Make sure all the kits register their classes with vtkInstantiator.
97  * Since ParaView uses Tcl wrapping, all of VTK is already compiled in
98  * anyway.  The instantiators will add no more code for the linker to
99  * collect.
100  */
101
102 #include <vtkCommonInstantiator.h>
103 #include <vtkFilteringInstantiator.h>
104 #include <vtkGenericFilteringInstantiator.h>
105 #include <vtkIOInstantiator.h>
106 #include <vtkImagingInstantiator.h>
107 #include <vtkInfovisInstantiator.h>
108 #include <vtkGraphicsInstantiator.h>
109
110 #include <vtkRenderingInstantiator.h>
111 #include <vtkVolumeRenderingInstantiator.h>
112 #include <vtkHybridInstantiator.h>
113 #include <vtkParallelInstantiator.h>
114
115 //#include <vtkPVServerCommonInstantiator.h>
116 //#include <vtkPVFiltersInstantiator.h>
117 //#include <vtkPVServerManagerInstantiator.h>
118 //#include <vtkClientServerInterpreter.h>
119
120
121
122 //----------------------------------------------------------------------------
123 // ClientServer wrapper initialization functions.
124 // Taken from ParaView sources (file pqMain.cxx)
125 extern "C" void vtkCommonCS_Initialize(vtkClientServerInterpreter*);
126 extern "C" void vtkFilteringCS_Initialize(vtkClientServerInterpreter*);
127 extern "C" void vtkGenericFilteringCS_Initialize(vtkClientServerInterpreter*);
128 extern "C" void vtkImagingCS_Initialize(vtkClientServerInterpreter*);
129 extern "C" void vtkInfovisCS_Initialize(vtkClientServerInterpreter*);
130 extern "C" void vtkGraphicsCS_Initialize(vtkClientServerInterpreter*);
131 extern "C" void vtkIOCS_Initialize(vtkClientServerInterpreter*);
132 extern "C" void vtkRenderingCS_Initialize(vtkClientServerInterpreter*);
133 extern "C" void vtkVolumeRenderingCS_Initialize(vtkClientServerInterpreter*);
134 extern "C" void vtkHybridCS_Initialize(vtkClientServerInterpreter*);
135 extern "C" void vtkWidgetsCS_Initialize(vtkClientServerInterpreter*);
136 extern "C" void vtkParallelCS_Initialize(vtkClientServerInterpreter*);
137 extern "C" void vtkPVServerCommonCS_Initialize(vtkClientServerInterpreter*);
138 extern "C" void vtkPVFiltersCS_Initialize(vtkClientServerInterpreter*);
139 extern "C" void vtkXdmfCS_Initialize(vtkClientServerInterpreter *);
140
141
142 //----------------------------------------------------------------------------
143 void ParaViewInitializeInterpreter(vtkProcessModule* pm)
144 {
145   vtkClientServerInterpreter* interp = pm->GetInterpreter();
146   // Initialize built-in wrapper modules.
147   vtkCommonCS_Initialize(interp);
148   vtkFilteringCS_Initialize(interp);
149   vtkGenericFilteringCS_Initialize(interp);
150   vtkImagingCS_Initialize(interp);
151   vtkInfovisCS_Initialize(interp);
152   vtkGraphicsCS_Initialize(interp);
153   vtkIOCS_Initialize(interp);
154   vtkRenderingCS_Initialize(interp);
155   vtkVolumeRenderingCS_Initialize(interp);
156   vtkHybridCS_Initialize(interp);
157   vtkWidgetsCS_Initialize(interp);
158   vtkParallelCS_Initialize(interp);
159   vtkPVServerCommonCS_Initialize(interp);
160   vtkPVFiltersCS_Initialize(interp);
161   vtkXdmfCS_Initialize(interp);
162 }
163
164 vtkPVMain*                 PVGUI_Module::pqImplementation::myPVMain = 0;
165 pqOptions*                 PVGUI_Module::pqImplementation::myPVOptions = 0;
166 PVGUI_ProcessModuleHelper* PVGUI_Module::pqImplementation::myPVHelper = 0;
167
168 PVGUI_Module* ParavisModule = 0;
169
170 /*!
171   \mainpage
172
173   <h2>Building and installing PARAVIS</h2>
174   As any other SALOME module, PARAVIS requires PARAVIS_ROOT_DIR environment variable to be set to PARAVIS
175   installation directory.
176   Other variables needed for correct detection of ParaView location:
177   \li PVHOME - points at the ParaView installation directory tree
178   \li PVVERSION - number of ParaView version
179
180   It also requires common SALOME environment including GUI_ROOT_DIR and other prerequsites.
181
182   As soon as the environment is set, excute the following commands in a shell:
183   \code
184   mkdir PARAVIS_BUILD
185   cd PARAVIS_BUILD
186   ../PARAVIS_SRC/build_configure
187   ../PARAVIS_SRC/configure --prefix=${PARAVIS_ROOT_DIR} -with-paraview
188   make 
189   make docs
190   make install
191   \endcode
192
193   PARAVIS module can be launched using the following commands:
194   \li Full SALOME configuration
195   \code
196   runSalome --modules="PARAVIS"
197   \endcode
198
199   <h2>ParaView GUI integration</h2>
200   <h3>ParaView GUI integration overview</h3>
201
202   The main idea is to reuse ParaView GUI internal logic as much as possible, providing a layer 
203   between it and SALOME GUI that hides the following SALOME GUI implementation details from ParaView:
204
205   \li SALOME GUI executable and Qt event loop
206   \li SALOME GUI desktop
207   \li Dock windows areas
208   \li SALOME menu and toolbar managers
209
210   Major part of the integration is implemented in PVGUI_Module class.
211
212   <h3>ParaView client initalization</h3>
213
214   ParaView client initalization is performed when an instance of PVGUI_Module class has been created 
215   and \link PVGUI_Module::initialize() PVGUI_Module::initialize()\endlink method is called by SALOME GUI.
216   The actual client start-up is done in \link PVGUI_Module::pvInit() PVGUI_Module::pvInit()\endlink method. 
217   It simulates actions perfomed by pqMain::Run( QApplication&, pqProcessModuleGUIHelper* ) method.
218   
219   Custom PVGUI_ProcessModuleHelper class derived from %pqProcessModuleGUIHelper base is the main actor in ParaView 
220   client initialization. It initializes the client that uses the main window (SALOME desktop) supplied from the outside, 
221   it does not start Qt event loop as this is done in SALOME GUI executable (SUITApp or SALOME_Session_Server), and after all 
222   it redirects ParaView diagnostic output to SALOME LogWindow with help of PVGUI_OutputWindowAdapter class.
223   This is achieved by reimplementing \link PVGUI_ProcessModuleHelper::InitializeApplication() InitializeApplication()\endlink,
224   \link PVGUI_ProcessModuleHelper::appExec() appExec()\endlink, \link PVGUI_ProcessModuleHelper::postAppExec() postAppExec()\endlink
225   virtual methods as well as those responsible for main window management.
226
227   <h3>ParaView GUI connection to SALOME desktop</h3>
228
229   ParaView Qt components include pqMainWindowCore class that handles most ParaView GUI client actions,
230   updates menu states and connects many GUI components.
231   After the client initalization \link PVGUI_Module::initialize() PVGUI_Module::initialize()\endlink method creates
232   an instance of internal PVGUI_Module::pqImplementation class (declared PVGUI_Module_impl.h) that wraps some ParaView GUI components: 
233   pqMainWindowCore, pqServer, etc. Instance of SALOME desktop widget is passed to pqMainWindowCore instead of ParaView main window.
234
235   Basically it simulates constructor of ParaView client's %MainWindow class (src/Applications/Client/MainWindow.cxx). It creates the same
236   menu and toolbar commands using SALOME menu and toolbar managers, connecting the actions to %pqMainWindowCore slots or to the module's 
237   slots in some cases. It also sets up dock widgets for ParaView widgets, such as object inspector, pipeline browser, etc.
238
239   ParaView GUI resources (icons) are reused directly from the ParaView resource directory, they are loaded into SALOME GUI 
240   resource manager, the path to these icons is specified in PARAVIS configuration XML files (LightApp.xml and SlomeApp.xml).
241
242   As both SALOME destop and ParaView main window classes inherit QMainWindow and %pqMainWindowCore deals with QMainWindow API to control
243   menus, tollbars and dock widgets, its integration into SALOME GUI is straightforward and smooth.
244
245   <h3>Multi-view manager</h3>
246
247   SALOME GUI requires that each kind of view be implemnted with help of (at least) three classes. For ParaView multi-view manager 
248   these are:
249
250   \li PVGUI_ViewManager - view manager class
251   \li PVGUI_Viewer      - view model class
252   \li PVGUI_ViewWindow  - view window class that acts as a parent for %pqViewManager
253
254   Single instances of PVGUI_ViewManager and PVGUI_ViewWindow classes are created by \link PVGUI_Module::showView() 
255   PVGUI_Module::showView()\endlink method upon the first PARAVIS module activation. The same method hides the multi-view manager 
256   when the module is deactivated (the user switches to another module or a study is closed). 
257   A special trick is used to make PVGUI_ViewWindow the parent of %pqViewManager widget. It is created initally by %pqMainWindowCore
258   with the desktop as a parent, so when it is shown PVGUI_ViewWindow instance is passed to its setParent() method. In  
259   \link PVGUI_ViewWindow::~PVGUI_ViewWindow() PVGUI_ViewWindow::~PVGUI_ViewWindow()\endlink the parent is nullified to avoid deletion
260   of %pqViewManager widget that would break %pqMainWindowCore class.
261
262   <h3>ParaView plugins</h3>
263   ParaView server and client plugins are managed by %pqMainWindowCore slots that has full access to PARAVIS menus and toolbars. 
264   As a result they appears automatically in PARAVIS menus and toolbars if loaded successfully.
265
266   <h2>Limitations of 2008 year prototype</h2>
267   \li SALOME persistence (possibility to save the module data into a tsudy file) is not implemented for PARAVIS module.
268   \li As a light module, PARAVIS does not have a CORBA engine that follows SALOME rules, however PARAVIS can use load a CORBA engine 
269   on its own if needed.
270 */
271
272 /*!
273   \class PVGUI_Module
274   \brief Implementation of light (no-CORBA-engine) 
275          SALOME module wrapping ParaView GUI.
276 */
277
278 /*!
279   \brief Constructor. Sets the default name for the module.
280 */
281 PVGUI_Module::PVGUI_Module()
282   : SalomeApp_Module( "PARAVIS" ),
283     LightApp_Module( "PARAVIS" ),
284     Implementation( 0 ),
285     mySelectionControlsTb( -1 ),
286     mySourcesMenuId( -1 ),
287     myFiltersMenuId( -1 )
288 {
289   ParavisModule = this;
290 }
291
292 /*!
293   \brief Destructor.
294 */
295 PVGUI_Module::~PVGUI_Module()
296 {
297 }
298
299 /*!
300   \brief Initialize module. Creates menus, prepares context menu, etc.
301   \param app SALOME GUI application instance
302 */
303 void PVGUI_Module::initialize( CAM_Application* app )
304 {
305   SalomeApp_Module::initialize( app );
306
307   // Uncomment to debug ParaView initialization
308   // "aa" used instead of "i" as GDB doesn't like "i" variables :)
309   /*
310   int aa = 1;
311   while( aa ){
312     aa = aa;
313   }
314   */
315   
316   // Initialize ParaView client
317   pvInit();
318
319   // Create GUI elements (menus, toolbars, dock widgets)
320   if ( !Implementation ){
321     SalomeApp_Application* anApp = getApp();
322
323     // Simulate ParaView client main window
324     Implementation = new pqImplementation( anApp->desktop() );
325
326     setupDockWidgets();
327     
328     pvCreateActions();
329     pvCreateMenus();
330     pvCreateToolBars();
331     
332     setupDockWidgetsContextMenu();
333
334     // Now that we're ready, initialize everything ...
335     Implementation->Core.initializeStates();
336
337     // Force creation of engine
338     PARAVIS::GetParavisGen(this);
339     updateObjBrowser();
340   }
341
342   QCoreApplication::processEvents();
343
344   SUIT_ResourceMgr* aResourceMgr = SUIT_Session::session()->resourceMgr();
345   bool isStop = aResourceMgr->booleanValue( "PARAVIS", "stop_trace", false );
346   if(!isStop)
347     QTimer::singleShot(500, this, SLOT(activateTrace()));
348   //  start_trace();
349 }
350
351
352 void PVGUI_Module::activateTrace()
353 {
354   start_trace();
355 }
356
357
358
359 /*!
360   \brief Get list of compliant dockable GUI elements
361   \param m map to be filled in ("type":"default_position")
362 */
363 void PVGUI_Module::windows( QMap<int, int>& m ) const
364 {
365   m.insert( LightApp_Application::WT_ObjectBrowser, Qt::LeftDockWidgetArea );
366   m.insert( LightApp_Application::WT_PyConsole, Qt::BottomDockWidgetArea );
367   // ParaView diagnostic output redirected here
368   m.insert( LightApp_Application::WT_LogWindow, Qt::BottomDockWidgetArea );
369 }
370
371 /*!
372   \brief Static method, performs initialization of ParaView session.
373   \return \c true if ParaView has been initialized successfully, otherwise false
374 */
375 bool PVGUI_Module::pvInit()
376 {
377   if ( !pqImplementation::myPVMain ){
378     // Obtain command-line arguments
379     int argc = 0;
380     QStringList args = QApplication::arguments();
381     char** argv = new char*[args.size()];
382     for ( QStringList::const_iterator it = args.begin(); argc < 1 && it != args.end(); it++, argc++ )
383       argv[argc] = strdup( (*it).toLatin1().constData() );
384
385     vtkPVMain::SetUseMPI(0);  // pvClient never runs with MPI.
386     vtkPVMain::Initialize(&argc, &argv); // Perform any initializations.
387
388     // TODO: Set plugin dir from preferences
389     //QApplication::setLibraryPaths(QStringList(dir.absolutePath()));
390
391     pqImplementation::myPVMain = vtkPVMain::New();
392     if ( !pqImplementation::myPVOptions )
393       pqImplementation::myPVOptions = pqOptions::New();
394     if ( !pqImplementation::myPVHelper )
395       pqImplementation::myPVHelper = PVGUI_ProcessModuleHelper::New();
396
397     pqImplementation::myPVOptions->SetProcessType(vtkPVOptions::PVCLIENT);
398
399     // This creates the Process Module and initializes it.
400     int ret = pqImplementation::myPVMain->Initialize(pqImplementation::myPVOptions, 
401                                                      pqImplementation::myPVHelper, 
402                                                      ParaViewInitializeInterpreter,
403                                                      argc, argv);
404     if (!ret){
405       // Tell process module that we support Multiple connections.
406       // This must be set before starting the event loop.
407       vtkProcessModule::GetProcessModule()->SupportMultipleConnectionsOn();
408       ret = pqImplementation::myPVHelper->Run(pqImplementation::myPVOptions);
409     }
410
411     if (argc == 1)
412       free(argv[0]); // because in creation argc < 1
413     delete[] argv;
414     return !ret;
415   }
416   
417   return true;
418 }
419  
420 /*!
421   \brief Static method, cleans up ParaView session at application exit.
422 */
423 void PVGUI_Module::pvShutdown()
424 {
425   if ( pqImplementation::myPVHelper )
426     pqImplementation::myPVHelper->finalize();
427 }  
428
429 /*!
430   \brief Shows (toShow = true) or hides ParaView view window
431 */
432 void PVGUI_Module::showView( bool toShow )
433 {
434   SalomeApp_Application* anApp = getApp();
435   PVGUI_ViewManager* viewMgr = dynamic_cast<PVGUI_ViewManager*>( anApp->getViewManager( PVGUI_Viewer::Type(), false ) );
436   if ( !viewMgr ) {
437     viewMgr = new PVGUI_ViewManager( anApp->activeStudy(), anApp->desktop() );
438     anApp->addViewManager( viewMgr );
439     connect( viewMgr, SIGNAL( lastViewClosed( SUIT_ViewManager* ) ),
440              anApp, SLOT( onCloseView( SUIT_ViewManager* ) ) );
441   }
442
443   PVGUI_ViewWindow* pvWnd = dynamic_cast<PVGUI_ViewWindow*>( viewMgr->getActiveView() );
444   if ( !pvWnd ) {
445     pvWnd = dynamic_cast<PVGUI_ViewWindow*>( viewMgr->createViewWindow() );
446     pvWnd->setMultiViewManager( &Implementation->Core.multiViewManager() );
447   }
448
449   pvWnd->setShown( toShow );
450 }
451
452 /*!
453   \brief Manage the label of Undo operation.
454 */
455 void PVGUI_Module::onUndoLabel( const QString& label )
456 {
457   action(UndoId)->setText(
458     label.isEmpty() ? tr("MEN_CANTUNDO") : QString(tr("MEN_UNDO_ACTION")).arg(label));
459   action(UndoId)->setStatusTip(
460     label.isEmpty() ? tr("MEN_CANTUNDO") : QString(tr("MEN_UNDO_ACTION_TIP")).arg(label));
461 }
462
463 /*!
464   \brief Manage the label of Redo operation.
465 */
466 void PVGUI_Module::onRedoLabel( const QString& label )
467 {
468   action(RedoId)->setText(
469     label.isEmpty() ? tr("MEN_CANTREDO") : QString(tr("MEN_REDO_ACTION")).arg(label));
470   action(RedoId)->setStatusTip(
471     label.isEmpty() ? tr("MEN_CANTREDO") : QString(tr("MEN_REDO_ACTION_TIP")).arg(label));
472 }
473
474 /*!
475   \brief Manage the label of Undo Camera operation.
476 */
477 void PVGUI_Module::onCameraUndoLabel( const QString& label )
478 {
479   action(CameraUndoId)->setText(
480     label.isEmpty() ? tr("MEN_CANT_CAMERA_UNDO") : QString(tr("MEN_CAMERA_UNDO_ACTION")).arg(label));
481   action(CameraUndoId)->setStatusTip(
482     label.isEmpty() ? tr("MEN_CANT_CAMERA_UNDO") : QString(tr("MEN_CAMERA_UNDO_ACTION_TIP")).arg(label));
483 }
484
485 /*!
486   \brief Manage the label of Redo Camera operation.
487 */
488 void PVGUI_Module::onCameraRedoLabel( const QString& label )
489 {
490   action(CameraRedoId)->setText(
491     label.isEmpty() ? tr("MEN_CANT_CAMERA_REDO") : QString(tr("MEN_CAMERA_REDO_ACTION")).arg(label));
492   action(CameraRedoId)->setStatusTip(
493     label.isEmpty() ? tr("MEN_CANT_CAMERA_REDO") : QString(tr("MEN_CAMERA_REDO_ACTION_TIP")).arg(label));
494 }
495
496 /*!
497   \brief Slot to delete all objects.
498 */
499 void PVGUI_Module::onDeleteAll()
500 {
501   pqObjectBuilder* builder = pqApplicationCore::instance()->getObjectBuilder();
502   Implementation->Core.getApplicationUndoStack()->beginUndoSet("Delete All");
503   builder->destroyPipelineProxies();
504   Implementation->Core.getApplicationUndoStack()->endUndoSet();
505 }
506
507 /*!
508   \brief Slot to check/uncheck the action for corresponding selection mode.
509 */
510 void PVGUI_Module::onSelectionModeChanged( int mode )
511 {
512   if( toolMgr()->toolBar( mySelectionControlsTb )->isEnabled() ) {
513     if(mode == pqRubberBandHelper::SELECT) //surface selection
514       action(SelectCellsOnId)->setChecked(true);
515     else if(mode == pqRubberBandHelper::SELECT_POINTS) //surface selection
516       action(SelectPointsOnId)->setChecked(true);
517     else if(mode == pqRubberBandHelper::FRUSTUM)
518       action(SelectCellsThroughId)->setChecked(true);
519     else if(mode == pqRubberBandHelper::FRUSTUM_POINTS)
520       action(SelectPointsThroughId)->setChecked(true);
521     else if (mode == pqRubberBandHelper::BLOCKS)
522       action(SelectBlockId)->setChecked(true);
523     else // INTERACT
524       action(InteractId)->setChecked(true);
525   }
526 }
527
528 /*!
529   \brief Slot to manage the change of axis center.
530 */
531 void PVGUI_Module::onShowCenterAxisChanged( bool enabled )
532 {
533   action(ShowCenterId)->setEnabled(enabled);
534   action(ShowCenterId)->blockSignals(true);
535   pqRenderView* renView = qobject_cast<pqRenderView*>(
536     pqActiveView::instance().current());
537   action(ShowCenterId)->setChecked( renView ? renView->getCenterAxesVisibility() : false);
538   action(ShowCenterId)->blockSignals(false);
539 }
540
541 /*!
542   \brief Slot to set tooltips for the first anf the last frames, i.e. a time range of animation.
543 */
544 void PVGUI_Module::setTimeRanges( double start, double end )
545 {
546   action(FirstFrameId)->setToolTip(QString("First Frame (%1)").arg(start, 0, 'g'));
547   action(LastFrameId)->setToolTip(QString("Last Frame (%1)").arg(end, 0, 'g'));
548 }
549
550
551 void PVGUI_Module::connectToPlay()
552 {
553   connect( action(PlayId), SIGNAL( triggered() ), &Implementation->Core.VCRController(), SLOT( onPlay() ) );
554 }
555
556
557 /*!
558   \brief Slot to manage the plaing process of animation.
559 */
560 void PVGUI_Module::onPlaying( bool playing )
561 {
562   SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr();
563   if(playing) {
564     disconnect( action(PlayId), SIGNAL( triggered() ),&Implementation->Core.VCRController(), SLOT( onPlay() ) );
565     connect( action(PlayId), SIGNAL( triggered() ), &Implementation->Core.VCRController(), SLOT( onPause() ) );
566     action(PlayId)->setIcon(QIcon(resMgr->loadPixmap("ParaView",tr("ICON_PAUSE"),false)));
567     action(PlayId)->setText("Pa&use");
568   }
569   else {
570     // Immediate connecting toPlay doubles event
571     QTimer::singleShot(10, this, SLOT(connectToPlay()));
572     //connect( action(PlayId), SIGNAL( triggered() ), &Implementation->Core.VCRController(), SLOT( onPlay() ) );
573     disconnect( action(PlayId), SIGNAL( triggered() ), &Implementation->Core.VCRController(), SLOT( onPause() ) );
574     action(PlayId)->setIcon(QIcon(resMgr->loadPixmap("ParaView",tr("ICON_PLAY"),false)));
575     action(PlayId)->setText("&Play");
576   }
577
578   Implementation->Core.setSelectiveEnabledState(!playing);
579 }
580
581 /*!
582   \brief Slot to add camera link.
583 */
584 void PVGUI_Module::onAddCameraLink()
585 {
586   pqView* vm = pqActiveView::instance().current();
587   pqRenderView* rm = qobject_cast<pqRenderView*>(vm);
588   if(rm) rm->linkToOtherView();
589   else SUIT_MessageBox::warning(getApp()->desktop(),
590                                 tr("WARNING"), tr("WRN_ADD_CAMERA_LINK"));
591 }
592
593 /*!
594   \brief Slot to show information about ParaView.
595 */
596 void PVGUI_Module::onHelpAbout()
597 {
598   pqClientAboutDialog* const dialog = new pqClientAboutDialog(getApp()->desktop());
599   dialog->setAttribute(Qt::WA_DeleteOnClose);
600   dialog->show();
601 }
602
603 /*!
604   \brief Slot to show native ParaView user documentation.
605 */
606 void PVGUI_Module::onParaViewHelp()
607 {
608   showHelpForProxy("index");
609 }
610
611 /*!
612   \brief Slot to show help for proxy.
613 */
614 void PVGUI_Module::showHelpForProxy( const QString& proxy )
615 {
616   // make sure assistant is ready
617   this->makeAssistant();
618
619   if(this->Implementation->myHelpWindow) {
620     this->Implementation->myHelpWindow->show();
621     this->Implementation->myHelpWindow->raise();
622   }
623   /*  if(this->Implementation->AssistantClient) {
624     this->Implementation->AssistantClient->openAssistant();
625     QString page("%1/Documentation/%2.html");
626     page = page.arg(this->Implementation->DocumentationDir);
627     page = page.arg(proxy);
628     this->Implementation->AssistantClient->showPage(page);
629     }*/
630 }
631
632 QString Locate( const QString& appName )
633 {
634   QString app_dir = QCoreApplication::applicationDirPath();
635   const char* inst_dirs[] = {
636     "/./",
637     "/../bin/",
638     "/../../bin/",
639     0
640   };
641   for (const char** dir = inst_dirs; *dir; ++dir) {
642     QString path = app_dir;
643     path += *dir;
644     path += appName;
645     //cout << "Checking : " << path.toAscii().data() << " ... ";
646     //cout.flush();
647     QFileInfo finfo (path);
648     if (finfo.exists()) {
649       //cout << " Success!" << endl;
650       return path;
651     }
652     //cout << " Failed" << endl;
653   }
654   return app_dir + QDir::separator() + appName;
655 }
656
657 /*!
658   \brief Initialized an assistant client.
659 */
660 void PVGUI_Module::makeAssistant()
661 {
662   if (this->Implementation->myHelpWindow)
663     return;
664
665   pqHelpWindow* helpWindow = new pqHelpWindow("ParaView Online Help", getApp()->desktop());
666   QObject::connect(helpWindow, SIGNAL(helpWarnings(const QString&)),
667                    this, SLOT(assistantError(const QString&)));
668   helpWindow->registerDocumentation(":/ParaViewResources/pqClient.qch");
669   this->Implementation->myHelpWindow = helpWindow;
670   this->Implementation->myHelpWindow->showPage("qthelp://paraview.org/paraview/Documentation/index.html");
671 }
672
673 /*!
674   \brief Slot to call the message handler with the critical message.
675 */
676 void PVGUI_Module::assistantError( const QString& error )
677 {
678   qCritical(error.toAscii().data());
679 }
680
681 /*!
682   \brief Slot to show the waiting state.
683 */
684 void PVGUI_Module::onPreAccept()
685 {
686   getApp()->desktop()->statusBar()->showMessage(tr("STB_PREACCEPT"));
687   QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
688 }
689
690 /*!
691   \brief Slot to show the ready state.
692 */
693 void PVGUI_Module::onPostAccept()
694 {
695   getApp()->desktop()->statusBar()->showMessage(tr("STB_POSTACCEPT"), 2000);
696   QTimer::singleShot(0, this, SLOT(endWaitCursor()));
697 }
698
699 /*!
700   \brief Slot to switch off wait cursor.
701 */
702 void PVGUI_Module::endWaitCursor()
703 {
704   QApplication::restoreOverrideCursor();
705 }
706
707 /*!
708   \brief Returns the ParaView multi-view manager.
709 */
710 pqViewManager* PVGUI_Module::getMultiViewManager() const
711 {
712   pqViewManager* aMVM = 0; 
713   if ( Implementation )
714     aMVM = &Implementation->Core.multiViewManager();
715   return aMVM;
716 }
717
718 /*!
719   \brief Processes QEvent::ActionAdded and QEvent::ActionRemoved from Lookmarks toolbar
720   in order to register/unregister this action in/from QtxActionToolMgr.
721 */
722 bool PVGUI_Module::eventFilter( QObject* theObject, QEvent* theEvent )
723 {
724   QToolBar* aTB = toolMgr()->toolBar(tr("TOOL_LOOKMARKS"));
725   if ( theObject == aTB ) {
726     
727     if ( theEvent->type() == QEvent::ActionAdded ) {
728       QList<QAction*> anActns = aTB->actions();
729       for (int i = 0; i < anActns.size(); ++i)
730         if ( toolMgr()->actionId(anActns.at(i)) == -1 ) {
731           toolMgr()->setUpdatesEnabled(false);
732           createTool( anActns.at(i), tr("TOOL_LOOKMARKS") );
733           toolMgr()->setUpdatesEnabled(true);
734         }
735     }
736
737     if ( theEvent->type() == QEvent::ActionRemoved ) {
738       QList<QAction*> anActns = aTB->actions();
739       QIntList aIDL = toolMgr()->idList();
740       for (int i = 0; i < aIDL.size(); ++i) {
741         if ( toolMgr()->action(aIDL.at(i))->parent() == aTB
742              &&
743              !anActns.contains( toolMgr()->action(aIDL.at(i)) ) ) {
744           toolMgr()->setUpdatesEnabled(false);
745           toolMgr()->unRegisterAction( aIDL.at(i) );
746           toolMgr()->remove( aIDL.at(i), tr("TOOL_LOOKMARKS") );
747           toolMgr()->setUpdatesEnabled(true);
748         }
749       }
750     }
751     
752   }
753
754   return QObject::eventFilter( theObject, theEvent );
755 }
756
757 /*!
758   \brief Activate module.
759   \param study current study
760   \return \c true if activaion is done successfully or 0 to prevent
761   activation on error
762 */
763 bool PVGUI_Module::activateModule( SUIT_Study* study )
764 {
765   bool isDone = SalomeApp_Module::activateModule( study );
766   if ( !isDone ) return false;
767
768   showView( true );
769
770   if ( mySourcesMenuId != -1 ) menuMgr()->show(mySourcesMenuId);
771   if ( myFiltersMenuId != -1 ) menuMgr()->show(myFiltersMenuId);
772   setMenuShown( true );
773   setToolShown( true );
774
775   toolMgr()->toolBar(tr("TOOL_LOOKMARKS"))->installEventFilter(this);
776
777   // Make default server connection
778   if ( Implementation )
779     Implementation->Core.makeDefaultConnectionIfNoneExists();
780
781   restoreDockWidgetsState();
782
783   return isDone;
784 }
785
786
787 /*!
788   \brief Deactivate module.
789   \param study current study
790   \return \c true if deactivaion is done successfully or 0 to prevent
791   deactivation on error
792 */
793 bool PVGUI_Module::deactivateModule( SUIT_Study* study )
794 {
795   toolMgr()->toolBar(tr("TOOL_LOOKMARKS"))->removeEventFilter(this);
796
797   showView( false );
798
799   // hide menus
800   menuMgr()->hide(mySourcesMenuId);
801   menuMgr()->hide(myFiltersMenuId);
802   setMenuShown( false );
803   setToolShown( false );
804
805   saveDockWidgetsState();
806
807   return SalomeApp_Module::deactivateModule( study );
808 }
809
810 /*!
811   \brief Called when application is closed.
812
813   Process finalize application functionality from ParaView in order to save server settings
814   and nullify application pointer if the application is being closed.
815
816   \param theApp application
817 */
818 void PVGUI_Module::onApplicationClosed( SUIT_Application* theApp )
819 {
820   int aAppsNb = SUIT_Session::session()->applications().size();
821   if (aAppsNb == 1) {
822     deleteTemporaryFiles();
823     pvShutdown();
824   }
825   CAM_Module::onApplicationClosed(theApp);
826 }
827
828 /*!
829   \brief Compares the contents of the window with the given reference image,
830   returns true if they "match" within some tolerance.
831 */
832 bool PVGUI_Module::compareView( const QString& ReferenceImage, double Threshold,
833                                 std::ostream& Output, const QString& TempDirectory )
834 {
835   if ( Implementation )
836     return Implementation->Core.compareView( ReferenceImage, Threshold, Output, TempDirectory );
837   return false;
838 }
839
840 QString PVGUI_Module::engineIOR() const
841 {
842   CORBA::String_var anIOR = PARAVIS::GetParavisGen(this)->GetIOR();
843   return QString(anIOR.in());
844 }
845
846 void PVGUI_Module::onOpenFile()
847 {
848   // This avoids an immediate exception on wrong MED file opening
849   Implementation->Core.onFileOpen();
850 }
851
852 /*!
853   \brief Open file of format supported by ParaView
854 */
855 void PVGUI_Module::openFile(const char* theName)
856 {
857   QStringList aFiles;
858   aFiles<<theName;
859   Implementation->Core.createReaderOnActiveServer(aFiles);
860 }
861
862 /*!
863   \brief Returns trace string
864 */
865 QString PVGUI_Module::printTrace()
866 {
867   return get_trace_string();
868 }
869
870 /*!
871   \brief Saves trace string to disk file
872 */
873 void PVGUI_Module::saveTrace(const char* theName)
874 {
875   save_trace(theName);
876 }
877
878 /*!
879   \brief Saves ParaView state to a disk file
880 */
881 void PVGUI_Module::saveParaviewState(const char* theFileName)
882 {
883   QStringList aFiles;
884   aFiles<<theFileName;
885   Implementation->Core.onFileSaveServerState(aFiles);
886 }
887
888 /*!
889   \brief Restores ParaView state from a disk file
890 */
891 void PVGUI_Module::loadParaviewState(const char* theFileName)
892 {
893   QStringList aFiles;
894   aFiles<<theFileName;
895   Implementation->Core.onFileLoadServerState(aFiles);
896 }
897
898 /*!
899   \brief Imports MED data from VISU module by data entry
900 */
901 void PVGUI_Module::onImportFromVisu(QString theEntry)
902 {
903   SUIT_OverrideCursor aWaitCursor;
904
905   // get active study
906   SalomeApp_Study* activeStudy = dynamic_cast<SalomeApp_Study*>(application()->activeStudy());
907   if(!activeStudy) return;
908
909   // get SALOMEDS client study 
910   _PTR(Study) aStudy = activeStudy->studyDS();
911   if(!aStudy) return;
912
913   // find VISU component in a study
914   _PTR(SComponent) aVisuComp = aStudy->FindComponent( "VISU" );
915   if(!aVisuComp) return;
916
917   // get SObject client by entry
918   _PTR(SObject) aSObj = aStudy->FindObjectID(qPrintable(theEntry));
919   if (!aSObj) return;
920
921   // get CORBA SObject
922   SALOMEDS_SObject* aSObject = _CAST(SObject, aSObj);
923   if ( !aSObject ) return;
924
925   // load VISU engine
926   SALOME_NamingService* aNamingService = SalomeApp_Application::namingService();
927   SALOME_LifeCycleCORBA aLCC(aNamingService);
928
929   Engines::Component_var aComponent = aLCC.FindOrLoad_Component("FactoryServer","VISU");
930   VISU::VISU_Gen_var aVISU = VISU::VISU_Gen::_narrow(aComponent);
931   if(CORBA::is_nil(aVISU)) return;
932
933   _PTR(StudyBuilder) aStudyBuilder = aStudy->NewBuilder();
934   aStudyBuilder->LoadWith( aVisuComp, SalomeApp_Application::orb()->object_to_string(aVISU) );
935
936   // set current study to VISU engine
937   //aVISU->SetCurrentStudy(aStudyVar);
938
939   // get VISU result object
940   CORBA::Object_var aResultObject = aSObject->GetObject();
941   if (CORBA::is_nil(aResultObject)) return;
942   VISU::Result_var aResult = VISU::Result::_narrow( aResultObject );
943   if (CORBA::is_nil(aResult)) return;
944
945   // export VISU result to the MED file
946   std::string aTmpDir = SALOMEDS_Tool::GetTmpDir();
947   std::string aFileName = aSObject->GetName();
948   std::string aFilePath = aTmpDir + aFileName;
949
950   if (aResult->ExportMED(aFilePath.c_str())) {
951     openFile(aFilePath.c_str());
952     myTemporaryFiles.append(QString(aFilePath.c_str()));
953   }
954 }
955
956 /*!
957   \brief Deletes temporary files created during import operation from VISU
958 */
959 void PVGUI_Module::deleteTemporaryFiles()
960 {
961   foreach(QString aFile, myTemporaryFiles) {
962     if (QFile::exists(aFile)) {
963       QFile::remove(aFile);
964     }
965   }
966 }
967
968
969 /*!
970   \brief Returns current active ParaView server
971 */
972 pqServer* PVGUI_Module::getActiveServer()
973 {
974   return Implementation->Core.getActiveServer();
975 }
976
977
978 /*!
979   \brief Creates PARAVIS preference pane 
980 */
981 void PVGUI_Module::createPreferences()
982 {
983   int TraceTab = addPreference( tr( "TIT_TRACE" ) );
984   addPreference( tr( "PREF_STOP_TRACE" ), TraceTab, LightApp_Preferences::Bool, "PARAVIS", "stop_trace");
985 }
986
987
988
989 /*!
990   \fn CAM_Module* createModule();
991   \brief Export module instance (factory function).
992   \return new created instance of the module
993 */
994
995 #ifdef WNT
996 #define PVGUI_EXPORT __declspec(dllexport)
997 #else   // WNT
998 #define PVGUI_EXPORT
999 #endif  // WNT
1000
1001 extern "C" {
1002   PVGUI_EXPORT CAM_Module* createModule() {
1003     return new PVGUI_Module();
1004   }
1005 }