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