]> SALOME platform Git repositories - modules/paravis.git/blob - src/PVGUI/PVGUI_Module.cxx
Salome HOME
WIP - This fixes the ParaVis compilation after deprecation of some ParaView API.
[modules/paravis.git] / src / PVGUI / PVGUI_Module.cxx
1 // PARAVIS : ParaView wrapper SALOME module
2 //
3 // Copyright (C) 2010-2019  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 #define PARAVIS_MODULE_NAME "PARAVIS"
24
25 #include <Standard_math.hxx>  // E.A. must be included before Python.h to fix compilation on windows
26 #ifdef HAVE_FINITE
27 #undef HAVE_FINITE            // VSR: avoid compilation warning on Linux : "HAVE_FINITE" redefined
28 #endif
29 #include <vtkPython.h> // Python first
30
31 #include "PVGUI_Module.h"
32
33 #include "PVViewer_ViewManager.h"
34 #include "PVViewer_Core.h"
35 #include "PVViewer_ViewWindow.h"
36 #include "PVViewer_ViewModel.h"
37 #include "PVGUI_ParaViewSettingsPane.h"
38 #include "PVViewer_GUIElements.h"
39 #include "PVServer_ServiceWrapper.h"
40 #include "PVGUI_DataModel.h"
41
42 // SALOME Includes
43 #include <utilities.h>
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 <LightApp_SelectionMgr.h>
53 #include <LightApp_NameDlg.h>
54 #include <LightApp_Application.h>
55 #include <LightApp_Study.h>
56 #include <SALOME_ListIO.hxx>
57
58 #include <QtxActionMenuMgr.h>
59 #include <QtxActionToolMgr.h>
60
61 #include <PARAVIS_version.h>
62
63 // External includes
64 #include <sstream>
65
66 #include <QAction>
67 #include <QApplication>
68 #include <QCursor>
69 #include <QDir>
70 #include <QFile>
71 #include <QFileInfo>
72 #include <QIcon>
73 #include <QInputDialog>
74 #include <QMenu>
75 #include <QStatusBar>
76 #include <QString>
77 #include <QStringList>
78 #include <QTimer>
79 #include <QToolBar>
80 #include <QTextStream>
81 #include <QShortcut>
82 #include <QDockWidget>
83 #include <QHelpEngine>
84
85 // Paraview includes
86 #include <vtkPVConfig.h>  // for symbol PARAVIEW_VERSION
87 #include <vtkProcessModule.h>
88 #include <vtkPVSession.h>
89 #include <vtkPVProgressHandler.h>
90 #include <vtkEventQtSlotConnect.h>
91 #include <vtkNew.h>
92 #include <vtkSMProxy.h>
93 #include <vtkSmartPointer.h>
94 #include <vtkSMSession.h>
95 #include <vtkSMTrace.h>
96 #include <vtkSMSessionProxyManager.h>
97 #include <vtkSMParaViewPipelineController.h>
98 #include <vtkSmartPyObject.h>
99
100 #include <pqApplicationCore.h>
101 #include <pqPVApplicationCore.h>
102 #include <pqObjectBuilder.h>
103 #include <pqOptions.h>
104 #include <pqSettings.h>
105 #include <pqServer.h>
106 #include <pqUndoStack.h>
107 #include <pqTabbedMultiViewWidget.h>
108 #include <pqActiveObjects.h>
109 #include <pqHelpReaction.h>
110 #include <pqPluginManager.h>
111 //#include <pqPythonDialog.h>
112 #include <pqPythonManager.h>
113 #include <pqLoadDataReaction.h>
114 #include <pqPythonScriptEditor.h>
115 #include <pqDataRepresentation.h>
116 #include <pqDisplayColorWidget.h>
117 #include <pqColorToolbar.h>
118 #include <pqScalarBarVisibilityReaction.h>
119 #include <pqServerResource.h>
120 #include <pqServerConnectReaction.h>
121 #include <pqPluginManager.h>
122 #include <pqVCRToolbar.h>
123 #include <pqAnimationScene.h>
124 #include <pqServerManagerModel.h>
125 #include <pqAnimationTimeToolbar.h>
126 #include <pqPipelineBrowserWidget.h>
127
128 #if PY_VERSION_HEX < 0x03050000
129 static char*
130 Py_EncodeLocale(const wchar_t *arg, size_t *size)
131 {
132         return _Py_wchar2char(arg, size);
133 }
134 static wchar_t*
135 Py_DecodeLocale(const char *arg, size_t *size)
136 {
137         return _Py_char2wchar(arg, size);
138 }
139 #endif
140
141 //----------------------------------------------------------------------------
142 PVGUI_Module* ParavisModule = 0;
143
144 /*!
145   \mainpage
146   This is the doxygen documentation of the ParaVis module.
147   If you are looking for general information about the structure of the module, you should
148   take a look at the <a href="../index.html">Sphinx documentation</a> first.
149
150   The integration of ParaView into SALOME is split in two parts:
151   \li the PVViewer in the GUI module (folder *src/PVViewer*)
152   \li the ParaVis module itself (the pages you are currently browsing)
153 */
154
155 /*!
156   \class PVGUI_Module
157   \brief Implementation 
158          SALOME module wrapping ParaView GUI.
159 */
160
161 /*!
162   \brief Clean up function
163
164   Used to stop ParaView progress events when
165   exception is caught by global exception handler.
166 */
167 void paravisCleanUp()
168 {
169   if ( pqApplicationCore::instance() ) {
170     pqServer* s = pqApplicationCore::instance()->getActiveServer();
171     if ( s ) s->session()->GetProgressHandler()->CleanupPendingProgress();
172   }
173 }
174
175 /*!
176   \brief Constructor. Sets the default name for the module.
177 */
178 PVGUI_Module::PVGUI_Module()
179   : LightApp_Module( PARAVIS_MODULE_NAME ),
180     mySourcesMenuId( -1 ),
181     myFiltersMenuId( -1 ),
182     myMacrosMenuId(-1),
183     myRecentMenuId(-1),
184     myCatalystMenuId(-1),
185     myOldMsgHandler(0),
186     myTraceWindow(0),
187     myInitTimer(0),
188     myGuiElements(0)
189 {
190 #ifdef HAS_PV_DOC
191   Q_INIT_RESOURCE( PVGUI );
192 #endif
193   ParavisModule = this;
194
195   // Clear old copies of embedded macros files
196   QString aDestPath = QString( "%1/.config/%2/Macros" ).arg( QDir::homePath() ).arg( QApplication::applicationName() );
197   QStringList aFilter;
198   aFilter << "*.py";
199
200   QDir aDestDir(aDestPath);
201   QStringList aDestFiles = aDestDir.entryList(aFilter, QDir::Files);
202   foreach (QString aMacrosPath, getEmbeddedMacrosList()) {
203     QString aMacrosName = QFileInfo(aMacrosPath).fileName();
204     if (aDestFiles.contains(aMacrosName)) {
205       aDestDir.remove(aMacrosName);
206     }
207   }
208 }
209
210 /*!
211   \brief Destructor.
212 */
213 PVGUI_Module::~PVGUI_Module()
214 {
215   if (myInitTimer)
216     delete myInitTimer;
217 }
218
219 /*!
220   \brief Retrieve the PVSERVER CORBA engine.
221   This uses the Python wrapper provided
222   by the PVViewer code in GUI (class PVViewer_EngineWrapper).
223   \sa GetCPPEngine()
224 */
225 PVServer_ServiceWrapper* PVGUI_Module::GetEngine()
226 {
227   return PVServer_ServiceWrapper::GetInstance();
228 }
229
230 /*!
231   \brief Create data model.
232   \return module specific data model
233 */
234 CAM_DataModel* PVGUI_Module::createDataModel()
235 {
236   return new PVGUI_DataModel( this );
237 }
238
239 /*!
240   \brief Get the ParaView application singleton.
241 */
242 pqPVApplicationCore* PVGUI_Module::GetPVApplication()
243 {
244   return PVViewer_Core::GetPVApplication();
245 }
246
247 /*!
248   \brief Initialize module. Creates menus, prepares context menu, etc.
249   \param app SALOME GUI application instance
250 */
251 void PVGUI_Module::initialize( CAM_Application* app )
252 {
253   LightApp_Module::initialize( app );
254
255   // Uncomment to debug ParaView initialization
256   // "aa" used instead of "i" as GDB doesn't like "i" variables :)
257   /*
258   int aa = 1;
259   while( aa ){
260     aa = aa;
261   }
262   */
263
264   LightApp_Application* anApp = getApp();
265   SUIT_Desktop* aDesktop = anApp->desktop();
266
267   // Remember current state of desktop toolbars
268   QList<QToolBar*> foreignToolbars = aDesktop->findChildren<QToolBar*>();
269
270   // Initialize ParaView client and associated behaviors
271   // and connect to externally launched pvserver
272   PVViewer_Core::ParaviewInitApp(aDesktop);
273   myGuiElements = PVViewer_GUIElements::GetInstance(aDesktop);
274
275   // [ABN]: careful with the order of the GUI element creation, the loading of the configuration
276   // and the connection to the server. This order is very sensitive if one wants to make
277   // sure all menus, etc ... are correctly populated.
278   // Reference points are: ParaViewMainWindow.cxx and branded_paraview_initializer.cxx.in
279   setupDockWidgets();
280
281   pvCreateActions();
282   pvCreateMenus();
283   pvCreateToolBars();
284
285   PVViewer_Core::ParaviewInitBehaviors(true, aDesktop);
286
287   QList<QDockWidget*> activeDocks = aDesktop->findChildren<QDockWidget*>();
288   QList<QMenu*> activeMenus = aDesktop->findChildren<QMenu*>();
289
290   // Setup quick-launch shortcuts.
291   QShortcut *ctrlSpace = new QShortcut(Qt::CTRL + Qt::Key_Space, aDesktop);
292   QObject::connect(ctrlSpace, SIGNAL(activated()),
293     pqApplicationCore::instance(), SLOT(quickLaunch()));
294
295   // Find Plugin Dock Widgets
296   QList<QDockWidget*> currentDocks = aDesktop->findChildren<QDockWidget*>();
297   QList<QDockWidget*>::iterator i;
298   for (i = currentDocks.begin(); i != currentDocks.end(); ++i) {
299     if(!activeDocks.contains(*i)) {
300       myDockWidgets[*i] = false; // hidden by default
301       (*i)->hide();
302     }
303   }
304
305     // Find Plugin Menus
306     // [ABN] TODO: fix this - triggers a SEGFAULT at deactivation() time.
307 //    QList<QMenu*> currentMenus = aDesktop->findChildren<QMenu*>();
308 //    QList<QMenu*>::iterator im;
309 //    for (im = currentMenus.begin(); im != currentMenus.end(); ++im) {
310 //      if(!activeMenus.contains(*im)) {
311 //          QString s = (*im)->title();
312 //          std::cout << " MENU "<<  s.toStdString() << std::endl;
313 //          myMenus.append(*im);
314 //      }
315 //    }
316
317   // Connect after toolbar creation, etc ... as some activations of the toolbars is triggered
318   // by the ServerConnection event:
319   const QString configPath(PVViewer_ViewManager::GetPVConfigPath());
320   PVViewer_Core::ParaviewLoadConfigurations(configPath, true);
321   PVViewer_ViewManager::ConnectToExternalPVServer(aDesktop);
322   updateObjBrowser();
323
324   // Find created toolbars
325   QCoreApplication::processEvents();
326
327   // process PVViewer toolbars (might be added by PVViewer created BEFORE activating ParaVis)
328   QList<QToolBar*> pvToolbars = myGuiElements->getToolbars();
329   foreach(QToolBar* aBar, pvToolbars) {
330     if (!myToolbars.contains(aBar)) {
331       myToolbars[aBar] = true;
332       myToolbarBreaks[aBar] = false;
333       aBar->setVisible(false);
334       aBar->toggleViewAction()->setVisible(false);
335     }
336   }
337
338   // process other toolbars (possibly added by Paraview)
339   QList<QToolBar*> allToolbars = aDesktop->findChildren<QToolBar*>();
340   foreach(QToolBar* aBar, allToolbars) {
341     if (!foreignToolbars.contains(aBar) && !myToolbars.contains(aBar)) {
342       myToolbars[aBar] = true;
343       myToolbarBreaks[aBar] = false;
344       aBar->setVisible(false);
345       aBar->toggleViewAction()->setVisible(false);
346     }
347   }
348
349   updateMacros();
350  
351   SUIT_ResourceMgr* aResourceMgr = SUIT_Session::session()->resourceMgr();
352   bool isStop = aResourceMgr->booleanValue( PARAVIS_MODULE_NAME, "stop_trace", false );
353   if(!isStop)
354     {
355       // Start a timer to schedule asap:
356       //  - the trace start
357       myInitTimer = new QTimer(aDesktop);
358       QObject::connect(myInitTimer, SIGNAL(timeout()), this, SLOT(onInitTimer()) );
359       myInitTimer->setSingleShot(true);
360       myInitTimer->start(0);
361     }
362
363   this->VTKConnect = vtkEventQtSlotConnect::New();
364   
365   vtkProcessModule* pm = vtkProcessModule::GetProcessModule();
366   if(pm) {
367     vtkPVSession* pvs = dynamic_cast<vtkPVSession*>(pm->GetSession());
368     if(pvs) {
369       vtkPVProgressHandler* ph = pvs->GetProgressHandler();
370       if(ph) {
371           this->VTKConnect->Connect(ph, vtkCommand::StartEvent,
372                                     this, SLOT(onStartProgress()));
373           this->VTKConnect->Connect(ph, vtkCommand::EndEvent,
374                                     this, SLOT(onEndProgress()));
375       }
376     }
377   }
378   connect( application(), SIGNAL( appClosed() ), this, SLOT( onStopTrace() ) );
379 }
380
381 /*!
382  * \brief Slot called when the progress bar starts.
383  */
384 void PVGUI_Module::onStartProgress()
385 {
386   // VSR 19/03/2015, issue 0023025
387   // next line is commented: it is bad idea to show wait cursor on ANY vtk event
388   // moreover, it does not work when running pvserver with --multi-client mode
389   //QApplication::setOverrideCursor(Qt::WaitCursor);
390 }
391
392 /*!
393  * \brief Slot called when the progress bar is done.
394  */
395 void PVGUI_Module::onEndProgress()
396 {
397   // VSR 19/03/2015, issue 0023025
398   // next line is commented: it is bad idea to show wait cursor on ANY vtk event
399   // moreover, it does not work when running pvserver with --multi-client mode
400   //QApplication::restoreOverrideCursor();
401 }
402
403 void PVGUI_Module::onDataRepresentationUpdated() {
404   LightApp_Study* activeStudy = dynamic_cast<LightApp_Study*>(application()->activeStudy());
405   if(!activeStudy) return;
406   
407   activeStudy->Modified();
408 }
409
410 /*!
411   \brief Initialisation timer event - Starts up the Python trace
412 */
413 void PVGUI_Module::onInitTimer()
414 {
415   startTrace();
416 }
417   
418 /*!
419   \brief Get list of embedded macros files
420 */
421 QStringList PVGUI_Module::getEmbeddedMacrosList()
422 {
423   QString aRootDir = getenv("PARAVIS_ROOT_DIR");
424
425   QString aSourcePath = aRootDir + "/bin/salome/Macro";
426
427   QStringList aFilter;
428   aFilter << "*.py";
429
430   QDir aSourceDir(aSourcePath);
431   QStringList aSourceFiles = aSourceDir.entryList(aFilter, QDir::Files);
432   QStringList aFullPathSourceFiles;
433   foreach (QString aMacrosName, aSourceFiles) {
434     aFullPathSourceFiles << aSourceDir.absoluteFilePath(aMacrosName);
435   }
436   return aFullPathSourceFiles;
437 }
438
439 /*!
440   \brief Update the list of embedded macros
441 */
442 void PVGUI_Module::updateMacros()
443 {
444   pqPythonManager* aPythonManager = pqPVApplicationCore::instance()->pythonManager();
445   if(!aPythonManager)  {
446     return;
447   }
448   
449   foreach (QString aStr, getEmbeddedMacrosList()) {
450     aPythonManager->addMacro(aStr);
451   }
452 }
453
454
455 /*!
456   \brief Get list of compliant dockable GUI elements
457   \param m map to be filled in ("type":"default_position")
458 */
459 void PVGUI_Module::windows( QMap<int, int>& m ) const
460 {
461   m.insert( LightApp_Application::WT_ObjectBrowser, Qt::LeftDockWidgetArea );
462 #ifndef DISABLE_PYCONSOLE
463   m.insert( LightApp_Application::WT_PyConsole, Qt::BottomDockWidgetArea );
464 #endif
465   // ParaView diagnostic output redirected here
466   m.insert( LightApp_Application::WT_LogWindow, Qt::BottomDockWidgetArea );
467 }
468
469 /*!
470   \brief Shows (toShow = true) or hides ParaView view window
471 */
472 void PVGUI_Module::showView( bool toShow )
473 {
474   // VSR: TODO: all below is not needed, if we use standard approach
475   // that consists in implementing viewManagers() function properly
476   // This should be done after we decide what to do with Log window.
477   LightApp_Application* anApp = getApp();
478   PVViewer_ViewManager* viewMgr =
479     dynamic_cast<PVViewer_ViewManager*>( anApp->getViewManager( PVViewer_Viewer::Type(), false ) );
480   if ( !viewMgr ) {
481     viewMgr = new PVViewer_ViewManager( anApp->activeStudy(), anApp->desktop() );
482     anApp->addViewManager( viewMgr );
483     connect( viewMgr, SIGNAL( lastViewClosed( SUIT_ViewManager* ) ),
484              anApp, SLOT( onCloseView( SUIT_ViewManager* ) ) );
485   }
486
487   PVViewer_ViewWindow* pvWnd = dynamic_cast<PVViewer_ViewWindow*>( viewMgr->getActiveView() );
488   if ( !pvWnd ) {
489     pvWnd = dynamic_cast<PVViewer_ViewWindow*>( viewMgr->createViewWindow() );
490     // this also connects to the pvserver and instantiates relevant PV behaviors
491   }
492
493   pvWnd->setVisible( toShow );
494   if ( toShow ) pvWnd->setFocus();
495 }
496
497 /*!
498   \brief Slot to show help for proxy.
499 */
500 void PVGUI_Module::showHelpForProxy( const QString& groupname, const QString& proxyname )
501 {
502   pqHelpReaction::showProxyHelp(groupname, proxyname);
503 }
504
505 /*!
506   \brief Slot to show the waiting state.
507 */
508 void PVGUI_Module::onPreAccept()
509 {
510   getApp()->desktop()->statusBar()->showMessage(tr("STB_PREACCEPT"));
511   QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
512 }
513
514 /*!
515   \brief Slot to show the ready state.
516 */
517 void PVGUI_Module::onPostAccept()
518 {
519   getApp()->desktop()->statusBar()->showMessage(tr("STB_POSTACCEPT"), 2000);
520   QTimer::singleShot(0, this, SLOT(endWaitCursor()));
521 }
522
523 /*!
524   \brief Slot to switch off wait cursor.
525 */
526 void PVGUI_Module::endWaitCursor()
527 {
528   QApplication::restoreOverrideCursor();
529 }
530
531 /*!
532   \brief Activate module.
533   \param study current study
534   \return \c true if activaion is done successfully or 0 to prevent
535   activation on error
536 */
537 bool PVGUI_Module::activateModule( SUIT_Study* study )
538 {
539   SUIT_ExceptionHandler::addCleanUpRoutine( paravisCleanUp );
540
541   storeCommonWindowsState();
542
543   bool isDone = LightApp_Module::activateModule( study );
544   if ( !isDone ) return false;
545
546   showView( true );
547   if ( mySourcesMenuId != -1 ) menuMgr()->show(mySourcesMenuId);
548   if ( myFiltersMenuId != -1 ) menuMgr()->show(myFiltersMenuId);
549   if ( myMacrosMenuId != -1 ) menuMgr()->show(myMacrosMenuId);
550   if ( myCatalystMenuId != -1 ) menuMgr()->show(myCatalystMenuId);
551
552   // Update the various menus with the content pre-loaded in myGuiElements
553 //  QMenu* srcMenu = menuMgr()->findMenu( mySourcesMenuId );
554 //  myGuiElements->updateSourcesMenu(srcMenu);
555 //  QMenu* filtMenu = menuMgr()->findMenu( myFiltersMenuId );
556 //  myGuiElements->updateFiltersMenu(filtMenu);
557 //  QMenu* macMenu = menuMgr()->findMenu( myMacrosMenuId );
558 //  myGuiElements->updateMacrosMenu(macMenu);
559
560   setMenuShown( true );
561   setToolShown( true );
562
563   restoreDockWidgetsState();
564
565   QMenu* aMenu = menuMgr()->findMenu( myRecentMenuId );
566   if(aMenu) {
567     QList<QAction*> anActns = aMenu->actions();
568     for (int i = 0; i < anActns.size(); ++i) {
569       QAction* a = anActns.at(i);
570       if(a)
571         a->setVisible(true);
572     }
573   }
574
575   QList<QMenu*>::iterator it;
576   for (it = myMenus.begin(); it != myMenus.end(); ++it) {
577     QAction* a = (*it)->menuAction();
578     if(a)
579       a->setVisible(true);
580   }
581
582   if ( myRecentMenuId != -1 ) menuMgr()->show(myRecentMenuId);
583
584   // VSR 18/10/2018 - 0023170: Workaround to re-select current index after module activation
585   QItemSelectionModel* selection_model = myGuiElements->getPipelineBrowserWidget()->getSelectionModel();
586   QModelIndex idx = selection_model->currentIndex();
587   selection_model->clearCurrentIndex();
588   selection_model->setCurrentIndex(idx, QItemSelectionModel::ClearAndSelect);
589
590   return isDone;
591 }
592
593
594 /*!
595   \brief Deactivate module.
596   \param study current study
597   \return \c true if deactivaion is done successfully or 0 to prevent
598   deactivation on error
599 */
600 bool PVGUI_Module::deactivateModule( SUIT_Study* study )
601 {
602   MESSAGE("PARAVIS deactivation ...")
603
604   QMenu* aMenu = menuMgr()->findMenu( myRecentMenuId );
605   if(aMenu) {
606     QList<QAction*> anActns = aMenu->actions();
607     for (int i = 0; i < anActns.size(); ++i) {
608       QAction* a = anActns.at(i);
609       if(a)
610         a->setVisible(false);
611     }
612   }
613
614   QList<QMenu*>::iterator it;
615   for (it = myMenus.begin(); it != myMenus.end(); ++it) {
616     QAction* a = (*it)->menuAction();
617     if(a)
618       a->setVisible(false);
619   }
620
621   QList<QDockWidget*> aStreamingViews = application()->desktop()->findChildren<QDockWidget*>("pqStreamingControls");
622   foreach(QDockWidget* aView, aStreamingViews) {
623     if (!myDockWidgets.contains(aView))
624       myDockWidgets[aView] = aView->isVisible();
625   }
626
627   /*if (pqImplementation::helpWindow) {
628     pqImplementation::helpWindow->hide();
629     }*/
630   // hide menus
631   menuMgr()->hide(myRecentMenuId);
632   menuMgr()->hide(mySourcesMenuId);
633   menuMgr()->hide(myFiltersMenuId);
634   menuMgr()->hide(myMacrosMenuId);
635   menuMgr()->hide(myCatalystMenuId);
636   setMenuShown( false );
637   setToolShown( false );
638
639   saveDockWidgetsState();
640
641   SUIT_ExceptionHandler::removeCleanUpRoutine( paravisCleanUp );
642
643   if (myOldMsgHandler)
644 #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
645     qInstallMsgHandler(myOldMsgHandler);
646 #else
647     qInstallMessageHandler(myOldMsgHandler);
648 #endif
649   restoreCommonWindowsState();
650   
651   return LightApp_Module::deactivateModule( study );
652 }
653
654
655 /*!
656   \brief Called when application is closed.
657
658   Process finalize application functionality from ParaView in order to save server settings
659   and nullify application pointer if the application is being closed.
660
661   \param theApp application
662 */
663 void PVGUI_Module::onApplicationClosed( SUIT_Application* theApp )
664 {
665   PVViewer_Core::ParaviewCleanup();
666   CAM_Module::onApplicationClosed(theApp);
667 }
668
669 /*!
670   \brief Called when study is closed.
671
672   Removes data model from the \a study.
673
674   \param study study being closed
675 */
676 void PVGUI_Module::studyClosed(SUIT_Study* study)
677 {
678   showView(false); // VSR: this seems to be not needed (all views are automatically closed)
679   clearParaviewState();
680   //Re-start trace 
681   onRestartTrace();
682
683   LightApp_Module::studyClosed(study);
684 }
685
686 /*!
687   \brief Open file of format supported by ParaView
688 */
689 void PVGUI_Module::openFile( const char* theName )
690 {
691   QStringList aFiles;
692   aFiles << theName;
693   pqLoadDataReaction::loadData( aFiles );
694 }
695
696 /*!
697   \brief Starts Python trace.
698  
699   Start trace invoking the newly introduced C++ API (PV 4.2)
700   (inspired from pqTraceReaction::start())
701 */
702 void PVGUI_Module::startTrace()
703 {
704   vtkSMSessionProxyManager* pxm = pqActiveObjects::instance().activeServer()->proxyManager();
705
706   vtkSmartPointer<vtkSMProxy> proxy;
707   proxy.TakeReference( pxm->NewProxy( "pythontracing", "PythonTraceOptions" ) );
708   if ( proxy ) {
709     vtkNew<vtkSMParaViewPipelineController> controller;
710     controller->InitializeProxy( proxy );
711   }
712   vtkSMTrace* trace = vtkSMTrace::StartTrace();
713   if ( proxy ) {
714     // Set manually the properties entered via the dialog box poping-up when requiring
715     // a trace start in PV4.2 (trace options)
716     SUIT_ResourceMgr* aResourceMgr = SUIT_Session::session()->resourceMgr();
717     int type = aResourceMgr->integerValue( PARAVIS_MODULE_NAME, "tracestate_type", 2 );
718     trace->SetPropertiesToTraceOnCreate( type );
719     trace->SetFullyTraceSupplementalProxies( false );
720   }
721 }
722
723 /*!
724   \brief Stops Python trace.
725 */
726 void PVGUI_Module::stopTrace()
727 {
728   vtkSMTrace::StopTrace();
729 }
730
731 /*!
732   \brief Execute a Python script.
733 */
734 void PVGUI_Module::executeScript( const char* script )
735 {
736   // ???
737   // Not sure this is the right fix, but the PYTHON_MANAGER has a function named
738   // executeScript() which seems to do what the runScript on pyShellDialog() class
739   // was doing.
740 #ifndef WNT
741   pqPythonManager* manager =
742     qobject_cast<pqPythonManager*>(pqApplicationCore::instance()->manager("PYTHON_MANAGER"));
743
744   if ( manager )  {
745     manager->executeScript(script);
746   }
747 #endif
748   /*
749 #ifndef WNT
750   pqPythonManager* manager = qobject_cast<pqPythonManager*>(
751                              pqApplicationCore::instance()->manager( "PYTHON_MANAGER" ) );
752   if ( manager )  {
753     pqPythonDialog* pyDiag = manager->pythonShellDialog();
754     if ( pyDiag ) {
755       pyDiag->runString(script);  
756     }
757   }
758 #endif
759   */
760 }
761
762 ///**
763 // *  Debug function printing out the given interpreter's execution context
764 // */
765 //void printInterpContext(PyInterp_Interp * interp )
766 //{
767 //  // Extract __smtraceString from interpreter's context
768 //  const PyObject* ctxt = interp->getExecutionContext();
769 //
770 //  PyObject* lst = PyDict_Keys((PyObject *)ctxt);
771 //  Py_ssize_t siz = PyList_GET_SIZE(lst);
772 //  for (Py_ssize_t i = 0; i < siz; i++)
773 //    {
774 //      PyObject * elem = PyList_GetItem(lst, i);
775 //      if (PyString_Check(elem))
776 //        {
777 //          std::cout << "At pos:" << i << ", " << Py_EncodeLocale(PyUnicode_AS_UNICODE(elem), NULL) << std::endl;
778 //        }
779 //      else
780 //        std::cout << "At pos:" << i << ", not a string!" << std::endl;
781 //    }
782 //  Py_XDECREF(lst);
783 //}
784
785 /*!
786   \brief Returns trace string
787 */
788 QString PVGUI_Module::getTraceString()
789 {
790   QString traceString = "";
791
792   static const QString replaceStr( "paraview.simple" );
793   std::stringstream nl;
794   nl << std::endl; // surely there is some Qt trick to do that in a portable way??
795   QString end_line( nl.str().c_str() );
796
797   vtkSMTrace* tracer = vtkSMTrace::GetActiveTracer();
798   if ( tracer ) {
799     traceString = tracer->GetCurrentTrace();
800     // 'import pvsimple' is necessary to fix the first call to DisableFirstRenderCamera in the paraview trace
801     // 'ShowParaviewView()' ensure there is an opened viewing window (otherwise SEGFAULT!)
802     traceString = "import pvsimple" + end_line +
803       "pvsimple.ShowParaviewView()" + end_line + traceString;
804
805     // Replace import "paraview.simple" by "pvsimple"
806     if ( !traceString.isEmpty() ) {
807       int aPos = traceString.indexOf( replaceStr );
808       while ( aPos != -1 ) {
809         traceString = traceString.replace( aPos, replaceStr.length(), "pvsimple" );
810         aPos = traceString.indexOf( replaceStr, aPos );
811       }
812     }
813   }
814
815   // Save camera position to, which is no longer output by the tracer ...
816   {
817     vtkPythonScopeGilEnsurer psge;
818     PyObject * mods(PySys_GetObject(const_cast<char*>("modules")));
819     PyObject * trace_mod(PyDict_GetItemString(mods, "paraview.smtrace"));  // module was already (really) imported by vtkSMTrace
820     if (trace_mod && trace_mod != Py_None && PyModule_Check(trace_mod)) {
821         vtkSmartPyObject save_cam(PyObject_GetAttrString(trace_mod, const_cast<char*>("SaveCameras")));
822         vtkSmartPyObject camera_trace(PyObject_CallMethod(save_cam, const_cast<char*>("get_trace"), NULL));
823         // Convert to a single string
824         vtkSmartPyObject ret(PyUnicode_FromUnicode(Py_DecodeLocale(end_line.toStdString().c_str(), NULL), end_line.size()));
825         vtkSmartPyObject final_string(PyObject_CallMethod(ret, const_cast<char*>("join"),
826             const_cast<char*>("O"), (PyObject*)camera_trace));
827         if (PyUnicode_CheckExact(final_string))
828           {
829             QString camera_qs(Py_EncodeLocale(PyUnicode_AS_UNICODE(final_string.GetPointer()), NULL));  // deep copy
830             traceString = traceString + end_line  + end_line + QString("#### saving camera placements for all active views")
831                 + end_line + end_line + camera_qs + end_line;
832           }
833       }
834   } 
835
836   return traceString;
837 }
838
839 /*!
840   \brief Saves trace string to disk file
841 */
842 void PVGUI_Module::saveTrace( const char* theName )
843 {
844   QFile file( theName );
845   if ( !file.open( QIODevice::WriteOnly | QIODevice::Text ) ) {
846     MESSAGE( "Could not open file:" << theName );
847     return;
848   }
849   QTextStream out( &file );
850   out << getTraceString();
851   file.close();
852 }
853
854 /*!
855   \brief Saves ParaView state to a disk file
856 */
857 void PVGUI_Module::saveParaviewState( const QString& theFileName )
858 {
859   pqApplicationCore::instance()->saveState( theFileName.toStdString().c_str() );
860 }
861
862 /*!
863   \brief Delete all objects for Paraview Pipeline Browser
864 */
865 void PVGUI_Module::clearParaviewState()
866 {
867   QAction* deleteAllAction = action( DeleteAllId );
868   if ( deleteAllAction ) {
869     deleteAllAction->activate( QAction::Trigger );
870   }
871 }
872
873 /*!
874   \brief Restores ParaView state from a disk file
875 */
876 void PVGUI_Module::loadParaviewState( const QString& theFileName )
877 {
878   pqApplicationCore::instance()->loadState( theFileName.toStdString().c_str(), getActiveServer() );
879 }
880
881 /*!
882   \brief Returns current active ParaView server
883 */
884 pqServer* PVGUI_Module::getActiveServer()
885 {
886   return pqApplicationCore::instance()->getActiveServer();
887 }
888
889
890 /*!
891   \brief Creates PARAVIS preferences panel.
892 */
893 void PVGUI_Module::createPreferences()
894 {
895   QList<QVariant> aIndices;
896   QStringList aStrings;
897
898   // Paraview settings tab
899   int aParaViewSettingsTab = addPreference( tr( "TIT_PVIEWSETTINGS" ) );
900
901   setPreferenceProperty(aParaViewSettingsTab, "stretch", false );
902   int aPanel = addPreference( QString(), aParaViewSettingsTab,
903                               LightApp_Preferences::UserDefined, PARAVIS_MODULE_NAME, "" );
904
905   setPreferenceProperty( aPanel, "content", (qint64)( new PVGUI_ParaViewSettingsPane( 0, getApp() ) ) );
906
907   // Paravis settings tab
908   int aParaVisSettingsTab = addPreference( tr( "TIT_PVISSETTINGS" ) );
909
910   addPreference( tr( "PREF_NO_EXT_PVSERVER" ), aParaVisSettingsTab, 
911                  LightApp_Preferences::Bool, PARAVIS_MODULE_NAME, "no_ext_pv_server" );
912
913   int aSaveType = addPreference( tr( "PREF_SAVE_TYPE_LBL" ), aParaVisSettingsTab,
914                                  LightApp_Preferences::Selector,
915                                  PARAVIS_MODULE_NAME, "savestate_type" );
916
917   aStrings.clear();
918   aIndices.clear();
919   aIndices << 0 << 1 << 2;
920   aStrings << tr("PREF_SAVE_TYPE_0") << tr("PREF_SAVE_TYPE_1") << tr("PREF_SAVE_TYPE_2");
921   setPreferenceProperty( aSaveType, "strings", aStrings );
922   setPreferenceProperty( aSaveType, "indexes", aIndices );
923
924   // ... "Language" group <<start>>
925   int traceGroup = addPreference( tr( "PREF_GROUP_TRACE" ), aParaVisSettingsTab );
926
927   int stopTrace = addPreference( tr( "PREF_STOP_TRACE" ), traceGroup, 
928                                  LightApp_Preferences::Bool, PARAVIS_MODULE_NAME, "stop_trace" );
929   setPreferenceProperty( stopTrace, "restart",  true );
930
931   int aTraceType = addPreference( tr( "PREF_TRACE_TYPE_LBL" ), traceGroup,
932                                  LightApp_Preferences::Selector,
933                                  PARAVIS_MODULE_NAME, "tracestate_type" );
934   aStrings.clear();
935   aIndices.clear();
936   aIndices << 0 << 1 << 2;
937   aStrings << tr("PREF_TRACE_TYPE_0") << tr("PREF_TRACE_TYPE_1") << tr("PREF_TRACE_TYPE_2");
938   setPreferenceProperty( aTraceType, "strings", aStrings );
939   setPreferenceProperty( aTraceType, "indexes", aIndices );
940   setPreferenceProperty( aTraceType, "restart",  true );
941 }
942
943 /*!
944   \brief. Show ParaView python trace.
945 */
946 void PVGUI_Module::onShowTrace()
947 {
948   if (!myTraceWindow) {
949     myTraceWindow = new pqPythonScriptEditor(getApp()->desktop());
950   }
951   myTraceWindow->setText(getTraceString());
952   myTraceWindow->show();
953   myTraceWindow->raise();
954   myTraceWindow->activateWindow();
955 }
956
957
958 /*!
959   \brief. Re-initialize ParaView python trace.
960 */
961 void PVGUI_Module::onRestartTrace()
962 {
963   stopTrace();
964   startTrace();
965 }
966
967 /*!
968   \brief. Close ParaView python trace.
969 */
970 void PVGUI_Module::onStopTrace()
971 {
972   stopTrace();
973 }
974 /*!
975   \brief Called when view manager is added
976 */
977 void PVGUI_Module::onViewManagerAdded( SUIT_ViewManager* vm )
978 {
979   if ( PVViewer_ViewManager* pvvm = dynamic_cast<PVViewer_ViewManager*>( vm ) ) {
980     connect( pvvm, SIGNAL( viewCreated( SUIT_ViewWindow* ) ), 
981              this, SLOT( onPVViewCreated( SUIT_ViewWindow* ) ) );
982     connect( pvvm, SIGNAL( deleteView( SUIT_ViewWindow* ) ),
983              this,  SLOT( onPVViewDelete( SUIT_ViewWindow* ) ) );
984   }
985 }
986
987 /*!
988   \brief Called when view manager is removed
989 */
990 void PVGUI_Module::onViewManagerRemoved( SUIT_ViewManager* vm )
991 {
992   if ( PVViewer_ViewManager* pvvm = dynamic_cast<PVViewer_ViewManager*>( vm ) )
993     disconnect( pvvm, SIGNAL( viewCreated( SUIT_ViewWindow* ) ),
994                 this, SLOT( onPVViewCreated( SUIT_ViewWindow* ) ) );
995 }
996
997 /*!
998   \brief Show toolbars at \a vw PV view window creating when PARAVIS is active.
999 */
1000 void PVGUI_Module::onPVViewCreated( SUIT_ViewWindow* vw )
1001 {
1002   myGuiElements->setToolBarVisible( true );
1003   restoreDockWidgetsState();
1004 }
1005
1006 /*!
1007   \brief Save toolbars state at \a view view closing.
1008 */
1009 void PVGUI_Module::onPVViewDelete( SUIT_ViewWindow* view )
1010 {
1011   if ( dynamic_cast<PVViewer_ViewWindow*>( view ) )
1012     saveDockWidgetsState( false );
1013 }
1014
1015 /*!
1016   \fn CAM_Module* createModule();
1017   \brief Export module instance (factory function).
1018   \return new created instance of the module
1019 */
1020
1021 #ifdef WNT
1022 #define PVGUI_EXPORT __declspec(dllexport)
1023 #else   // WNT
1024 #define PVGUI_EXPORT
1025 #endif  // WNT
1026
1027 extern "C" {
1028
1029   bool flag = false;
1030   PVGUI_EXPORT CAM_Module* createModule() {
1031     return new PVGUI_Module();
1032   }
1033   
1034   PVGUI_EXPORT char* getModuleVersion() {
1035     return (char*)PARAVIS_VERSION_STR;
1036   }
1037 }