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