1 // PARAVIS : ParaView wrapper SALOME module
3 // Copyright (C) 2010-2014 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 <pqActiveView.h>
116 #include <pqObjectBuilder.h>
117 #include <pqOptions.h>
118 #include <pqSettings.h>
119 #include <pqServer.h>
120 #include <pqUndoStack.h>
121 #include <pqTabbedMultiViewWidget.h>
122 #include <pqActiveObjects.h>
123 #include <pqHelpReaction.h>
124 #include <pqPluginManager.h>
125 #include <pqPythonDialog.h>
126 #include <pqPythonManager.h>
127 #include <pqLoadDataReaction.h>
128 #include <pqPythonScriptEditor.h>
129 #include <pqDataRepresentation.h>
130 #include <pqDisplayColorWidget.h>
131 #include <pqColorToolbar.h>
132 #include <pqScalarBarVisibilityReaction.h>
133 #include <pqServerResource.h>
134 #include <pqServerConnectReaction.h>
137 #include <PyInterp_Interp.h>
139 #include <PVViewer_EngineWrapper.h>
142 //----------------------------------------------------------------------------
143 PVGUI_Module* ParavisModule = 0;
144 PVSERVER_ORB::PVSERVER_Gen_var PVGUI_Module::MyEngine;
148 TODO TODO update this:
150 <h2>Building and installing PARAVIS</h2>
151 As any other SALOME module, PARAVIS requires PARAVIS_ROOT_DIR environment variable to be set to PARAVIS
152 installation directory.
153 Other variables needed for correct detection of ParaView location:
154 \li PVHOME - points at the ParaView installation directory tree
155 \li PVVERSION - number of ParaView version
157 It also requires common SALOME environment including GUI_ROOT_DIR and other prerequsites.
160 PARAVIS module can be launched using the following commands:
161 \li Full SALOME configuration
163 runSalome --modules="PARAVIS"
166 <h2>ParaView GUI integration</h2>
167 <h3>ParaView GUI integration overview</h3>
169 The main idea is to reuse ParaView GUI internal logic as much as possible, providing a layer
170 between it and SALOME GUI that hides the following SALOME GUI implementation details from ParaView:
172 \li SALOME GUI executable and Qt event loop
173 \li SALOME GUI desktop
174 \li Dock windows areas
175 \li SALOME menu and toolbar managers
177 Major part of the integration is implemented in PVGUI_Module class.
179 <h3>ParaView client initalization</h3>
181 ParaView client initalization is performed when an instance of PVGUI_Module class has been created
182 and \link PVGUI_Module::initialize() PVGUI_Module::initialize()\endlink method is called by SALOME GUI.
183 The actual client start-up is done in \link PVGUI_Module::pvInit() PVGUI_Module::pvInit()\endlink method.
186 <h3>Multi-view manager</h3>
188 SALOME GUI requires that each kind of view be implemnted with help of (at least) three classes. For ParaView multi-view manager
191 \li PVGUI_ViewManager - view manager class
192 \li PVGUI_Viewer - view model class
193 \li PVGUI_ViewWindow - view window class that acts as a parent for %pqViewManager
195 Single instances of PVGUI_ViewManager and PVGUI_ViewWindow classes are created by \link PVGUI_Module::showView()
196 PVGUI_Module::showView()\endlink method upon the first PARAVIS module activation. The same method hides the multi-view manager
197 when the module is deactivated (the user switches to another module or a study is closed).
198 A special trick is used to make PVGUI_ViewWindow the parent of %pqViewManager widget. It is created initally by %pqMainWindowCore
199 with the desktop as a parent, so when it is shown PVGUI_ViewWindow instance is passed to its setParent() method. In
200 \link PVGUI_ViewWindow::~PVGUI_ViewWindow() PVGUI_ViewWindow::~PVGUI_ViewWindow()\endlink the parent is nullified to avoid deletion
201 of %pqViewManager widget that would break %pqMainWindowCore class.
203 <h3>ParaView plugins</h3>
204 ParaView server and client plugins are managed by %pqMainWindowCore slots that has full access to PARAVIS menus and toolbars.
205 As a result they appears automatically in PARAVIS menus and toolbars if loaded successfully.
210 \brief Implementation
211 SALOME module wrapping ParaView GUI.
215 ClientFindOrCreateParavisComponent(_PTR(Study) theStudyDocument)
217 _PTR(SComponent) aSComponent = theStudyDocument->FindComponent("PVSERVER");
219 _PTR(StudyBuilder) aStudyBuilder = theStudyDocument->NewBuilder();
220 aStudyBuilder->NewCommand();
221 int aLocked = theStudyDocument->GetProperties()->IsLocked();
222 if (aLocked) theStudyDocument->GetProperties()->SetLocked(false);
223 aSComponent = aStudyBuilder->NewComponent("PVSERVER");
224 _PTR(GenericAttribute) anAttr =
225 aStudyBuilder->FindOrCreateAttribute(aSComponent, "AttributeName");
226 _PTR(AttributeName) aName (anAttr);
228 ORB_INIT& init = *SINGLETON_<ORB_INIT>::Instance();
229 CORBA::ORB_var anORB = init( qApp->argc(), qApp->argv() );
231 SALOME_NamingService *NamingService = new SALOME_NamingService( anORB );
232 CORBA::Object_var objVarN = NamingService->Resolve("/Kernel/ModulCatalog");
233 SALOME_ModuleCatalog::ModuleCatalog_var Catalogue =
234 SALOME_ModuleCatalog::ModuleCatalog::_narrow(objVarN);
235 SALOME_ModuleCatalog::Acomponent_var Comp = Catalogue->GetComponent( "PVSERVER" );
236 if (!Comp->_is_nil()) {
237 aName->SetValue(Comp->componentusername());
240 anAttr = aStudyBuilder->FindOrCreateAttribute(aSComponent, "AttributePixMap");
241 _PTR(AttributePixMap) aPixmap (anAttr);
242 aPixmap->SetPixMap( "pqAppIcon16.png" );
244 // Create Attribute parameters for future using
245 anAttr = aStudyBuilder->FindOrCreateAttribute(aSComponent, "AttributeParameter");
247 aStudyBuilder->DefineComponentInstance(aSComponent, PVGUI_Module::GetCPPEngine()->GetIOR());
248 if (aLocked) theStudyDocument->GetProperties()->SetLocked(true);
249 aStudyBuilder->CommitCommand();
255 Clean up function; used to stop ParaView progress events when
256 exception is caught by global exception handler.
258 void paravisCleanUp()
260 if ( pqApplicationCore::instance() ) {
261 pqServer* s = pqApplicationCore::instance()->getActiveServer();
262 if ( s ) s->session()->GetProgressHandler()->CleanupPendingProgress();
267 \brief Constructor. Sets the default name for the module.
269 PVGUI_Module::PVGUI_Module()
270 : SalomeApp_Module( PARAVIS_MODULE_NAME ),
271 mySelectionControlsTb( -1 ),
272 mySourcesMenuId( -1 ),
273 myFiltersMenuId( -1 ),
275 myToolbarsMenuId(-1),
285 Q_INIT_RESOURCE( PVGUI );
287 ParavisModule = this;
289 // Clear old copies of embedded macros files
290 QString aDestPath = QString( "%1/.config/%2/Macros" ).arg( QDir::homePath() ).arg( QApplication::applicationName() );
294 QDir aDestDir(aDestPath);
295 QStringList aDestFiles = aDestDir.entryList(aFilter, QDir::Files);
296 foreach (QString aMacrosPath, getEmbeddedMacrosList()) {
297 QString aMacrosName = QFileInfo(aMacrosPath).fileName();
298 if (aDestFiles.contains(aMacrosName)) {
299 aDestDir.remove(aMacrosName);
307 PVGUI_Module::~PVGUI_Module()
309 if (myPushTraceTimer)
310 delete myPushTraceTimer;
315 PVViewer_EngineWrapper * PVGUI_Module::GetEngine()
317 return PVViewer_EngineWrapper::GetInstance();
320 PVSERVER_ORB::PVSERVER_Gen_var PVGUI_Module::GetCPPEngine()
322 // initialize PARAVIS module engine (load, if necessary)
323 if ( CORBA::is_nil( MyEngine ) ) {
324 Engines::EngineComponent_var comp =
325 SalomeApp_Application::lcc()->FindOrLoad_Component( "FactoryServer", "PVSERVER" );
326 MyEngine = PVSERVER_ORB::PVSERVER_Gen::_narrow( comp );
332 \brief Create data model.
333 \return module specific data model
335 CAM_DataModel* PVGUI_Module::createDataModel()
337 return new PVGUI_DataModel( this );
340 pqPVApplicationCore * PVGUI_Module::GetPVApplication()
342 return PVViewer_ViewManager::GetPVApplication();
346 \brief Initialize module. Creates menus, prepares context menu, etc.
347 \param app SALOME GUI application instance
349 void PVGUI_Module::initialize( CAM_Application* app )
351 LightApp_Module::initialize( app );
353 // Create ParaViS actions
355 // Create ParaViS menus
358 // Uncomment to debug ParaView initialization
359 // "aa" used instead of "i" as GDB doesn't like "i" variables :)
367 LightApp_Application* anApp = getApp();
368 SUIT_Desktop* aDesktop = anApp->desktop();
370 // Initialize ParaView client and associated behaviors
371 // and connect to externally launched pvserver
372 PVViewer_ViewManager::ParaviewInitApp(aDesktop, anApp->logWindow());
373 myGuiElements = PVViewer_GUIElements::GetInstance(aDesktop);
375 // Remember current state of desktop toolbars
376 QList<QToolBar*> foreignToolbars = aDesktop->findChildren<QToolBar*>();
380 // Behaviors and connection must be instanciated *after* widgets are in place
381 // In PARAVIS module we do not wait for PVViewer_ViewWindow to be instanciated to have this:
382 PVViewer_ViewManager::ParaviewInitBehaviors(true, aDesktop);
388 // Connect after toolbar creation, etc ... as some activations of the toolbars is triggered
389 // by the ServerConnection event:
390 PVViewer_ViewManager::ConnectToExternalPVServer(aDesktop);
392 QList<QDockWidget*> activeDocks = aDesktop->findChildren<QDockWidget*>();
393 QList<QMenu*> activeMenus = aDesktop->findChildren<QMenu*>();
395 // Setup quick-launch shortcuts.
396 QShortcut *ctrlSpace = new QShortcut(Qt::CTRL + Qt::Key_Space, aDesktop);
397 QObject::connect(ctrlSpace, SIGNAL(activated()),
398 pqApplicationCore::instance(), SLOT(quickLaunch()));
400 // Find Plugin Dock Widgets
401 QList<QDockWidget*> currentDocks = aDesktop->findChildren<QDockWidget*>();
402 QList<QDockWidget*>::iterator i;
403 for (i = currentDocks.begin(); i != currentDocks.end(); ++i) {
404 if(!activeDocks.contains(*i)) {
405 myDockWidgets[*i] = false; // hidden by default
411 // [ABN] TODO: fix this - triggers a SEGFAULT at deactivation() time.
412 // QList<QMenu*> currentMenus = aDesktop->findChildren<QMenu*>();
413 // QList<QMenu*>::iterator im;
414 // for (im = currentMenus.begin(); im != currentMenus.end(); ++im) {
415 // if(!activeMenus.contains(*im)) {
416 // QString s = (*im)->title();
417 // std::cout << " MENU "<< s.toStdString() << std::endl;
418 // myMenus.append(*im);
422 PVViewer_ViewManager::ParaviewLoadConfigurations();
425 // Find created toolbars
426 QCoreApplication::processEvents();
428 QList<QToolBar*> allToolbars = aDesktop->findChildren<QToolBar*>();
429 foreach(QToolBar* aBar, allToolbars) {
430 if (!foreignToolbars.contains(aBar)) {
431 myToolbars[aBar] = true;
432 myToolbarBreaks[aBar] = false;
433 aBar->setVisible(false);
434 aBar->toggleViewAction()->setVisible(false);
440 SUIT_ResourceMgr* aResourceMgr = SUIT_Session::session()->resourceMgr();
441 bool isStop = aResourceMgr->booleanValue( PARAVIS_MODULE_NAME, "stop_trace", false );
444 // Start a timer to schedule asap:
446 myInitTimer = new QTimer(aDesktop);
447 QObject::connect(myInitTimer, SIGNAL(timeout()), this, SLOT(onInitTimer()) );
448 myInitTimer->setSingleShot(true);
449 myInitTimer->start(0);
451 // Another timer to regularly push the trace onto the engine:
452 myPushTraceTimer = new QTimer(aDesktop);
453 QObject::connect(myPushTraceTimer, SIGNAL(timeout()), this, SLOT(onPushTraceTimer()) );
454 myPushTraceTimer->setSingleShot(false);
455 myPushTraceTimer->start(500);
458 this->VTKConnect = vtkEventQtSlotConnect::New();
460 vtkProcessModule* pm = vtkProcessModule::GetProcessModule();
462 vtkPVSession* pvs = dynamic_cast<vtkPVSession*>(pm->GetSession());
464 vtkPVProgressHandler* ph = pvs->GetProgressHandler();
466 this->VTKConnect->Connect(ph, vtkCommand::StartEvent,
467 this, SLOT(onStartProgress()));
468 this->VTKConnect->Connect(ph, vtkCommand::EndEvent,
469 this, SLOT(onEndProgress()));
475 void PVGUI_Module::onStartProgress()
477 QApplication::setOverrideCursor(Qt::WaitCursor);
480 void PVGUI_Module::onEndProgress()
482 QApplication::restoreOverrideCursor();
485 void PVGUI_Module::onDataRepresentationUpdated() {
486 SalomeApp_Study* activeStudy = dynamic_cast<SalomeApp_Study*>(application()->activeStudy());
487 if(!activeStudy) return;
489 activeStudy->Modified();
493 \brief Initialisation timer event - trace start up
495 void PVGUI_Module::onInitTimer()
501 \brief Get list of embedded macros files
503 QStringList PVGUI_Module::getEmbeddedMacrosList()
505 QString aRootDir = getenv("PARAVIS_ROOT_DIR");
507 QString aSourcePath = aRootDir + "/bin/salome/Macro";
512 QDir aSourceDir(aSourcePath);
513 QStringList aSourceFiles = aSourceDir.entryList(aFilter, QDir::Files);
514 QStringList aFullPathSourceFiles;
515 foreach (QString aMacrosName, aSourceFiles) {
516 aFullPathSourceFiles << aSourceDir.absoluteFilePath(aMacrosName);
518 return aFullPathSourceFiles;
521 void PVGUI_Module::updateMacros()
523 pqPythonManager* aPythonManager = pqPVApplicationCore::instance()->pythonManager();
524 if(!aPythonManager) {
528 foreach (QString aStr, getEmbeddedMacrosList()) {
529 aPythonManager->addMacro(aStr);
535 \brief Get list of compliant dockable GUI elements
536 \param m map to be filled in ("type":"default_position")
538 void PVGUI_Module::windows( QMap<int, int>& m ) const
540 m.insert( LightApp_Application::WT_ObjectBrowser, Qt::LeftDockWidgetArea );
541 m.insert( LightApp_Application::WT_PyConsole, Qt::BottomDockWidgetArea );
542 // ParaView diagnostic output redirected here
543 m.insert( LightApp_Application::WT_LogWindow, Qt::BottomDockWidgetArea );
547 \brief Shows (toShow = true) or hides ParaView view window
549 void PVGUI_Module::showView( bool toShow )
551 LightApp_Application* anApp = getApp();
552 PVViewer_ViewManager* viewMgr =
553 dynamic_cast<PVViewer_ViewManager*>( anApp->getViewManager( PVViewer_Viewer::Type(), false ) );
555 viewMgr = new PVViewer_ViewManager( anApp->activeStudy(), anApp->desktop(), anApp->logWindow() );
556 anApp->addViewManager( viewMgr );
557 connect( viewMgr, SIGNAL( lastViewClosed( SUIT_ViewManager* ) ),
558 anApp, SLOT( onCloseView( SUIT_ViewManager* ) ) );
561 PVViewer_ViewWindow* pvWnd = dynamic_cast<PVViewer_ViewWindow*>( viewMgr->getActiveView() );
563 pvWnd = dynamic_cast<PVViewer_ViewWindow*>( viewMgr->createViewWindow() );
564 // this also connects to the pvserver and instantiates relevant PV behaviors
567 pvWnd->setShown( toShow );
568 if ( toShow ) pvWnd->setFocus();
572 \brief Slot to show help for proxy.
574 void PVGUI_Module::showHelpForProxy( const QString& groupname, const QString& proxyname )
576 pqHelpReaction::showProxyHelp(groupname, proxyname);
581 \brief Slot to show the waiting state.
583 void PVGUI_Module::onPreAccept()
585 getApp()->desktop()->statusBar()->showMessage(tr("STB_PREACCEPT"));
586 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
590 \brief Slot to show the ready state.
592 void PVGUI_Module::onPostAccept()
594 getApp()->desktop()->statusBar()->showMessage(tr("STB_POSTACCEPT"), 2000);
595 QTimer::singleShot(0, this, SLOT(endWaitCursor()));
599 \brief Slot to switch off wait cursor.
601 void PVGUI_Module::endWaitCursor()
603 QApplication::restoreOverrideCursor();
606 static void ParavisMessageOutput(QtMsgType type, const char *msg)
611 vtkOutputWindow::GetInstance()->DisplayText(msg);
614 vtkOutputWindow::GetInstance()->DisplayErrorText(msg);
617 vtkOutputWindow::GetInstance()->DisplayErrorText(msg);
620 vtkOutputWindow::GetInstance()->DisplayErrorText(msg);
626 \brief Activate module.
627 \param study current study
628 \return \c true if activaion is done successfully or 0 to prevent
631 bool PVGUI_Module::activateModule( SUIT_Study* study )
633 myOldMsgHandler = qInstallMsgHandler(ParavisMessageOutput);
635 SUIT_ExceptionHandler::addCleanUpRoutine( paravisCleanUp );
637 storeCommonWindowsState();
639 bool isDone = LightApp_Module::activateModule( study );
640 if ( !isDone ) return false;
643 if ( mySourcesMenuId != -1 ) menuMgr()->show(mySourcesMenuId);
644 if ( myFiltersMenuId != -1 ) menuMgr()->show(myFiltersMenuId);
645 if ( myMacrosMenuId != -1 ) menuMgr()->show(myMacrosMenuId);
646 if ( myToolbarsMenuId != -1 ) menuMgr()->show(myToolbarsMenuId);
648 // Update the various menus with the content pre-loaded in myGuiElements
649 // QMenu* srcMenu = menuMgr()->findMenu( mySourcesMenuId );
650 // myGuiElements->updateSourcesMenu(srcMenu);
651 // QMenu* filtMenu = menuMgr()->findMenu( myFiltersMenuId );
652 // myGuiElements->updateFiltersMenu(filtMenu);
653 // QMenu* macMenu = menuMgr()->findMenu( myMacrosMenuId );
654 // myGuiElements->updateMacrosMenu(macMenu);
656 setMenuShown( true );
657 setToolShown( true );
659 restoreDockWidgetsState();
661 QMenu* aMenu = menuMgr()->findMenu( myRecentMenuId );
663 QList<QAction*> anActns = aMenu->actions();
664 for (int i = 0; i < anActns.size(); ++i) {
665 QAction* a = anActns.at(i);
671 QList<QMenu*>::iterator it;
672 for (it = myMenus.begin(); it != myMenus.end(); ++it) {
673 QAction* a = (*it)->menuAction();
678 if ( myRecentMenuId != -1 ) menuMgr()->show(myRecentMenuId);
680 ClientFindOrCreateParavisComponent(PARAVIS::GetCStudy(this));
687 \brief Deactivate module.
688 \param study current study
689 \return \c true if deactivaion is done successfully or 0 to prevent
690 deactivation on error
692 bool PVGUI_Module::deactivateModule( SUIT_Study* study )
694 MESSAGE("PARAVIS deactivation ...")
696 QMenu* aMenu = menuMgr()->findMenu( myRecentMenuId );
698 QList<QAction*> anActns = aMenu->actions();
699 for (int i = 0; i < anActns.size(); ++i) {
700 QAction* a = anActns.at(i);
702 a->setVisible(false);
706 QList<QMenu*>::iterator it;
707 for (it = myMenus.begin(); it != myMenus.end(); ++it) {
708 QAction* a = (*it)->menuAction();
710 a->setVisible(false);
713 QList<QDockWidget*> aStreamingViews = application()->desktop()->findChildren<QDockWidget*>("pqStreamingControls");
714 foreach(QDockWidget* aView, aStreamingViews) {
715 if (!myDockWidgets.contains(aView))
716 myDockWidgets[aView] = aView->isVisible();
719 /*if (pqImplementation::helpWindow) {
720 pqImplementation::helpWindow->hide();
724 menuMgr()->hide(myRecentMenuId);
725 menuMgr()->hide(mySourcesMenuId);
726 menuMgr()->hide(myFiltersMenuId);
727 menuMgr()->hide(myMacrosMenuId);
728 menuMgr()->hide(myToolbarsMenuId);
729 setMenuShown( false );
730 setToolShown( false );
732 saveDockWidgetsState();
734 SUIT_ExceptionHandler::removeCleanUpRoutine( paravisCleanUp );
737 qInstallMsgHandler(myOldMsgHandler);
739 restoreCommonWindowsState();
741 return LightApp_Module::deactivateModule( study );
746 \brief Called when application is closed.
748 Process finalize application functionality from ParaView in order to save server settings
749 and nullify application pointer if the application is being closed.
751 \param theApp application
753 void PVGUI_Module::onApplicationClosed( SUIT_Application* theApp )
755 PVViewer_ViewManager::ParaviewCleanup();
757 int aAppsNb = SUIT_Session::session()->applications().size();
759 deleteTemporaryFiles();
761 CAM_Module::onApplicationClosed(theApp);
766 \brief Deletes temporary files created during import operation from VISU
768 void PVGUI_Module::deleteTemporaryFiles()
770 foreach(QString aFile, myTemporaryFiles) {
771 if (QFile::exists(aFile)) {
772 QFile::remove(aFile);
779 \brief Called when study is closed.
781 Removes data model from the \a study.
783 \param study study being closed
785 void PVGUI_Module::studyClosed(SUIT_Study* study)
787 clearParaviewState();
789 LightApp_Module::studyClosed(study);
793 \brief Called when study is opened.
795 void PVGUI_Module::onModelOpened()
797 _PTR(Study) studyDS = PARAVIS::GetCStudy(this);
802 _PTR(SComponent) paravisComp =
803 studyDS->FindComponent(PARAVIS_MODULE_NAME);
808 _PTR(ChildIterator) anIter(studyDS->NewChildIterator(paravisComp));
809 for (; anIter->More(); anIter->Next()) {
810 _PTR(SObject) aSObj = anIter->Value();
811 _PTR(GenericAttribute) anAttr;
812 if (!aSObj->FindAttribute(anAttr, "AttributeLocalID")) {
815 _PTR(AttributeLocalID) anID(anAttr);
816 if (anID->Value() == PVSTATEID) {
823 \brief Returns IOR of current engine
825 QString PVGUI_Module::engineIOR() const
827 CORBA::String_var anIOR = GetCPPEngine()->GetIOR();
828 return QString(anIOR.in());
832 \brief Open file of format supported by ParaView
834 void PVGUI_Module::openFile(const char* theName)
838 pqLoadDataReaction::loadData(aFiles);
842 * Start trace invoking the newly introduced C++ API (PV 4.2)
843 * (inspired from pqTraceReaction::start())
845 void PVGUI_Module::startTrace()
847 vtkSMSessionProxyManager* pxm = pqActiveObjects::instance().activeServer()->proxyManager();
849 vtkSmartPointer<vtkSMProxy> proxy;
850 proxy.TakeReference(pxm->NewProxy("pythontracing", "PythonTraceOptions"));
853 vtkNew<vtkSMParaViewPipelineController> controller;
854 controller->InitializeProxy(proxy);
856 vtkSMTrace* trace = vtkSMTrace::StartTrace();
859 // Set manually the properties entered via the dialog box poping-up when requiring
860 // a trace start in PV4.2 (trace options)
861 trace->SetPropertiesToTraceOnCreate(vtkSMTrace::RECORD_USER_MODIFIED_PROPERTIES);
862 trace->SetFullyTraceSupplementalProxies(false);
866 void PVGUI_Module::stopTrace()
868 vtkSMTrace::StopTrace();
871 void PVGUI_Module::executeScript(const char *script)
874 pqPythonManager* manager = qobject_cast<pqPythonManager*>(
875 pqApplicationCore::instance()->manager("PYTHON_MANAGER"));
877 pqPythonDialog* pyDiag = manager->pythonShellDialog();
879 pyDiag->runString(script);
886 // * Debug function printing out the given interpreter's execution context
888 //void printInterpContext(PyInterp_Interp * interp )
890 // // Extract __smtraceString from interpreter's context
891 // const PyObject* ctxt = interp->getExecutionContext();
893 // PyObject* lst = PyDict_Keys((PyObject *)ctxt);
894 // Py_ssize_t siz = PyList_GET_SIZE(lst);
895 // for (Py_ssize_t i = 0; i < siz; i++)
897 // PyObject * elem = PyList_GetItem(lst, i);
898 // if (PyString_Check(elem))
900 // std::cout << "At pos:" << i << ", " << PyString_AsString(elem) << std::endl;
903 // std::cout << "At pos:" << i << ", not a string!" << std::endl;
909 \brief Returns trace string
911 static const QString MYReplaceStr("paraview.simple");
912 QString PVGUI_Module::getTraceString()
914 vtkSMTrace *tracer = vtkSMTrace::GetActiveTracer();
915 if (!tracer) // trace is not started
918 QString traceString(tracer->GetCurrentTrace());
919 std::stringstream nl; nl << std::endl; // surely there is some Qt trick to do that in a portable way??
920 QString end_line(nl.str().c_str());
921 // 'import pvsimple' is necessary to fix the first call to DisableFirstRenderCamera in the paraview trace
922 // 'ShowParaviewView()' ensure there is an opened viewing window (otherwise SEGFAULT!)
923 traceString = "import pvsimple" + end_line +
924 "pvsimple.ShowParaviewView()" + end_line + traceString;
926 // Replace import "paraview.simple" by "pvsimple"
927 if ((!traceString.isNull()) && traceString.length() != 0) {
928 int aPos = traceString.indexOf(MYReplaceStr);
930 traceString = traceString.replace(aPos, MYReplaceStr.length(), "pvsimple");
931 aPos = traceString.indexOf(MYReplaceStr, aPos);
939 \brief Saves trace string to disk file
941 void PVGUI_Module::saveTrace(const char* theName)
944 if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
945 MESSAGE( "Could not open file:" << theName );
948 QTextStream out(&file);
949 out << getTraceString();
954 \brief Saves ParaView state to a disk file
956 void PVGUI_Module::saveParaviewState(const char* theFileName)
958 pqApplicationCore::instance()->saveState(theFileName);
962 \brief Delete all objects for Paraview Pipeline Browser
964 void PVGUI_Module::clearParaviewState()
966 QAction* deleteAllAction = action(DeleteAllId);
967 if (deleteAllAction) {
968 deleteAllAction->activate(QAction::Trigger);
973 \brief Restores ParaView state from a disk file
975 If toClear == true, the current ojects will be deleted
977 void PVGUI_Module::loadParaviewState(const char* theFileName)
979 pqApplicationCore::instance()->loadState(theFileName, getActiveServer());
983 \brief Returns current active ParaView server
985 pqServer* PVGUI_Module::getActiveServer()
987 return pqApplicationCore::instance()->getActiveServer();
992 \brief Creates PARAVIS preference pane
994 void PVGUI_Module::createPreferences()
996 // Paraview settings tab
997 int aParaViewSettingsTab = addPreference( tr( "TIT_PVIEWSETTINGS" ) );
999 setPreferenceProperty(aParaViewSettingsTab, "stretch", false );
1000 int aPanel = addPreference(QString(), aParaViewSettingsTab, LightApp_Preferences::UserDefined, PARAVIS_MODULE_NAME, "");
1002 setPreferenceProperty(aPanel, "content", (qint64)(new PVGUI_ParaViewSettingsPane(0, getApp())));
1004 // Paravis settings tab
1005 int aParaVisSettingsTab = addPreference( tr( "TIT_PVISSETTINGS" ) );
1006 addPreference( tr( "PREF_STOP_TRACE" ), aParaVisSettingsTab, LightApp_Preferences::Bool, PARAVIS_MODULE_NAME, "stop_trace");
1008 addPreference( tr( "PREF_NO_EXT_PVSERVER" ), aParaVisSettingsTab, LightApp_Preferences::Bool, PARAVIS_MODULE_NAME, "no_ext_pv_server");
1010 int aSaveType = addPreference(tr( "PREF_SAVE_TYPE_LBL" ), aParaVisSettingsTab,
1011 LightApp_Preferences::Selector,
1012 PARAVIS_MODULE_NAME, "savestate_type");
1013 QList<QVariant> aIndices;
1014 QStringList aStrings;
1016 aStrings<<tr("PREF_SAVE_TYPE_0");
1017 aStrings<<tr("PREF_SAVE_TYPE_1");
1018 aStrings<<tr("PREF_SAVE_TYPE_2");
1019 setPreferenceProperty(aSaveType, "strings", aStrings);
1020 setPreferenceProperty(aSaveType, "indexes", aIndices);
1024 \brief Creates ParaViS context menu popup
1026 void PVGUI_Module::contextMenuPopup(const QString& theClient, QMenu* theMenu, QString& theTitle)
1028 LightApp_Module::contextMenuPopup(theClient, theMenu, theTitle);
1030 // Check if we are in Object Browser
1031 SUIT_DataBrowser* ob = getApp()->objectBrowser();
1032 bool isOBClient = (ob && theClient == ob->popupClientType());
1037 // Get list of selected objects
1038 LightApp_SelectionMgr* aSelectionMgr = getApp()->selectionMgr();
1039 SALOME_ListIO aListIO;
1040 aSelectionMgr->selectedObjects(aListIO);
1041 if (aListIO.Extent() == 1 && aListIO.First()->hasEntry()) {
1042 QString entry = QString(aListIO.First()->getEntry());
1045 SalomeApp_Study* activeStudy =
1046 dynamic_cast<SalomeApp_Study*>(getApp()->activeStudy());
1051 // Get SALOMEDS client study
1052 _PTR(Study) studyDS = activeStudy->studyDS();
1057 QString paravisDataType(PARAVIS_MODULE_NAME);
1058 if(activeStudy && activeStudy->isComponent(entry) &&
1059 activeStudy->componentDataType(entry) == paravisDataType) {
1060 // ParaViS module object
1061 theMenu->addSeparator();
1062 theMenu->addAction(action(SaveStatePopupId));
1065 // Try to get state object
1066 _PTR(SObject) stateSObj =
1067 studyDS->FindObjectID(entry.toLatin1().constData());
1073 _PTR(GenericAttribute) anAttr;
1074 if (!stateSObj->FindAttribute(anAttr, "AttributeLocalID")) {
1078 _PTR(AttributeLocalID) anID(anAttr);
1080 if (anID->Value() == PVSTATEID) {
1081 // Paraview state object
1082 theMenu->addSeparator();
1083 theMenu->addAction(action(AddStatePopupId));
1084 theMenu->addAction(action(CleanAndAddStatePopupId));
1085 theMenu->addSeparator();
1086 theMenu->addAction(action(ParaVisRenameId));
1087 theMenu->addAction(action(ParaVisDeleteId));
1094 \brief. Show ParaView python trace.
1096 void PVGUI_Module::onShowTrace()
1098 if (!myTraceWindow) {
1099 myTraceWindow = new pqPythonScriptEditor(getApp()->desktop());
1101 myTraceWindow->setText(getTraceString());
1102 myTraceWindow->show();
1103 myTraceWindow->raise();
1104 myTraceWindow->activateWindow();
1109 \brief. Re-initialize ParaView python trace.
1111 void PVGUI_Module::onRestartTrace()
1118 \brief Save state under the module root object.
1120 void PVGUI_Module::onSaveMultiState()
1122 // Create state study object
1124 // Get SALOMEDS client study
1125 _PTR(Study) studyDS = PARAVIS::GetCStudy(this);
1130 _PTR(SComponent) paravisComp =
1131 studyDS->FindComponent(PARAVIS_MODULE_NAME);
1136 // Unlock the study if it is locked
1137 bool isLocked = studyDS->GetProperties()->IsLocked();
1139 studyDS->GetProperties()->SetLocked(false);
1142 QString stateName = tr("SAVED_PARAVIEW_STATE_NAME") +
1143 QString::number(myStateCounter + 1);
1145 _PTR(StudyBuilder) studyBuilder = studyDS->NewBuilder();
1146 _PTR(SObject) newSObj = studyBuilder->NewObject(paravisComp);
1149 _PTR(GenericAttribute) anAttr;
1150 anAttr = studyBuilder->FindOrCreateAttribute(newSObj, "AttributeName");
1151 _PTR(AttributeName) nameAttr(anAttr);
1153 nameAttr->SetValue(stateName.toLatin1().constData());
1156 anAttr = studyBuilder->FindOrCreateAttribute(newSObj, "AttributeLocalID");
1157 _PTR(AttributeLocalID) localIdAttr(anAttr);
1159 localIdAttr->SetValue(PVSTATEID);
1162 QString stateEntry = QString::fromStdString(newSObj->GetID());
1164 // File name for state saving
1165 QString tmpDir = QString::fromStdString(SALOMEDS_Tool::GetTmpDir());
1166 QString fileName = QString("%1_paravisstate:%2").arg(tmpDir, stateEntry);
1168 anAttr = studyBuilder->FindOrCreateAttribute(newSObj, "AttributeString");
1169 _PTR(AttributeString) stringAttr(anAttr);
1171 stringAttr->SetValue(fileName.toLatin1().constData());
1173 // Lock the study back if necessary
1175 studyDS->GetProperties()->SetLocked(true);
1179 saveParaviewState(fileName.toLatin1().constData());
1180 myTemporaryFiles.append(fileName);
1182 // Increment the counter
1189 \brief Restore the selected state by merging with the current one.
1191 void PVGUI_Module::onAddState()
1193 loadSelectedState(false);
1197 \brief Clean the current state and restore the selected one.
1199 void PVGUI_Module::onCleanAddState()
1201 loadSelectedState(true);
1205 \brief Rename the selected object.
1207 void PVGUI_Module::onRename()
1209 LightApp_SelectionMgr* aSelectionMgr = getApp()->selectionMgr();
1210 SALOME_ListIO aListIO;
1211 aSelectionMgr->selectedObjects(aListIO);
1213 if (aListIO.Extent() == 1 && aListIO.First()->hasEntry()) {
1214 std::string entry = aListIO.First()->getEntry();
1216 // Get SALOMEDS client study
1217 _PTR(Study) studyDS = PARAVIS::GetCStudy(this);
1222 // Unlock the study if it is locked
1223 bool isLocked = studyDS->GetProperties()->IsLocked();
1225 studyDS->GetProperties()->SetLocked(false);
1228 // Rename the selected state object
1229 _PTR(SObject) stateSObj = studyDS->FindObjectID(entry);
1234 _PTR(GenericAttribute) anAttr;
1235 if (stateSObj->FindAttribute(anAttr, "AttributeName")) {
1236 _PTR(AttributeName) nameAttr (anAttr);
1238 LightApp_NameDlg::getName(getApp()->desktop(), nameAttr->Value().c_str());
1239 if (!newName.isEmpty()) {
1240 nameAttr->SetValue(newName.toLatin1().constData());
1241 aListIO.First()->setName(newName.toLatin1().constData());
1245 // Lock the study back if necessary
1247 studyDS->GetProperties()->SetLocked(true);
1250 // Update object browser
1257 \brief Delete the selected objects.
1259 void PVGUI_Module::onDelete()
1261 LightApp_SelectionMgr* aSelectionMgr = getApp()->selectionMgr();
1262 SALOME_ListIO aListIO;
1263 aSelectionMgr->selectedObjects(aListIO);
1265 if (aListIO.Extent() == 1 && aListIO.First()->hasEntry()) {
1266 std::string entry = aListIO.First()->getEntry();
1268 // Get SALOMEDS client study
1269 _PTR(Study) studyDS = PARAVIS::GetCStudy(this);
1274 // Unlock the study if it is locked
1275 bool isLocked = studyDS->GetProperties()->IsLocked();
1277 studyDS->GetProperties()->SetLocked(false);
1280 // Remove the selected state from the study
1281 _PTR(StudyBuilder) studyBuilder = studyDS->NewBuilder();
1282 _PTR(SObject) stateSObj = studyDS->FindObjectID(entry);
1283 studyBuilder->RemoveObject(stateSObj);
1285 // Lock the study back if necessary
1287 studyDS->GetProperties()->SetLocked(true);
1290 // Update object browser
1295 void PVGUI_Module::onPushTraceTimer()
1297 //MESSAGE("onPushTraceTimer(): Pushing trace to engine...");
1298 GetEngine()->PutPythonTraceStringToEngine(getTraceString().toStdString().c_str());
1302 \brief Discover help project files from the resources.
1303 \return name of the help file.
1305 QString PVGUI_Module::getHelpFileName() {
1306 QString aPVHome(getenv("PVHOME"));
1307 if (aPVHome.isNull()) {
1308 qWarning("Wariable PVHOME is not defined");
1311 QChar aSep = QDir::separator();
1312 //PARAVIEW_VERSION from the vtkPVConfig.h file
1313 QString aFileName = aPVHome + aSep + "share" + aSep + "doc" + aSep + "paraview-"+ PARAVIEW_VERSION + aSep + "paraview.qch";
1319 \brief Load selected paraview state
1321 If toClear == true, the current state will be cleared
1323 void PVGUI_Module::loadSelectedState(bool toClear)
1327 LightApp_SelectionMgr* aSelectionMgr = getApp()->selectionMgr();
1328 SALOME_ListIO aListIO;
1329 aSelectionMgr->selectedObjects(aListIO);
1331 if (aListIO.Extent() == 1 && aListIO.First()->hasEntry()) {
1332 std::string entry = aListIO.First()->getEntry();
1334 // Get SALOMEDS client study
1335 _PTR(Study) studyDS = PARAVIS::GetCStudy(this);
1341 _PTR(SObject) stateSObj = studyDS->FindObjectID(entry);
1342 _PTR(GenericAttribute) anAttr;
1343 if (!stateSObj->FindAttribute(anAttr, "AttributeLocalID")) {
1346 _PTR(AttributeLocalID) anID(anAttr);
1347 if (!anID->Value() == PVSTATEID) {
1351 // Get state file name
1352 if (stateSObj->FindAttribute(anAttr, "AttributeString")) {
1353 _PTR(AttributeString) aStringAttr(anAttr);
1354 QString stringValue(aStringAttr->Value().c_str());
1356 if (QFile::exists(stringValue)) {
1357 fileName = stringValue;
1362 if (!fileName.isEmpty()) {
1364 clearParaviewState();
1367 loadParaviewState(fileName.toLatin1().constData());
1370 SUIT_MessageBox::critical(getApp()->desktop(),
1372 tr("ERR_STATE_CANNOT_BE_RESTORED"));
1377 \fn CAM_Module* createModule();
1378 \brief Export module instance (factory function).
1379 \return new created instance of the module
1383 #define PVGUI_EXPORT __declspec(dllexport)
1385 #define PVGUI_EXPORT
1391 PVGUI_EXPORT CAM_Module* createModule() {
1392 return new PVGUI_Module();
1395 PVGUI_EXPORT char* getModuleVersion() {
1396 return (char*)PARAVIS_VERSION_STR;