1 // PARAVIS : ParaView wrapper SALOME module
3 // Copyright (C) 2010-2015 CEA/DEN, EDF R&D
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.
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.
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
19 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 // File : PVGUI_Module.cxx
23 #define PARAVIS_MODULE_NAME "PARAVIS"
25 #include <Standard_math.hxx> // E.A. must be included before Python.h to fix compilation on windows
27 #undef HAVE_FINITE // VSR: avoid compilation warning on Linux : "HAVE_FINITE" redefined
29 #include <vtkPython.h> // Python first
30 #include "PVGUI_Module.h"
32 //#ifdef PARAVIS_WITH_FULL_CORBA
33 //# include "PARAVIS_Gen_i.hh"
36 #include CORBA_SERVER_HEADER(SALOME_ModuleCatalog)
37 #include CORBA_SERVER_HEADER(SALOMEDS)
39 #include "PVViewer_ViewManager.h"
40 #include "PVViewer_ViewWindow.h"
41 #include "PVViewer_ViewModel.h"
42 #include "PVGUI_Tools.h"
43 #include "PVGUI_ParaViewSettingsPane.h"
44 #include "PVViewer_GUIElements.h"
45 #include "PVViewer_EngineWrapper.h"
46 #include "PVGUI_DataModel.h"
49 #include <utilities.h>
50 #include <SUIT_DataBrowser.h>
51 #include <SUIT_Desktop.h>
52 #include <SUIT_MessageBox.h>
53 #include <SUIT_ResourceMgr.h>
54 #include <SUIT_Session.h>
55 #include <SUIT_OverrideCursor.h>
56 #include <SUIT_ExceptionHandler.h>
58 #include <SALOME_LifeCycleCORBA.hxx>
59 #include <SALOMEDS_SObject.hxx>
61 #include <LightApp_SelectionMgr.h>
62 #include <LightApp_NameDlg.h>
63 #include <LightApp_Application.h>
64 #include <SalomeApp_Application.h> // should ultimately be a LightApp only
65 #include <SalomeApp_Study.h>
66 #include <SALOME_ListIO.hxx>
67 #include <SALOMEDS_Tool.hxx>
68 #include <Utils_ORB_INIT.hxx>
69 #include <Utils_SINGLETON.hxx>
71 #include <QtxActionMenuMgr.h>
72 #include <QtxActionToolMgr.h>
74 #include <PARAVIS_version.h>
80 #include <QApplication>
86 #include <QInputDialog>
90 #include <QStringList>
93 #include <QTextStream>
95 #include <QDockWidget>
96 #include <QHelpEngine>
99 #include <vtkPVConfig.h> // for symbol PARAVIEW_VERSION
100 #include <vtkProcessModule.h>
101 #include <vtkPVSession.h>
102 #include <vtkPVProgressHandler.h>
103 #include <vtkOutputWindow.h>
104 #include <vtkEventQtSlotConnect.h>
106 #include <vtkSMProxy.h>
107 #include <vtkSmartPointer.h>
108 #include <vtkSMSession.h>
109 #include <vtkSMTrace.h>
110 #include <vtkSMSessionProxyManager.h>
111 #include <vtkSMParaViewPipelineController.h>
113 #include <pqApplicationCore.h>
114 #include <pqPVApplicationCore.h>
115 #include <pqObjectBuilder.h>
116 #include <pqOptions.h>
117 #include <pqSettings.h>
118 #include <pqServer.h>
119 #include <pqUndoStack.h>
120 #include <pqTabbedMultiViewWidget.h>
121 #include <pqActiveObjects.h>
122 #include <pqHelpReaction.h>
123 #include <pqPluginManager.h>
124 #include <pqPythonDialog.h>
125 #include <pqPythonManager.h>
126 #include <pqLoadDataReaction.h>
127 #include <pqPythonScriptEditor.h>
128 #include <pqDataRepresentation.h>
129 #include <pqDisplayColorWidget.h>
130 #include <pqColorToolbar.h>
131 #include <pqScalarBarVisibilityReaction.h>
132 #include <pqServerResource.h>
133 #include <pqServerConnectReaction.h>
134 #include <pqPluginManager.h>
135 #include <pqVCRToolbar.h>
136 #include <pqAnimationScene.h>
137 #include <pqServerManagerModel.h>
138 #include <pqAnimationTimeToolbar.h>
140 //#include <PVViewer_EngineWrapper.h>
143 //----------------------------------------------------------------------------
144 PVGUI_Module* ParavisModule = 0;
145 PVSERVER_ORB::PVSERVER_Gen_var PVGUI_Module::MyEngine;
149 TODO TODO update this:
151 <h2>Building and installing PARAVIS</h2>
152 As any other SALOME module, PARAVIS requires PARAVIS_ROOT_DIR environment variable to be set to PARAVIS
153 installation directory.
154 Other variables needed for correct detection of ParaView location:
155 \li PVHOME - points at the ParaView installation directory tree
156 \li PVVERSION - number of ParaView version
158 It also requires common SALOME environment including GUI_ROOT_DIR and other prerequsites.
161 PARAVIS module can be launched using the following commands:
162 \li Full SALOME configuration
164 runSalome --modules="PARAVIS"
167 <h2>ParaView GUI integration</h2>
168 <h3>ParaView GUI integration overview</h3>
170 The main idea is to reuse ParaView GUI internal logic as much as possible, providing a layer
171 between it and SALOME GUI that hides the following SALOME GUI implementation details from ParaView:
173 \li SALOME GUI executable and Qt event loop
174 \li SALOME GUI desktop
175 \li Dock windows areas
176 \li SALOME menu and toolbar managers
178 Major part of the integration is implemented in PVGUI_Module class.
180 <h3>ParaView client initalization</h3>
182 ParaView client initalization is performed when an instance of PVGUI_Module class has been created
183 and \link PVGUI_Module::initialize() PVGUI_Module::initialize()\endlink method is called by SALOME GUI.
184 The actual client start-up is done in \link PVGUI_Module::pvInit() PVGUI_Module::pvInit()\endlink method.
187 <h3>Multi-view manager</h3>
189 SALOME GUI requires that each kind of view be implemnted with help of (at least) three classes. For ParaView multi-view manager
192 \li PVGUI_ViewManager - view manager class
193 \li PVGUI_Viewer - view model class
194 \li PVGUI_ViewWindow - view window class that acts as a parent for %pqViewManager
196 Single instances of PVGUI_ViewManager and PVGUI_ViewWindow classes are created by \link PVGUI_Module::showView()
197 PVGUI_Module::showView()\endlink method upon the first PARAVIS module activation. The same method hides the multi-view manager
198 when the module is deactivated (the user switches to another module or a study is closed).
199 A special trick is used to make PVGUI_ViewWindow the parent of %pqViewManager widget. It is created initally by %pqMainWindowCore
200 with the desktop as a parent, so when it is shown PVGUI_ViewWindow instance is passed to its setParent() method. In
201 \link PVGUI_ViewWindow::~PVGUI_ViewWindow() PVGUI_ViewWindow::~PVGUI_ViewWindow()\endlink the parent is nullified to avoid deletion
202 of %pqViewManager widget that would break %pqMainWindowCore class.
204 <h3>ParaView plugins</h3>
205 ParaView server and client plugins are managed by %pqMainWindowCore slots that has full access to PARAVIS menus and toolbars.
206 As a result they appears automatically in PARAVIS menus and toolbars if loaded successfully.
211 \brief Implementation
212 SALOME module wrapping ParaView GUI.
216 ClientFindOrCreateParavisComponent(_PTR(Study) theStudyDocument)
218 _PTR(SComponent) aSComponent = theStudyDocument->FindComponent("PVSERVER");
220 _PTR(StudyBuilder) aStudyBuilder = theStudyDocument->NewBuilder();
221 aStudyBuilder->NewCommand();
222 int aLocked = theStudyDocument->GetProperties()->IsLocked();
223 if (aLocked) theStudyDocument->GetProperties()->SetLocked(false);
224 aSComponent = aStudyBuilder->NewComponent("PVSERVER");
225 _PTR(GenericAttribute) anAttr =
226 aStudyBuilder->FindOrCreateAttribute(aSComponent, "AttributeName");
227 _PTR(AttributeName) aName (anAttr);
229 ORB_INIT& init = *SINGLETON_<ORB_INIT>::Instance();
230 CORBA::ORB_var anORB = init( qApp->argc(), qApp->argv() );
232 SALOME_NamingService *NamingService = new SALOME_NamingService( anORB );
233 CORBA::Object_var objVarN = NamingService->Resolve("/Kernel/ModulCatalog");
234 SALOME_ModuleCatalog::ModuleCatalog_var Catalogue =
235 SALOME_ModuleCatalog::ModuleCatalog::_narrow(objVarN);
236 SALOME_ModuleCatalog::Acomponent_var Comp = Catalogue->GetComponent( "PVSERVER" );
237 if (!Comp->_is_nil()) {
238 aName->SetValue(Comp->componentusername());
241 anAttr = aStudyBuilder->FindOrCreateAttribute(aSComponent, "AttributePixMap");
242 _PTR(AttributePixMap) aPixmap (anAttr);
243 aPixmap->SetPixMap( "pqAppIcon16.png" );
245 // Create Attribute parameters for future using
246 anAttr = aStudyBuilder->FindOrCreateAttribute(aSComponent, "AttributeParameter");
248 aStudyBuilder->DefineComponentInstance(aSComponent, PVGUI_Module::GetCPPEngine()->GetIOR());
249 if (aLocked) theStudyDocument->GetProperties()->SetLocked(true);
250 aStudyBuilder->CommitCommand();
256 Clean up function; used to stop ParaView progress events when
257 exception is caught by global exception handler.
259 void paravisCleanUp()
261 if ( pqApplicationCore::instance() ) {
262 pqServer* s = pqApplicationCore::instance()->getActiveServer();
263 if ( s ) s->session()->GetProgressHandler()->CleanupPendingProgress();
268 \brief Constructor. Sets the default name for the module.
270 PVGUI_Module::PVGUI_Module()
271 : SalomeApp_Module( PARAVIS_MODULE_NAME ),
272 mySelectionControlsTb( -1 ),
273 mySourcesMenuId( -1 ),
274 myFiltersMenuId( -1 ),
276 myToolbarsMenuId(-1),
286 Q_INIT_RESOURCE( PVGUI );
288 ParavisModule = this;
290 // Clear old copies of embedded macros files
291 QString aDestPath = QString( "%1/.config/%2/Macros" ).arg( QDir::homePath() ).arg( QApplication::applicationName() );
295 QDir aDestDir(aDestPath);
296 QStringList aDestFiles = aDestDir.entryList(aFilter, QDir::Files);
297 foreach (QString aMacrosPath, getEmbeddedMacrosList()) {
298 QString aMacrosName = QFileInfo(aMacrosPath).fileName();
299 if (aDestFiles.contains(aMacrosName)) {
300 aDestDir.remove(aMacrosName);
308 PVGUI_Module::~PVGUI_Module()
310 if (myPushTraceTimer)
311 delete myPushTraceTimer;
316 PVViewer_EngineWrapper * PVGUI_Module::GetEngine()
318 return PVViewer_EngineWrapper::GetInstance();
321 PVSERVER_ORB::PVSERVER_Gen_var PVGUI_Module::GetCPPEngine()
323 // initialize PARAVIS module engine (load, if necessary)
324 if ( CORBA::is_nil( MyEngine ) ) {
325 Engines::EngineComponent_var comp =
326 SalomeApp_Application::lcc()->FindOrLoad_Component( "FactoryServer", "PVSERVER" );
327 MyEngine = PVSERVER_ORB::PVSERVER_Gen::_narrow( comp );
333 \brief Create data model.
334 \return module specific data model
336 CAM_DataModel* PVGUI_Module::createDataModel()
338 return new PVGUI_DataModel( this );
341 pqPVApplicationCore * PVGUI_Module::GetPVApplication()
343 return PVViewer_ViewManager::GetPVApplication();
347 \brief Initialize module. Creates menus, prepares context menu, etc.
348 \param app SALOME GUI application instance
350 void PVGUI_Module::initialize( CAM_Application* app )
352 LightApp_Module::initialize( app );
357 // Uncomment to debug ParaView initialization
358 // "aa" used instead of "i" as GDB doesn't like "i" variables :)
366 LightApp_Application* anApp = getApp();
367 SUIT_Desktop* aDesktop = anApp->desktop();
369 // Remember current state of desktop toolbars
370 QList<QToolBar*> foreignToolbars = aDesktop->findChildren<QToolBar*>();
372 // Initialize ParaView client and associated behaviors
373 // and connect to externally launched pvserver
374 PVViewer_ViewManager::ParaviewInitApp(aDesktop, anApp->logWindow());
375 myGuiElements = PVViewer_GUIElements::GetInstance(aDesktop);
377 // [ABN]: careful with the order of the GUI element creation, the loading of the configuration
378 // and the connection to the server. This order is very sensitive if one wants to make
379 // sure all menus, etc ... are correctly populated.
380 // Reference points are: ParaViewMainWindow.cxx and branded_paraview_initializer.cxx.in
387 PVViewer_ViewManager::ParaviewInitBehaviors(true, aDesktop);
389 QList<QDockWidget*> activeDocks = aDesktop->findChildren<QDockWidget*>();
390 QList<QMenu*> activeMenus = aDesktop->findChildren<QMenu*>();
392 // Setup quick-launch shortcuts.
393 QShortcut *ctrlSpace = new QShortcut(Qt::CTRL + Qt::Key_Space, aDesktop);
394 QObject::connect(ctrlSpace, SIGNAL(activated()),
395 pqApplicationCore::instance(), SLOT(quickLaunch()));
397 // Find Plugin Dock Widgets
398 QList<QDockWidget*> currentDocks = aDesktop->findChildren<QDockWidget*>();
399 QList<QDockWidget*>::iterator i;
400 for (i = currentDocks.begin(); i != currentDocks.end(); ++i) {
401 if(!activeDocks.contains(*i)) {
402 myDockWidgets[*i] = false; // hidden by default
408 // [ABN] TODO: fix this - triggers a SEGFAULT at deactivation() time.
409 // QList<QMenu*> currentMenus = aDesktop->findChildren<QMenu*>();
410 // QList<QMenu*>::iterator im;
411 // for (im = currentMenus.begin(); im != currentMenus.end(); ++im) {
412 // if(!activeMenus.contains(*im)) {
413 // QString s = (*im)->title();
414 // std::cout << " MENU "<< s.toStdString() << std::endl;
415 // myMenus.append(*im);
419 // Connect after toolbar creation, etc ... as some activations of the toolbars is triggered
420 // by the ServerConnection event:
421 PVViewer_ViewManager::ParaviewLoadConfigurations(true);
422 PVViewer_ViewManager::ConnectToExternalPVServer(aDesktop);
425 // Find created toolbars
426 QCoreApplication::processEvents();
428 // process PVViewer toolbars (might be added by PVViewer created BEFORE activating ParaVis)
429 QList<QToolBar*> pvToolbars = myGuiElements->getToolbars();
430 foreach(QToolBar* aBar, pvToolbars) {
431 if (!myToolbars.contains(aBar)) {
432 myToolbars[aBar] = true;
433 myToolbarBreaks[aBar] = false;
434 aBar->setVisible(false);
435 aBar->toggleViewAction()->setVisible(false);
439 // process other toolbars (possibly added by Paraview)
440 QList<QToolBar*> allToolbars = aDesktop->findChildren<QToolBar*>();
441 foreach(QToolBar* aBar, allToolbars) {
442 if (!foreignToolbars.contains(aBar) && !myToolbars.contains(aBar)) {
443 myToolbars[aBar] = true;
444 myToolbarBreaks[aBar] = false;
445 aBar->setVisible(false);
446 aBar->toggleViewAction()->setVisible(false);
452 SUIT_ResourceMgr* aResourceMgr = SUIT_Session::session()->resourceMgr();
453 bool isStop = aResourceMgr->booleanValue( PARAVIS_MODULE_NAME, "stop_trace", false );
456 // Start a timer to schedule asap:
458 myInitTimer = new QTimer(aDesktop);
459 QObject::connect(myInitTimer, SIGNAL(timeout()), this, SLOT(onInitTimer()) );
460 myInitTimer->setSingleShot(true);
461 myInitTimer->start(0);
463 // Another timer to regularly push the trace onto the engine:
464 myPushTraceTimer = new QTimer(aDesktop);
465 QObject::connect(myPushTraceTimer, SIGNAL(timeout()), this, SLOT(onPushTraceTimer()) );
466 myPushTraceTimer->setSingleShot(false);
467 myPushTraceTimer->start(500);
470 this->VTKConnect = vtkEventQtSlotConnect::New();
472 vtkProcessModule* pm = vtkProcessModule::GetProcessModule();
474 vtkPVSession* pvs = dynamic_cast<vtkPVSession*>(pm->GetSession());
476 vtkPVProgressHandler* ph = pvs->GetProgressHandler();
478 this->VTKConnect->Connect(ph, vtkCommand::StartEvent,
479 this, SLOT(onStartProgress()));
480 this->VTKConnect->Connect(ph, vtkCommand::EndEvent,
481 this, SLOT(onEndProgress()));
490 * Little trick to force the proper update of the timesteps/time range when the module is initialized.
491 * This is otherwise not properly working when PARAVIS is activated after a PVViewer has already been
494 void PVGUI_Module::fixAnimationScene()
496 pqServer* server = pqActiveObjects::instance().activeServer();
497 pqApplicationCore * app = pqApplicationCore::instance();
498 pqPipelineSource * src = app->getObjectBuilder()->createSource(QString("sources"), QString("TimeSource"),server);
499 app->getObjectBuilder()->destroy(src);
502 void PVGUI_Module::onStartProgress()
504 QApplication::setOverrideCursor(Qt::WaitCursor);
507 void PVGUI_Module::onEndProgress()
509 QApplication::restoreOverrideCursor();
512 void PVGUI_Module::onDataRepresentationUpdated() {
513 SalomeApp_Study* activeStudy = dynamic_cast<SalomeApp_Study*>(application()->activeStudy());
514 if(!activeStudy) return;
516 activeStudy->Modified();
520 \brief Initialisation timer event - trace start up
522 void PVGUI_Module::onInitTimer()
528 \brief Get list of embedded macros files
530 QStringList PVGUI_Module::getEmbeddedMacrosList()
532 QString aRootDir = getenv("PARAVIS_ROOT_DIR");
534 QString aSourcePath = aRootDir + "/bin/salome/Macro";
539 QDir aSourceDir(aSourcePath);
540 QStringList aSourceFiles = aSourceDir.entryList(aFilter, QDir::Files);
541 QStringList aFullPathSourceFiles;
542 foreach (QString aMacrosName, aSourceFiles) {
543 aFullPathSourceFiles << aSourceDir.absoluteFilePath(aMacrosName);
545 return aFullPathSourceFiles;
548 void PVGUI_Module::updateMacros()
550 pqPythonManager* aPythonManager = pqPVApplicationCore::instance()->pythonManager();
551 if(!aPythonManager) {
555 foreach (QString aStr, getEmbeddedMacrosList()) {
556 aPythonManager->addMacro(aStr);
562 \brief Get list of compliant dockable GUI elements
563 \param m map to be filled in ("type":"default_position")
565 void PVGUI_Module::windows( QMap<int, int>& m ) const
567 m.insert( LightApp_Application::WT_ObjectBrowser, Qt::LeftDockWidgetArea );
568 m.insert( LightApp_Application::WT_PyConsole, Qt::BottomDockWidgetArea );
569 // ParaView diagnostic output redirected here
570 m.insert( LightApp_Application::WT_LogWindow, Qt::BottomDockWidgetArea );
574 \brief Shows (toShow = true) or hides ParaView view window
576 void PVGUI_Module::showView( bool toShow )
578 LightApp_Application* anApp = getApp();
579 PVViewer_ViewManager* viewMgr =
580 dynamic_cast<PVViewer_ViewManager*>( anApp->getViewManager( PVViewer_Viewer::Type(), false ) );
582 viewMgr = new PVViewer_ViewManager( anApp->activeStudy(), anApp->desktop(), anApp->logWindow() );
583 anApp->addViewManager( viewMgr );
584 connect( viewMgr, SIGNAL( lastViewClosed( SUIT_ViewManager* ) ),
585 anApp, SLOT( onCloseView( SUIT_ViewManager* ) ) );
588 PVViewer_ViewWindow* pvWnd = dynamic_cast<PVViewer_ViewWindow*>( viewMgr->getActiveView() );
590 pvWnd = dynamic_cast<PVViewer_ViewWindow*>( viewMgr->createViewWindow() );
591 // this also connects to the pvserver and instantiates relevant PV behaviors
594 pvWnd->setShown( toShow );
595 if ( toShow ) pvWnd->setFocus();
599 \brief Slot to show help for proxy.
601 void PVGUI_Module::showHelpForProxy( const QString& groupname, const QString& proxyname )
603 pqHelpReaction::showProxyHelp(groupname, proxyname);
608 \brief Slot to show the waiting state.
610 void PVGUI_Module::onPreAccept()
612 getApp()->desktop()->statusBar()->showMessage(tr("STB_PREACCEPT"));
613 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
617 \brief Slot to show the ready state.
619 void PVGUI_Module::onPostAccept()
621 getApp()->desktop()->statusBar()->showMessage(tr("STB_POSTACCEPT"), 2000);
622 QTimer::singleShot(0, this, SLOT(endWaitCursor()));
626 \brief Slot to switch off wait cursor.
628 void PVGUI_Module::endWaitCursor()
630 QApplication::restoreOverrideCursor();
633 static void ParavisMessageOutput(QtMsgType type, const char *msg)
638 vtkOutputWindow::GetInstance()->DisplayText(msg);
641 vtkOutputWindow::GetInstance()->DisplayErrorText(msg);
644 vtkOutputWindow::GetInstance()->DisplayErrorText(msg);
647 vtkOutputWindow::GetInstance()->DisplayErrorText(msg);
653 \brief Activate module.
654 \param study current study
655 \return \c true if activaion is done successfully or 0 to prevent
658 bool PVGUI_Module::activateModule( SUIT_Study* study )
660 myOldMsgHandler = qInstallMsgHandler(ParavisMessageOutput);
662 SUIT_ExceptionHandler::addCleanUpRoutine( paravisCleanUp );
664 storeCommonWindowsState();
666 bool isDone = LightApp_Module::activateModule( study );
667 if ( !isDone ) return false;
670 if ( mySourcesMenuId != -1 ) menuMgr()->show(mySourcesMenuId);
671 if ( myFiltersMenuId != -1 ) menuMgr()->show(myFiltersMenuId);
672 if ( myMacrosMenuId != -1 ) menuMgr()->show(myMacrosMenuId);
673 if ( myToolbarsMenuId != -1 ) menuMgr()->show(myToolbarsMenuId);
675 // Update the various menus with the content pre-loaded in myGuiElements
676 // QMenu* srcMenu = menuMgr()->findMenu( mySourcesMenuId );
677 // myGuiElements->updateSourcesMenu(srcMenu);
678 // QMenu* filtMenu = menuMgr()->findMenu( myFiltersMenuId );
679 // myGuiElements->updateFiltersMenu(filtMenu);
680 // QMenu* macMenu = menuMgr()->findMenu( myMacrosMenuId );
681 // myGuiElements->updateMacrosMenu(macMenu);
683 setMenuShown( true );
684 setToolShown( true );
686 restoreDockWidgetsState();
688 QMenu* aMenu = menuMgr()->findMenu( myRecentMenuId );
690 QList<QAction*> anActns = aMenu->actions();
691 for (int i = 0; i < anActns.size(); ++i) {
692 QAction* a = anActns.at(i);
698 QList<QMenu*>::iterator it;
699 for (it = myMenus.begin(); it != myMenus.end(); ++it) {
700 QAction* a = (*it)->menuAction();
705 if ( myRecentMenuId != -1 ) menuMgr()->show(myRecentMenuId);
707 ClientFindOrCreateParavisComponent(PARAVIS::GetCStudy(this));
714 \brief Deactivate module.
715 \param study current study
716 \return \c true if deactivaion is done successfully or 0 to prevent
717 deactivation on error
719 bool PVGUI_Module::deactivateModule( SUIT_Study* study )
721 MESSAGE("PARAVIS deactivation ...")
723 QMenu* aMenu = menuMgr()->findMenu( myRecentMenuId );
725 QList<QAction*> anActns = aMenu->actions();
726 for (int i = 0; i < anActns.size(); ++i) {
727 QAction* a = anActns.at(i);
729 a->setVisible(false);
733 QList<QMenu*>::iterator it;
734 for (it = myMenus.begin(); it != myMenus.end(); ++it) {
735 QAction* a = (*it)->menuAction();
737 a->setVisible(false);
740 QList<QDockWidget*> aStreamingViews = application()->desktop()->findChildren<QDockWidget*>("pqStreamingControls");
741 foreach(QDockWidget* aView, aStreamingViews) {
742 if (!myDockWidgets.contains(aView))
743 myDockWidgets[aView] = aView->isVisible();
746 /*if (pqImplementation::helpWindow) {
747 pqImplementation::helpWindow->hide();
751 menuMgr()->hide(myRecentMenuId);
752 menuMgr()->hide(mySourcesMenuId);
753 menuMgr()->hide(myFiltersMenuId);
754 menuMgr()->hide(myMacrosMenuId);
755 menuMgr()->hide(myToolbarsMenuId);
756 setMenuShown( false );
757 setToolShown( false );
759 saveDockWidgetsState();
761 SUIT_ExceptionHandler::removeCleanUpRoutine( paravisCleanUp );
764 qInstallMsgHandler(myOldMsgHandler);
766 restoreCommonWindowsState();
768 return LightApp_Module::deactivateModule( study );
773 \brief Called when application is closed.
775 Process finalize application functionality from ParaView in order to save server settings
776 and nullify application pointer if the application is being closed.
778 \param theApp application
780 void PVGUI_Module::onApplicationClosed( SUIT_Application* theApp )
782 PVViewer_ViewManager::ParaviewCleanup();
784 int aAppsNb = SUIT_Session::session()->applications().size();
786 deleteTemporaryFiles();
788 CAM_Module::onApplicationClosed(theApp);
793 \brief Deletes temporary files created during import operation from VISU
795 void PVGUI_Module::deleteTemporaryFiles()
797 foreach(QString aFile, myTemporaryFiles) {
798 if (QFile::exists(aFile)) {
799 QFile::remove(aFile);
806 \brief Called when study is closed.
808 Removes data model from the \a study.
810 \param study study being closed
812 void PVGUI_Module::studyClosed(SUIT_Study* study)
814 clearParaviewState();
816 LightApp_Module::studyClosed(study);
820 \brief Called when study is opened.
822 void PVGUI_Module::onModelOpened()
824 _PTR(Study) studyDS = PARAVIS::GetCStudy(this);
829 _PTR(SComponent) paravisComp =
830 studyDS->FindComponent(PARAVIS_MODULE_NAME);
835 _PTR(ChildIterator) anIter(studyDS->NewChildIterator(paravisComp));
836 for (; anIter->More(); anIter->Next()) {
837 _PTR(SObject) aSObj = anIter->Value();
838 _PTR(GenericAttribute) anAttr;
839 if (!aSObj->FindAttribute(anAttr, "AttributeLocalID")) {
842 _PTR(AttributeLocalID) anID(anAttr);
843 if (anID->Value() == PVSTATEID) {
850 \brief Returns IOR of current engine
852 QString PVGUI_Module::engineIOR() const
854 CORBA::String_var anIOR = GetCPPEngine()->GetIOR();
855 return QString(anIOR.in());
859 \brief Open file of format supported by ParaView
861 void PVGUI_Module::openFile(const char* theName)
865 pqLoadDataReaction::loadData(aFiles);
869 * Start trace invoking the newly introduced C++ API (PV 4.2)
870 * (inspired from pqTraceReaction::start())
872 void PVGUI_Module::startTrace()
874 vtkSMSessionProxyManager* pxm = pqActiveObjects::instance().activeServer()->proxyManager();
876 vtkSmartPointer<vtkSMProxy> proxy;
877 proxy.TakeReference(pxm->NewProxy("pythontracing", "PythonTraceOptions"));
880 vtkNew<vtkSMParaViewPipelineController> controller;
881 controller->InitializeProxy(proxy);
883 vtkSMTrace* trace = vtkSMTrace::StartTrace();
886 // Set manually the properties entered via the dialog box poping-up when requiring
887 // a trace start in PV4.2 (trace options)
888 trace->SetPropertiesToTraceOnCreate(vtkSMTrace::RECORD_USER_MODIFIED_PROPERTIES);
889 trace->SetFullyTraceSupplementalProxies(false);
893 void PVGUI_Module::stopTrace()
895 vtkSMTrace::StopTrace();
898 void PVGUI_Module::executeScript(const char *script)
901 pqPythonManager* manager = qobject_cast<pqPythonManager*>(
902 pqApplicationCore::instance()->manager("PYTHON_MANAGER"));
904 pqPythonDialog* pyDiag = manager->pythonShellDialog();
906 pyDiag->runString(script);
913 // * Debug function printing out the given interpreter's execution context
915 //void printInterpContext(PyInterp_Interp * interp )
917 // // Extract __smtraceString from interpreter's context
918 // const PyObject* ctxt = interp->getExecutionContext();
920 // PyObject* lst = PyDict_Keys((PyObject *)ctxt);
921 // Py_ssize_t siz = PyList_GET_SIZE(lst);
922 // for (Py_ssize_t i = 0; i < siz; i++)
924 // PyObject * elem = PyList_GetItem(lst, i);
925 // if (PyString_Check(elem))
927 // std::cout << "At pos:" << i << ", " << PyString_AsString(elem) << std::endl;
930 // std::cout << "At pos:" << i << ", not a string!" << std::endl;
936 \brief Returns trace string
938 static const QString MYReplaceStr("paraview.simple");
939 QString PVGUI_Module::getTraceString()
941 vtkSMTrace *tracer = vtkSMTrace::GetActiveTracer();
942 if (!tracer) // trace is not started
945 QString traceString(tracer->GetCurrentTrace());
946 std::stringstream nl; nl << std::endl; // surely there is some Qt trick to do that in a portable way??
947 QString end_line(nl.str().c_str());
948 // 'import pvsimple' is necessary to fix the first call to DisableFirstRenderCamera in the paraview trace
949 // 'ShowParaviewView()' ensure there is an opened viewing window (otherwise SEGFAULT!)
950 traceString = "import pvsimple" + end_line +
951 "pvsimple.ShowParaviewView()" + end_line + traceString;
953 // Replace import "paraview.simple" by "pvsimple"
954 if ((!traceString.isNull()) && traceString.length() != 0) {
955 int aPos = traceString.indexOf(MYReplaceStr);
957 traceString = traceString.replace(aPos, MYReplaceStr.length(), "pvsimple");
958 aPos = traceString.indexOf(MYReplaceStr, aPos);
966 \brief Saves trace string to disk file
968 void PVGUI_Module::saveTrace(const char* theName)
971 if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
972 MESSAGE( "Could not open file:" << theName );
975 QTextStream out(&file);
976 out << getTraceString();
981 \brief Saves ParaView state to a disk file
983 void PVGUI_Module::saveParaviewState(const char* theFileName)
985 pqApplicationCore::instance()->saveState(theFileName);
989 \brief Delete all objects for Paraview Pipeline Browser
991 void PVGUI_Module::clearParaviewState()
993 QAction* deleteAllAction = action(DeleteAllId);
994 if (deleteAllAction) {
995 deleteAllAction->activate(QAction::Trigger);
1000 \brief Restores ParaView state from a disk file
1002 If toClear == true, the current ojects will be deleted
1004 void PVGUI_Module::loadParaviewState(const char* theFileName)
1006 pqApplicationCore::instance()->loadState(theFileName, getActiveServer());
1010 \brief Returns current active ParaView server
1012 pqServer* PVGUI_Module::getActiveServer()
1014 return pqApplicationCore::instance()->getActiveServer();
1019 \brief Creates PARAVIS preference pane
1021 void PVGUI_Module::createPreferences()
1023 // Paraview settings tab
1024 int aParaViewSettingsTab = addPreference( tr( "TIT_PVIEWSETTINGS" ) );
1026 setPreferenceProperty(aParaViewSettingsTab, "stretch", false );
1027 int aPanel = addPreference(QString(), aParaViewSettingsTab, LightApp_Preferences::UserDefined, PARAVIS_MODULE_NAME, "");
1029 setPreferenceProperty(aPanel, "content", (qint64)(new PVGUI_ParaViewSettingsPane(0, getApp())));
1031 // Paravis settings tab
1032 int aParaVisSettingsTab = addPreference( tr( "TIT_PVISSETTINGS" ) );
1033 addPreference( tr( "PREF_STOP_TRACE" ), aParaVisSettingsTab, LightApp_Preferences::Bool, PARAVIS_MODULE_NAME, "stop_trace");
1035 addPreference( tr( "PREF_NO_EXT_PVSERVER" ), aParaVisSettingsTab, LightApp_Preferences::Bool, PARAVIS_MODULE_NAME, "no_ext_pv_server");
1037 int aSaveType = addPreference(tr( "PREF_SAVE_TYPE_LBL" ), aParaVisSettingsTab,
1038 LightApp_Preferences::Selector,
1039 PARAVIS_MODULE_NAME, "savestate_type");
1040 QList<QVariant> aIndices;
1041 QStringList aStrings;
1043 aStrings<<tr("PREF_SAVE_TYPE_0");
1044 aStrings<<tr("PREF_SAVE_TYPE_1");
1045 aStrings<<tr("PREF_SAVE_TYPE_2");
1046 setPreferenceProperty(aSaveType, "strings", aStrings);
1047 setPreferenceProperty(aSaveType, "indexes", aIndices);
1051 \brief Creates ParaViS context menu popup
1053 void PVGUI_Module::contextMenuPopup(const QString& theClient, QMenu* theMenu, QString& theTitle)
1055 LightApp_Module::contextMenuPopup(theClient, theMenu, theTitle);
1057 // Check if we are in Object Browser
1058 SUIT_DataBrowser* ob = getApp()->objectBrowser();
1059 bool isOBClient = (ob && theClient == ob->popupClientType());
1064 // Get list of selected objects
1065 LightApp_SelectionMgr* aSelectionMgr = getApp()->selectionMgr();
1066 SALOME_ListIO aListIO;
1067 aSelectionMgr->selectedObjects(aListIO);
1068 if (aListIO.Extent() == 1 && aListIO.First()->hasEntry()) {
1069 QString entry = QString(aListIO.First()->getEntry());
1072 SalomeApp_Study* activeStudy =
1073 dynamic_cast<SalomeApp_Study*>(getApp()->activeStudy());
1078 // Get SALOMEDS client study
1079 _PTR(Study) studyDS = activeStudy->studyDS();
1084 QString paravisDataType(PARAVIS_MODULE_NAME);
1085 if(activeStudy && activeStudy->isComponent(entry) &&
1086 activeStudy->componentDataType(entry) == paravisDataType) {
1087 // ParaViS module object
1088 theMenu->addSeparator();
1089 theMenu->addAction(action(SaveStatePopupId));
1092 // Try to get state object
1093 _PTR(SObject) stateSObj =
1094 studyDS->FindObjectID(entry.toLatin1().constData());
1100 _PTR(GenericAttribute) anAttr;
1101 if (!stateSObj->FindAttribute(anAttr, "AttributeLocalID")) {
1105 _PTR(AttributeLocalID) anID(anAttr);
1107 if (anID->Value() == PVSTATEID) {
1108 // Paraview state object
1109 theMenu->addSeparator();
1110 theMenu->addAction(action(AddStatePopupId));
1111 theMenu->addAction(action(CleanAndAddStatePopupId));
1112 theMenu->addSeparator();
1113 theMenu->addAction(action(ParaVisRenameId));
1114 theMenu->addAction(action(ParaVisDeleteId));
1121 \brief. Show ParaView python trace.
1123 void PVGUI_Module::onShowTrace()
1125 if (!myTraceWindow) {
1126 myTraceWindow = new pqPythonScriptEditor(getApp()->desktop());
1128 myTraceWindow->setText(getTraceString());
1129 myTraceWindow->show();
1130 myTraceWindow->raise();
1131 myTraceWindow->activateWindow();
1136 \brief. Re-initialize ParaView python trace.
1138 void PVGUI_Module::onRestartTrace()
1145 \brief Save state under the module root object.
1147 void PVGUI_Module::onSaveMultiState()
1149 // Create state study object
1151 // Get SALOMEDS client study
1152 _PTR(Study) studyDS = PARAVIS::GetCStudy(this);
1157 _PTR(SComponent) paravisComp =
1158 studyDS->FindComponent(PARAVIS_MODULE_NAME);
1163 // Unlock the study if it is locked
1164 bool isLocked = studyDS->GetProperties()->IsLocked();
1166 studyDS->GetProperties()->SetLocked(false);
1169 QString stateName = tr("SAVED_PARAVIEW_STATE_NAME") +
1170 QString::number(myStateCounter + 1);
1172 _PTR(StudyBuilder) studyBuilder = studyDS->NewBuilder();
1173 _PTR(SObject) newSObj = studyBuilder->NewObject(paravisComp);
1176 _PTR(GenericAttribute) anAttr;
1177 anAttr = studyBuilder->FindOrCreateAttribute(newSObj, "AttributeName");
1178 _PTR(AttributeName) nameAttr(anAttr);
1180 nameAttr->SetValue(stateName.toLatin1().constData());
1183 anAttr = studyBuilder->FindOrCreateAttribute(newSObj, "AttributeLocalID");
1184 _PTR(AttributeLocalID) localIdAttr(anAttr);
1186 localIdAttr->SetValue(PVSTATEID);
1189 QString stateEntry = QString::fromStdString(newSObj->GetID());
1191 // File name for state saving
1192 QString tmpDir = QString::fromStdString(SALOMEDS_Tool::GetTmpDir());
1193 QString fileName = QString("%1_paravisstate:%2").arg(tmpDir, stateEntry);
1195 anAttr = studyBuilder->FindOrCreateAttribute(newSObj, "AttributeString");
1196 _PTR(AttributeString) stringAttr(anAttr);
1198 stringAttr->SetValue(fileName.toLatin1().constData());
1200 // Lock the study back if necessary
1202 studyDS->GetProperties()->SetLocked(true);
1206 saveParaviewState(fileName.toLatin1().constData());
1207 myTemporaryFiles.append(fileName);
1209 // Increment the counter
1216 \brief Restore the selected state by merging with the current one.
1218 void PVGUI_Module::onAddState()
1220 loadSelectedState(false);
1224 \brief Clean the current state and restore the selected one.
1226 void PVGUI_Module::onCleanAddState()
1228 loadSelectedState(true);
1232 \brief Rename the selected object.
1234 void PVGUI_Module::onRename()
1236 LightApp_SelectionMgr* aSelectionMgr = getApp()->selectionMgr();
1237 SALOME_ListIO aListIO;
1238 aSelectionMgr->selectedObjects(aListIO);
1240 if (aListIO.Extent() == 1 && aListIO.First()->hasEntry()) {
1241 std::string entry = aListIO.First()->getEntry();
1243 // Get SALOMEDS client study
1244 _PTR(Study) studyDS = PARAVIS::GetCStudy(this);
1249 // Unlock the study if it is locked
1250 bool isLocked = studyDS->GetProperties()->IsLocked();
1252 studyDS->GetProperties()->SetLocked(false);
1255 // Rename the selected state object
1256 _PTR(SObject) stateSObj = studyDS->FindObjectID(entry);
1261 _PTR(GenericAttribute) anAttr;
1262 if (stateSObj->FindAttribute(anAttr, "AttributeName")) {
1263 _PTR(AttributeName) nameAttr (anAttr);
1265 LightApp_NameDlg::getName(getApp()->desktop(), nameAttr->Value().c_str());
1266 if (!newName.isEmpty()) {
1267 nameAttr->SetValue(newName.toLatin1().constData());
1268 aListIO.First()->setName(newName.toLatin1().constData());
1272 // Lock the study back if necessary
1274 studyDS->GetProperties()->SetLocked(true);
1277 // Update object browser
1284 \brief Delete the selected objects.
1286 void PVGUI_Module::onDelete()
1288 LightApp_SelectionMgr* aSelectionMgr = getApp()->selectionMgr();
1289 SALOME_ListIO aListIO;
1290 aSelectionMgr->selectedObjects(aListIO);
1292 if (aListIO.Extent() == 1 && aListIO.First()->hasEntry()) {
1293 std::string entry = aListIO.First()->getEntry();
1295 // Get SALOMEDS client study
1296 _PTR(Study) studyDS = PARAVIS::GetCStudy(this);
1301 // Unlock the study if it is locked
1302 bool isLocked = studyDS->GetProperties()->IsLocked();
1304 studyDS->GetProperties()->SetLocked(false);
1307 // Remove the selected state from the study
1308 _PTR(StudyBuilder) studyBuilder = studyDS->NewBuilder();
1309 _PTR(SObject) stateSObj = studyDS->FindObjectID(entry);
1310 studyBuilder->RemoveObject(stateSObj);
1312 // Lock the study back if necessary
1314 studyDS->GetProperties()->SetLocked(true);
1317 // Update object browser
1322 void PVGUI_Module::onPushTraceTimer()
1324 //MESSAGE("onPushTraceTimer(): Pushing trace to engine...");
1325 GetEngine()->PutPythonTraceStringToEngine(getTraceString().toStdString().c_str());
1329 \brief Discover help project files from the resources.
1330 \return name of the help file.
1332 QString PVGUI_Module::getHelpFileName() {
1333 QString aPVHome(getenv("PVHOME"));
1334 if (aPVHome.isNull()) {
1335 qWarning("Wariable PVHOME is not defined");
1338 QChar aSep = QDir::separator();
1339 //PARAVIEW_VERSION from the vtkPVConfig.h file
1340 QString aFileName = aPVHome + aSep + "share" + aSep + "doc" + aSep + "paraview-"+ PARAVIEW_VERSION + aSep + "paraview.qch";
1346 \brief Load selected paraview state
1348 If toClear == true, the current state will be cleared
1350 void PVGUI_Module::loadSelectedState(bool toClear)
1354 LightApp_SelectionMgr* aSelectionMgr = getApp()->selectionMgr();
1355 SALOME_ListIO aListIO;
1356 aSelectionMgr->selectedObjects(aListIO);
1358 if (aListIO.Extent() == 1 && aListIO.First()->hasEntry()) {
1359 std::string entry = aListIO.First()->getEntry();
1361 // Get SALOMEDS client study
1362 _PTR(Study) studyDS = PARAVIS::GetCStudy(this);
1368 _PTR(SObject) stateSObj = studyDS->FindObjectID(entry);
1369 _PTR(GenericAttribute) anAttr;
1370 if (!stateSObj->FindAttribute(anAttr, "AttributeLocalID")) {
1373 _PTR(AttributeLocalID) anID(anAttr);
1374 if (!anID->Value() == PVSTATEID) {
1378 // Get state file name
1379 if (stateSObj->FindAttribute(anAttr, "AttributeString")) {
1380 _PTR(AttributeString) aStringAttr(anAttr);
1381 QString stringValue(aStringAttr->Value().c_str());
1383 if (QFile::exists(stringValue)) {
1384 fileName = stringValue;
1389 if (!fileName.isEmpty()) {
1391 clearParaviewState();
1394 loadParaviewState(fileName.toLatin1().constData());
1397 SUIT_MessageBox::critical(getApp()->desktop(),
1399 tr("ERR_STATE_CANNOT_BE_RESTORED"));
1404 \fn CAM_Module* createModule();
1405 \brief Export module instance (factory function).
1406 \return new created instance of the module
1410 #define PVGUI_EXPORT __declspec(dllexport)
1412 #define PVGUI_EXPORT
1418 PVGUI_EXPORT CAM_Module* createModule() {
1419 return new PVGUI_Module();
1422 PVGUI_EXPORT char* getModuleVersion() {
1423 return (char*)PARAVIS_VERSION_STR;