Salome HOME
Sample servers configuration file.
[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 #include "PVGUI_Module_impl.h"
28 #include "PVGUI_ProcessModuleHelper.h"
29 #include "PVGUI_ViewModel.h"
30 #include "PVGUI_ViewManager.h"
31 #include "PVGUI_ViewWindow.h"
32
33 #include <SUIT_Desktop.h>
34 #include <SUIT_MessageBox.h>
35 #include <SUIT_ResourceMgr.h>
36 #include <SUIT_Session.h>
37 #include <LightApp_Application.h>
38 #include <LightApp_SelectionMgr.h>
39 #include <QtxActionMenuMgr.h>
40 #include <QtxActionToolMgr.h>
41
42 #include <QAction>
43 #include <QApplication>
44 #include <QCursor>
45 #include <QDir>
46 #include <QFile>
47 #include <QFileInfo>
48 #include <QIcon>
49 #include <QInputDialog>
50 #include <QStatusBar>
51 #include <QString>
52 #include <QStringList>
53 #include <QTimer>
54 #include <QToolBar>
55
56 #include <pqApplicationCore.h>
57 #include <pqActiveServer.h>
58 #include <pqActiveView.h>
59 #include <pqClientAboutDialog.h>
60 #include <pqObjectBuilder.h>
61 #include <pqOptions.h>
62 #include <pqRenderView.h>
63 #include <pqRubberBandHelper.h>
64 #include <pqServer.h>
65 #include <pqServerManagerModel.h>
66 #include <pqServerResource.h>
67 #include <pqUndoStack.h>
68 #include <pqVCRController.h>
69 #include <pqViewManager.h>
70 #include <vtkPVMain.h>
71 #include <vtkProcessModule.h>
72
73 /*
74  * Make sure all the kits register their classes with vtkInstantiator.
75  * Since ParaView uses Tcl wrapping, all of VTK is already compiled in
76  * anyway.  The instantiators will add no more code for the linker to
77  * collect.
78  */
79
80 #include <vtkCommonInstantiator.h>
81 #include <vtkFilteringInstantiator.h>
82 #include <vtkGenericFilteringInstantiator.h>
83 #include <vtkIOInstantiator.h>
84 #include <vtkImagingInstantiator.h>
85 #include <vtkInfovisInstantiator.h>
86 #include <vtkGraphicsInstantiator.h>
87
88 #include <vtkRenderingInstantiator.h>
89 #include <vtkVolumeRenderingInstantiator.h>
90 #include <vtkHybridInstantiator.h>
91 #include <vtkParallelInstantiator.h>
92
93 #include <vtkPVServerCommonInstantiator.h>
94 #include <vtkPVFiltersInstantiator.h>
95 #include <vtkPVServerManagerInstantiator.h>
96 #include <vtkClientServerInterpreter.h>
97
98
99 //----------------------------------------------------------------------------
100 // ClientServer wrapper initialization functions.
101 // Taken from ParaView sources (file pqMain.cxx)
102 extern "C" void vtkCommonCS_Initialize(vtkClientServerInterpreter*);
103 extern "C" void vtkFilteringCS_Initialize(vtkClientServerInterpreter*);
104 extern "C" void vtkGenericFilteringCS_Initialize(vtkClientServerInterpreter*);
105 extern "C" void vtkImagingCS_Initialize(vtkClientServerInterpreter*);
106 extern "C" void vtkInfovisCS_Initialize(vtkClientServerInterpreter*);
107 extern "C" void vtkGraphicsCS_Initialize(vtkClientServerInterpreter*);
108 extern "C" void vtkIOCS_Initialize(vtkClientServerInterpreter*);
109 extern "C" void vtkRenderingCS_Initialize(vtkClientServerInterpreter*);
110 extern "C" void vtkVolumeRenderingCS_Initialize(vtkClientServerInterpreter*);
111 extern "C" void vtkHybridCS_Initialize(vtkClientServerInterpreter*);
112 extern "C" void vtkWidgetsCS_Initialize(vtkClientServerInterpreter*);
113 extern "C" void vtkParallelCS_Initialize(vtkClientServerInterpreter*);
114 extern "C" void vtkPVServerCommonCS_Initialize(vtkClientServerInterpreter*);
115 extern "C" void vtkPVFiltersCS_Initialize(vtkClientServerInterpreter*);
116 extern "C" void vtkXdmfCS_Initialize(vtkClientServerInterpreter *);
117
118 //----------------------------------------------------------------------------
119 void ParaViewInitializeInterpreter(vtkProcessModule* pm)
120 {
121   // Initialize built-in wrapper modules.
122   vtkCommonCS_Initialize(pm->GetInterpreter());
123   vtkFilteringCS_Initialize(pm->GetInterpreter());
124   vtkGenericFilteringCS_Initialize(pm->GetInterpreter());
125   vtkImagingCS_Initialize(pm->GetInterpreter());
126   vtkInfovisCS_Initialize(pm->GetInterpreter());
127   vtkGraphicsCS_Initialize(pm->GetInterpreter());
128   vtkIOCS_Initialize(pm->GetInterpreter());
129   vtkRenderingCS_Initialize(pm->GetInterpreter());
130   vtkVolumeRenderingCS_Initialize(pm->GetInterpreter());
131   vtkHybridCS_Initialize(pm->GetInterpreter());
132   vtkWidgetsCS_Initialize(pm->GetInterpreter());
133   vtkParallelCS_Initialize(pm->GetInterpreter());
134   vtkPVServerCommonCS_Initialize(pm->GetInterpreter());
135   vtkPVFiltersCS_Initialize(pm->GetInterpreter());
136   vtkXdmfCS_Initialize(pm->GetInterpreter());
137 }
138
139 vtkPVMain*                 PVGUI_Module::pqImplementation::myPVMain = 0;
140 pqOptions*                 PVGUI_Module::pqImplementation::myPVOptions = 0;
141 PVGUI_ProcessModuleHelper* PVGUI_Module::pqImplementation::myPVHelper = 0;
142
143 /*!
144   \class PVGUI_Module
145   \brief Implementation of light (no-CORBA-engine) 
146          SALOME module wrapping ParaView GUI.
147 */
148
149 /*!
150   \brief Constructor. Sets the default name for the module.
151 */
152 PVGUI_Module::PVGUI_Module()
153   : LightApp_Module( "PARAVIS" ),
154     Implementation( 0 ),
155     mySelectionControlsTb( -1 ),
156     mySourcesMenuId( -1 ),
157     myFiltersMenuId( -1 )
158 {
159 }
160
161 /*!
162   \brief Destructor.
163 */
164 PVGUI_Module::~PVGUI_Module()
165 {
166 }
167
168 /*!
169   \brief Initialize module. Creates menus, prepares context menu, etc.
170   \param app application instance
171 */
172 void PVGUI_Module::initialize( CAM_Application* app )
173 {
174   LightApp_Module::initialize( app );
175
176   // Uncomment to debug ParaView initialization
177   // "aa" used instead of "i" as GDB doesn't like "i" variables :)
178   /*
179   int aa = 1;
180   while( aa ){
181     aa = aa;
182   }
183   */
184   
185   // Initialize ParaView client
186   pvInit();
187
188   // Create GUI elements (menus, toolbars, dock widgets)
189   if ( !Implementation ){
190     LightApp_Application* anApp = getApp();
191
192     // Simulate ParaView client main window
193     Implementation = new pqImplementation( anApp->desktop() );
194
195     setupDockWidgets();
196     
197     pvCreateActions();
198     pvCreateMenus();
199     pvCreateToolBars();
200     
201     setupDockWidgetsContextMenu();
202
203     // Now that we're ready, initialize everything ...
204     Implementation->Core.initializeStates();
205   }
206 }
207
208 /*!
209   \brief Get list of compliant dockable GUI elements
210   \param m map to be filled in ("type":"default_position")
211 */
212 void PVGUI_Module::windows( QMap<int, int>& m ) const
213 {
214   m.insert( LightApp_Application::WT_ObjectBrowser, Qt::LeftDockWidgetArea );
215   m.insert( LightApp_Application::WT_PyConsole, Qt::BottomDockWidgetArea );
216   // ParaView diagnostic output redirected here
217   m.insert( LightApp_Application::WT_LogWindow, Qt::BottomDockWidgetArea );
218 }
219
220 /*!
221   \brief Create custom popup menu selection object.
222   \return new selected object
223 */
224 /*LightApp_Selection* PVGUI_Module::createSelection() const
225 {
226   return new PVGUI_Selection();
227 }*/
228
229 /*!
230   \brief Create data model.
231   \return module specific data model
232 */
233 /*CAM_DataModel* PVGUI_Module::createDataModel()
234 {
235   return new PVGUI_DataModel( this );
236 }*/
237
238 /*!
239   \brief Static method, performs initialization of ParaView session.
240   \return \c true if ParaView has been initialized successfully, otherwise false
241 */
242 bool PVGUI_Module::pvInit()
243 {
244   if ( !pqImplementation::myPVMain ){
245     // Obtain command-line arguments
246     // Workaround to avoid pqOptions messages: pass only the executable path to vtkPVMain
247     int argc = 0;
248     QStringList args = QApplication::arguments();
249     char** argv = new char*[args.size()];
250     for ( QStringList::const_iterator it = args.begin(); argc < 1 && it != args.end(); it++, argc++ )
251       argv[argc] = strdup( (*it).toLatin1().constData() );
252
253     vtkPVMain::SetInitializeMPI(0);  // pvClient never runs with MPI.
254     vtkPVMain::Initialize(&argc, &argv); // Perform any initializations.
255
256     // TODO: Set plugin dir from preferences
257     //QApplication::setLibraryPaths(QStringList(dir.absolutePath()));
258
259     pqImplementation::myPVMain = vtkPVMain::New();
260     if ( !pqImplementation::myPVOptions )
261       pqImplementation::myPVOptions = pqOptions::New();
262     if ( !pqImplementation::myPVHelper )
263       pqImplementation::myPVHelper = PVGUI_ProcessModuleHelper::New();
264
265     pqImplementation::myPVOptions->SetProcessType(vtkPVOptions::PVCLIENT);
266
267     // This creates the Process Module and initializes it.
268     int ret = pqImplementation::myPVMain->Initialize(pqImplementation::myPVOptions, 
269                                                      pqImplementation::myPVHelper, 
270                                                      ParaViewInitializeInterpreter,
271                                                      argc, argv);
272     if (!ret){
273       // Tell process module that we support Multiple connections.
274       // This must be set before starting the event loop.
275       vtkProcessModule::GetProcessModule()->SupportMultipleConnectionsOn();
276       ret = pqImplementation::myPVHelper->Run(pqImplementation::myPVOptions);
277     }
278
279     delete[] argv;
280     return !ret;
281   }
282   
283   return true;
284 }
285  
286 /*!
287   \brief Static method, cleans up ParaView session at application exit.
288 */
289 void PVGUI_Module::pvShutdown()
290 {
291   // TODO...
292 }  
293
294 /*!
295   \brief Shows (toShow = true) or hides ParaView view window
296 */
297 void PVGUI_Module::showView( bool toShow )
298 {
299   LightApp_Application* anApp = getApp();
300   PVGUI_ViewManager* viewMgr = dynamic_cast<PVGUI_ViewManager*>( anApp->getViewManager( PVGUI_Viewer::Type(), false ) );
301   if ( !viewMgr ) {
302     viewMgr = new PVGUI_ViewManager( anApp->activeStudy(), anApp->desktop() );
303     anApp->addViewManager( viewMgr );
304     connect( viewMgr, SIGNAL( lastViewClosed( SUIT_ViewManager* ) ),
305              anApp, SLOT( onCloseView( SUIT_ViewManager* ) ) );
306   }
307
308   PVGUI_ViewWindow* pvWnd = dynamic_cast<PVGUI_ViewWindow*>( viewMgr->getActiveView() );
309   if ( !pvWnd ) {
310     pvWnd = dynamic_cast<PVGUI_ViewWindow*>( viewMgr->createViewWindow() );
311     pvWnd->setMultiViewManager( &Implementation->Core.multiViewManager() );
312   }
313
314   pvWnd->setShown( toShow );
315 }
316
317 /*!
318   \brief Manage the label of Undo operation.
319 */
320 void PVGUI_Module::onUndoLabel( const QString& label )
321 {
322   action(UndoId)->setText(
323     label.isEmpty() ? tr("MEN_CANTUNDO") : QString(tr("MEN_UNDO_ACTION")).arg(label));
324   action(UndoId)->setStatusTip(
325     label.isEmpty() ? tr("MEN_CANTUNDO") : QString(tr("MEN_UNDO_ACTION_TIP")).arg(label));
326 }
327
328 /*!
329   \brief Manage the label of Redo operation.
330 */
331 void PVGUI_Module::onRedoLabel( const QString& label )
332 {
333   action(RedoId)->setText(
334     label.isEmpty() ? tr("MEN_CANTREDO") : QString(tr("MEN_REDO_ACTION")).arg(label));
335   action(RedoId)->setStatusTip(
336     label.isEmpty() ? tr("MEN_CANTREDO") : QString(tr("MEN_REDO_ACTION_TIP")).arg(label));
337 }
338
339 /*!
340   \brief Manage the label of Undo Camera operation.
341 */
342 void PVGUI_Module::onCameraUndoLabel( const QString& label )
343 {
344   action(CameraUndoId)->setText(
345     label.isEmpty() ? tr("MEN_CANT_CAMERA_UNDO") : QString(tr("MEN_CAMERA_UNDO_ACTION")).arg(label));
346   action(CameraUndoId)->setStatusTip(
347     label.isEmpty() ? tr("MEN_CANT_CAMERA_UNDO") : QString(tr("MEN_CAMERA_UNDO_ACTION_TIP")).arg(label));
348 }
349
350 /*!
351   \brief Manage the label of Redo Camera operation.
352 */
353 void PVGUI_Module::onCameraRedoLabel( const QString& label )
354 {
355   action(CameraRedoId)->setText(
356     label.isEmpty() ? tr("MEN_CANT_CAMERA_REDO") : QString(tr("MEN_CAMERA_REDO_ACTION")).arg(label));
357   action(CameraRedoId)->setStatusTip(
358     label.isEmpty() ? tr("MEN_CANT_CAMERA_REDO") : QString(tr("MEN_CAMERA_REDO_ACTION_TIP")).arg(label));
359 }
360
361 /*!
362   \brief Slot to delete all objects.
363 */
364 void PVGUI_Module::onDeleteAll()
365 {
366   pqObjectBuilder* builder = pqApplicationCore::instance()->getObjectBuilder();
367   Implementation->Core.getApplicationUndoStack()->beginUndoSet("Delete All");
368   builder->destroyPipelineProxies();
369   Implementation->Core.getApplicationUndoStack()->endUndoSet();
370 }
371
372 /*!
373   \brief Slot to check/uncheck the action for corresponding selection mode.
374 */
375 void PVGUI_Module::onSelectionModeChanged( int mode )
376 {
377   if( toolMgr()->toolBar( mySelectionControlsTb )->isEnabled() ) {
378     if(mode == pqRubberBandHelper::SELECT) //surface selection
379       action(SelectCellsOnId)->setChecked(true);
380     else if(mode == pqRubberBandHelper::SELECT_POINTS) //surface selection
381       action(SelectPointsOnId)->setChecked(true);
382     else if(mode == pqRubberBandHelper::FRUSTUM)
383       action(SelectCellsThroughId)->setChecked(true);
384     else if(mode == pqRubberBandHelper::FRUSTUM_POINTS)
385       action(SelectPointsThroughId)->setChecked(true);
386     else if (mode == pqRubberBandHelper::BLOCKS)
387       action(SelectBlockId)->setChecked(true);
388     else // INTERACT
389       action(InteractId)->setChecked(true);
390   }
391 }
392
393 /*!
394   \brief Slot to manage the change of axis center.
395 */
396 void PVGUI_Module::onShowCenterAxisChanged( bool enabled )
397 {
398   action(ShowCenterId)->setEnabled(enabled);
399   action(ShowCenterId)->blockSignals(true);
400   pqRenderView* renView = qobject_cast<pqRenderView*>(
401     pqActiveView::instance().current());
402   action(ShowCenterId)->setChecked( renView ? renView->getCenterAxesVisibility() : false);
403   action(ShowCenterId)->blockSignals(false);
404 }
405
406 /*!
407   \brief Slot to set tooltips for the first anf the last frames, i.e. a time range of animation.
408 */
409 void PVGUI_Module::setTimeRanges( double start, double end )
410 {
411   action(FirstFrameId)->setToolTip(QString("First Frame (%1)").arg(start, 0, 'g'));
412   action(LastFrameId)->setToolTip(QString("Last Frame (%1)").arg(end, 0, 'g'));
413 }
414
415 /*!
416   \brief Slot to manage the plaing process of animation.
417 */
418 void PVGUI_Module::onPlaying( bool playing )
419 {
420   SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr();
421   if(playing) {
422     disconnect( action(PlayId),                        SIGNAL( triggered() ),
423                 &Implementation->Core.VCRController(), SLOT( onPlay() ) );
424     connect( action(PlayId),                        SIGNAL( triggered() ),
425              &Implementation->Core.VCRController(), SLOT( onPause() ) );
426     action(PlayId)->setIcon(QIcon(resMgr->loadPixmap("ParaView",tr("ICON_PAUSE"),false)));
427     action(PlayId)->setText("Pa&use");
428   }
429   else {
430     connect( action(PlayId),                        SIGNAL( triggered() ),
431              &Implementation->Core.VCRController(), SLOT( onPlay() ) );
432     disconnect( action(PlayId),                        SIGNAL( triggered() ),
433                 &Implementation->Core.VCRController(), SLOT( onPause() ) );
434     action(PlayId)->setIcon(QIcon(resMgr->loadPixmap("ParaView",tr("ICON_PLAY"),false)));
435     action(PlayId)->setText("&Play");
436   }
437
438   Implementation->Core.setSelectiveEnabledState(!playing);
439 }
440
441 /*!
442   \brief Slot to add camera link.
443 */
444 void PVGUI_Module::onAddCameraLink()
445 {
446   pqView* vm = pqActiveView::instance().current();
447   pqRenderView* rm = qobject_cast<pqRenderView*>(vm);
448   if(rm) rm->linkToOtherView();
449   else SUIT_MessageBox::warning(getApp()->desktop(),
450                                 tr("WARNING"), tr("WRN_ADD_CAMERA_LINK"));
451 }
452
453 /*!
454   \brief Slot to show information about ParaView.
455 */
456 void PVGUI_Module::onHelpAbout()
457 {
458   pqClientAboutDialog* const dialog = new pqClientAboutDialog(getApp()->desktop());
459   dialog->setAttribute(Qt::WA_DeleteOnClose);
460   dialog->show();
461 }
462
463 /*!
464   \brief Slot to show help for proxy.
465 */
466 void PVGUI_Module::showHelpForProxy( const QString& proxy )
467 {
468   // make sure assistant is ready
469   this->makeAssistant();
470
471   if(this->Implementation->AssistantClient) {
472     this->Implementation->AssistantClient->openAssistant();
473     QString page("%1/Documentation/%2.html");
474     page = page.arg(this->Implementation->DocumentationDir);
475     page = page.arg(proxy);
476     this->Implementation->AssistantClient->showPage(page);
477   }
478 }
479
480 QString Locate( const QString& appName )
481 {
482   QString app_dir = QCoreApplication::applicationDirPath();
483   const char* inst_dirs[] = {
484     "/./",
485     "/../bin/",
486     "/../../bin/",
487     0
488   };
489   for (const char** dir = inst_dirs; *dir; ++dir) {
490     QString path = app_dir;
491     path += *dir;
492     path += appName;
493     //cout << "Checking : " << path.toAscii().data() << " ... ";
494     //cout.flush();
495     QFileInfo finfo (path);
496     if (finfo.exists()) {
497       //cout << " Success!" << endl;
498       return path;
499     }
500     //cout << " Failed" << endl;
501   }
502   return app_dir + QDir::separator() + appName;
503 }
504
505 /*!
506   \brief Initialized an assistant client.
507 */
508 void PVGUI_Module::makeAssistant()
509 {
510   if(this->Implementation->AssistantClient)
511     return;
512   
513   QString assistantExe;
514   QString profileFile;
515   
516   const char* assistantName = "assistant";
517 #ifdef WNT
518   const char* binDir = "\\";
519   const char* binDir1 = "\\..\\";
520 #else
521   const char* binDir = "/bin/";
522   const char* binDir1 = "/bin/bin/";
523 #endif
524
525   QString helper = QString(getenv("PVHOME")) + binDir + QString("pqClientDocFinder.txt");
526   if(!QFile::exists(helper))
527     helper = QString(getenv("PVHOME")) + binDir1 + QString("pqClientDocFinder.txt");
528   if(QFile::exists(helper)) {
529     QFile file(helper);
530     if(file.open(QIODevice::ReadOnly)) {
531       assistantExe = file.readLine().trimmed();
532       profileFile = file.readLine().trimmed();
533       // CMake escapes spaces, we need to unescape those.
534       assistantExe.replace("\\ ", " ");
535       profileFile.replace("\\ ", " ");
536     }
537   }
538
539   if(assistantExe.isEmpty()) {
540     assistantExe = ::Locate(assistantName);//assistantExe = ::Locate(assistantProgName);
541     /*
542     QString assistant = QCoreApplication::applicationDirPath();
543     assistant += QDir::separator();
544     assistant += assistantName;
545     assistantExe = assistant;
546     */
547   }
548
549   this->Implementation->AssistantClient = new QAssistantClient(assistantExe, this);
550   QObject::connect(this->Implementation->AssistantClient, SIGNAL(error(const QString&)),
551                    this,                                  SLOT(assistantError(const QString&)));
552
553   QStringList args;
554   args.append(QString("-profile"));
555
556   if(profileFile.isEmpty()) {
557     // see if help is bundled up with the application
558     QString profile = ::Locate("pqClient.adp");
559     /*QCoreApplication::applicationDirPath() + QDir::separator()
560       + QString("pqClient.adp");*/
561     
562     if(QFile::exists(profile))
563       profileFile = profile;
564   }
565
566   if(profileFile.isEmpty() && getenv("PARAVIEW_HELP")) {
567     // not bundled, ask for help
568     args.append(getenv("PARAVIEW_HELP"));
569   }
570   else if(profileFile.isEmpty()) {
571     // no help, error out
572     SUIT_MessageBox::critical(getApp()->desktop(),"Help error", "Couldn't find"
573                               " pqClient.adp.\nTry setting the PARAVIEW_HELP environment variable which"
574                               " points to that file");
575     delete this->Implementation->AssistantClient;
576     return;
577   }
578
579   QFileInfo fi(profileFile);
580   this->Implementation->DocumentationDir = fi.absolutePath();
581
582   args.append(profileFile);
583
584   this->Implementation->AssistantClient->setArguments(args);
585 }
586
587 /*!
588   \brief Slot to call the message handler with the critical message.
589 */
590 void PVGUI_Module::assistantError( const QString& error )
591 {
592   qCritical(error.toAscii().data());
593 }
594
595 /*!
596   \brief Slot to show the waiting state.
597 */
598 void PVGUI_Module::onPreAccept()
599 {
600   getApp()->desktop()->statusBar()->showMessage(tr("STB_PREACCEPT"));
601   QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
602 }
603
604 /*!
605   \brief Slot to show the ready state.
606 */
607 void PVGUI_Module::onPostAccept()
608 {
609   getApp()->desktop()->statusBar()->showMessage(tr("STB_POSTACCEPT"), 2000);
610   QTimer::singleShot(0, this, SLOT(endWaitCursor()));
611 }
612
613 /*!
614   \brief Slot to switch off wait cursor.
615 */
616 void PVGUI_Module::endWaitCursor()
617 {
618   QApplication::restoreOverrideCursor();
619 }
620
621 /*!
622   \brief Returns the ParaView multi-view manager.
623 */
624 pqViewManager* PVGUI_Module::getMultiViewManager() const
625 {
626   pqViewManager* aMVM = 0; 
627   if ( Implementation )
628     aMVM = &Implementation->Core.multiViewManager();
629   return aMVM;
630 }
631
632 /*!
633   \brief Processes QEvent::ActionAdded and QEvent::ActionRemoved from Lookmarks toolbar
634   in order to register/unregister this action in/from QtxActionToolMgr.
635 */
636 bool PVGUI_Module::eventFilter( QObject* theObject, QEvent* theEvent )
637 {
638   QToolBar* aTB = toolMgr()->toolBar(tr("TOOL_LOOKMARKS"));
639   if ( theObject == aTB ) {
640     
641     if ( theEvent->type() == QEvent::ActionAdded ) {
642       QList<QAction*> anActns = aTB->actions();
643       for (int i = 0; i < anActns.size(); ++i)
644         if ( toolMgr()->actionId(anActns.at(i)) == -1 ) {
645           toolMgr()->setUpdatesEnabled(false);
646           createTool( anActns.at(i), tr("TOOL_LOOKMARKS") );
647           toolMgr()->setUpdatesEnabled(true);
648         }
649     }
650
651     if ( theEvent->type() == QEvent::ActionRemoved ) {
652       QList<QAction*> anActns = aTB->actions();
653       QIntList aIDL = toolMgr()->idList();
654       for (int i = 0; i < aIDL.size(); ++i) {
655         if ( toolMgr()->action(aIDL.at(i))->parent() == aTB
656              &&
657              !anActns.contains( toolMgr()->action(aIDL.at(i)) ) ) {
658           toolMgr()->setUpdatesEnabled(false);
659           toolMgr()->unRegisterAction( aIDL.at(i) );
660           toolMgr()->remove( aIDL.at(i), tr("TOOL_LOOKMARKS") );
661           toolMgr()->setUpdatesEnabled(true);
662         }
663       }
664     }
665     
666   }
667
668   return QObject::eventFilter( theObject, theEvent );
669 }
670
671 /*!
672   \brief Activate module.
673   \param study current study
674   \return \c true if activaion is done successfully or 0 to prevent
675   activation on error
676 */
677 bool PVGUI_Module::activateModule( SUIT_Study* study )
678 {
679   bool isDone = LightApp_Module::activateModule( study );
680   if ( !isDone ) return false;
681
682   showView( true );
683
684   if ( mySourcesMenuId != -1 ) menuMgr()->show(mySourcesMenuId);
685   if ( myFiltersMenuId != -1 ) menuMgr()->show(myFiltersMenuId);
686   setMenuShown( true );
687   setToolShown( true );
688
689   toolMgr()->toolBar(tr("TOOL_LOOKMARKS"))->installEventFilter(this);
690
691   // Make default server connection
692   if ( Implementation )
693     Implementation->Core.makeDefaultConnectionIfNoneExists();
694
695   restoreDockWidgetsState();
696
697   return isDone;
698 }
699
700
701 /*!
702   \brief Deactivate module.
703   \param study current study
704   \return \c true if deactivaion is done successfully or 0 to prevent
705   deactivation on error
706 */
707 bool PVGUI_Module::deactivateModule( SUIT_Study* study )
708 {
709   toolMgr()->toolBar(tr("TOOL_LOOKMARKS"))->removeEventFilter(this);
710
711   showView( false );
712
713   // hide menus
714   menuMgr()->hide(mySourcesMenuId);
715   menuMgr()->hide(myFiltersMenuId);
716   setMenuShown( false );
717   setToolShown( false );
718
719   saveDockWidgetsState();
720
721   return LightApp_Module::deactivateModule( study );
722 }
723
724 /*!
725   \brief Compares the contents of the window with the given reference image,
726   returns true if they "match" within some tolerance.
727 */
728 bool PVGUI_Module::compareView( const QString& ReferenceImage, double Threshold,
729                                 ostream& Output, const QString& TempDirectory )
730 {
731   if ( Implementation )
732     return Implementation->Core.compareView( ReferenceImage, Threshold, Output, TempDirectory );
733   return false;
734 }
735
736 /*!
737   \fn CAM_Module* createModule();
738   \brief Export module instance (factory function).
739   \return new created instance of the module
740 */
741
742 #ifdef WNT
743 #define PVGUI_EXPORT __declspec(dllexport)
744 #else   // WNT
745 #define PVGUI_EXPORT
746 #endif  // WNT
747
748 extern "C" {
749   PVGUI_EXPORT CAM_Module* createModule() {
750     return new PVGUI_Module();
751   }
752 }