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);
383 PVViewer_ViewManager::ConnectToExternalPVServer(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 PVViewer_ViewManager::ParaviewLoadConfigurations();
422 // Find created toolbars
423 QCoreApplication::processEvents();
425 QList<QToolBar*> allToolbars = aDesktop->findChildren<QToolBar*>();
426 foreach(QToolBar* aBar, allToolbars) {
427 if (!foreignToolbars.contains(aBar)) {
428 myToolbars[aBar] = true;
429 myToolbarBreaks[aBar] = false;
430 aBar->setVisible(false);
431 aBar->toggleViewAction()->setVisible(false);
437 SUIT_ResourceMgr* aResourceMgr = SUIT_Session::session()->resourceMgr();
438 bool isStop = aResourceMgr->booleanValue( PARAVIS_MODULE_NAME, "stop_trace", false );
441 // Start a timer to schedule asap:
443 myInitTimer = new QTimer(aDesktop);
444 QObject::connect(myInitTimer, SIGNAL(timeout()), this, SLOT(onInitTimer()) );
445 myInitTimer->setSingleShot(true);
446 myInitTimer->start(0);
448 // Another timer to regularly push the trace onto the engine:
449 myPushTraceTimer = new QTimer(aDesktop);
450 QObject::connect(myPushTraceTimer, SIGNAL(timeout()), this, SLOT(onPushTraceTimer()) );
451 myPushTraceTimer->setSingleShot(false);
452 myPushTraceTimer->start(500);
455 this->VTKConnect = vtkEventQtSlotConnect::New();
457 vtkProcessModule* pm = vtkProcessModule::GetProcessModule();
459 vtkPVSession* pvs = dynamic_cast<vtkPVSession*>(pm->GetSession());
461 vtkPVProgressHandler* ph = pvs->GetProgressHandler();
463 this->VTKConnect->Connect(ph, vtkCommand::StartEvent,
464 this, SLOT(onStartProgress()));
465 this->VTKConnect->Connect(ph, vtkCommand::EndEvent,
466 this, SLOT(onEndProgress()));
472 void PVGUI_Module::onStartProgress()
474 QApplication::setOverrideCursor(Qt::WaitCursor);
477 void PVGUI_Module::onEndProgress()
479 QApplication::restoreOverrideCursor();
482 void PVGUI_Module::onDataRepresentationUpdated() {
483 SalomeApp_Study* activeStudy = dynamic_cast<SalomeApp_Study*>(application()->activeStudy());
484 if(!activeStudy) return;
486 activeStudy->Modified();
490 \brief Initialisation timer event - trace start up
492 void PVGUI_Module::onInitTimer()
498 \brief Get list of embedded macros files
500 QStringList PVGUI_Module::getEmbeddedMacrosList()
502 QString aRootDir = getenv("PARAVIS_ROOT_DIR");
504 QString aSourcePath = aRootDir + "/bin/salome/Macro";
509 QDir aSourceDir(aSourcePath);
510 QStringList aSourceFiles = aSourceDir.entryList(aFilter, QDir::Files);
511 QStringList aFullPathSourceFiles;
512 foreach (QString aMacrosName, aSourceFiles) {
513 aFullPathSourceFiles << aSourceDir.absoluteFilePath(aMacrosName);
515 return aFullPathSourceFiles;
518 void PVGUI_Module::updateMacros()
520 pqPythonManager* aPythonManager = pqPVApplicationCore::instance()->pythonManager();
521 if(!aPythonManager) {
525 foreach (QString aStr, getEmbeddedMacrosList()) {
526 aPythonManager->addMacro(aStr);
532 \brief Get list of compliant dockable GUI elements
533 \param m map to be filled in ("type":"default_position")
535 void PVGUI_Module::windows( QMap<int, int>& m ) const
537 m.insert( LightApp_Application::WT_ObjectBrowser, Qt::LeftDockWidgetArea );
538 m.insert( LightApp_Application::WT_PyConsole, Qt::BottomDockWidgetArea );
539 // ParaView diagnostic output redirected here
540 m.insert( LightApp_Application::WT_LogWindow, Qt::BottomDockWidgetArea );
544 \brief Shows (toShow = true) or hides ParaView view window
546 void PVGUI_Module::showView( bool toShow )
548 LightApp_Application* anApp = getApp();
549 PVViewer_ViewManager* viewMgr =
550 dynamic_cast<PVViewer_ViewManager*>( anApp->getViewManager( PVViewer_Viewer::Type(), false ) );
552 viewMgr = new PVViewer_ViewManager( anApp->activeStudy(), anApp->desktop(), anApp->logWindow() );
553 anApp->addViewManager( viewMgr );
554 connect( viewMgr, SIGNAL( lastViewClosed( SUIT_ViewManager* ) ),
555 anApp, SLOT( onCloseView( SUIT_ViewManager* ) ) );
558 PVViewer_ViewWindow* pvWnd = dynamic_cast<PVViewer_ViewWindow*>( viewMgr->getActiveView() );
560 pvWnd = dynamic_cast<PVViewer_ViewWindow*>( viewMgr->createViewWindow() );
561 // this also connects to the pvserver and instantiates relevant PV behaviors
564 pvWnd->setShown( toShow );
565 if ( toShow ) pvWnd->setFocus();
569 \brief Slot to show help for proxy.
571 void PVGUI_Module::showHelpForProxy( const QString& groupname, const QString& proxyname )
573 pqHelpReaction::showProxyHelp(groupname, proxyname);
578 \brief Slot to show the waiting state.
580 void PVGUI_Module::onPreAccept()
582 getApp()->desktop()->statusBar()->showMessage(tr("STB_PREACCEPT"));
583 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
587 \brief Slot to show the ready state.
589 void PVGUI_Module::onPostAccept()
591 getApp()->desktop()->statusBar()->showMessage(tr("STB_POSTACCEPT"), 2000);
592 QTimer::singleShot(0, this, SLOT(endWaitCursor()));
596 \brief Slot to switch off wait cursor.
598 void PVGUI_Module::endWaitCursor()
600 QApplication::restoreOverrideCursor();
603 static void ParavisMessageOutput(QtMsgType type, const char *msg)
608 vtkOutputWindow::GetInstance()->DisplayText(msg);
611 vtkOutputWindow::GetInstance()->DisplayErrorText(msg);
614 vtkOutputWindow::GetInstance()->DisplayErrorText(msg);
617 vtkOutputWindow::GetInstance()->DisplayErrorText(msg);
623 \brief Activate module.
624 \param study current study
625 \return \c true if activaion is done successfully or 0 to prevent
628 bool PVGUI_Module::activateModule( SUIT_Study* study )
630 myOldMsgHandler = qInstallMsgHandler(ParavisMessageOutput);
632 SUIT_ExceptionHandler::addCleanUpRoutine( paravisCleanUp );
634 storeCommonWindowsState();
636 bool isDone = LightApp_Module::activateModule( study );
637 if ( !isDone ) return false;
640 if ( mySourcesMenuId != -1 ) menuMgr()->show(mySourcesMenuId);
641 if ( myFiltersMenuId != -1 ) menuMgr()->show(myFiltersMenuId);
642 if ( myMacrosMenuId != -1 ) menuMgr()->show(myMacrosMenuId);
643 if ( myToolbarsMenuId != -1 ) menuMgr()->show(myToolbarsMenuId);
645 // Update the various menus with the content pre-loaded in myGuiElements
646 // QMenu* srcMenu = menuMgr()->findMenu( mySourcesMenuId );
647 // myGuiElements->updateSourcesMenu(srcMenu);
648 // QMenu* filtMenu = menuMgr()->findMenu( myFiltersMenuId );
649 // myGuiElements->updateFiltersMenu(filtMenu);
650 // QMenu* macMenu = menuMgr()->findMenu( myMacrosMenuId );
651 // myGuiElements->updateMacrosMenu(macMenu);
653 setMenuShown( true );
654 setToolShown( true );
656 restoreDockWidgetsState();
658 QMenu* aMenu = menuMgr()->findMenu( myRecentMenuId );
660 QList<QAction*> anActns = aMenu->actions();
661 for (int i = 0; i < anActns.size(); ++i) {
662 QAction* a = anActns.at(i);
668 QList<QMenu*>::iterator it;
669 for (it = myMenus.begin(); it != myMenus.end(); ++it) {
670 QAction* a = (*it)->menuAction();
675 if ( myRecentMenuId != -1 ) menuMgr()->show(myRecentMenuId);
677 ClientFindOrCreateParavisComponent(PARAVIS::GetCStudy(this));
684 \brief Deactivate module.
685 \param study current study
686 \return \c true if deactivaion is done successfully or 0 to prevent
687 deactivation on error
689 bool PVGUI_Module::deactivateModule( SUIT_Study* study )
691 MESSAGE("PARAVIS deactivation ...")
693 QMenu* aMenu = menuMgr()->findMenu( myRecentMenuId );
695 QList<QAction*> anActns = aMenu->actions();
696 for (int i = 0; i < anActns.size(); ++i) {
697 QAction* a = anActns.at(i);
699 a->setVisible(false);
703 QList<QMenu*>::iterator it;
704 for (it = myMenus.begin(); it != myMenus.end(); ++it) {
705 QAction* a = (*it)->menuAction();
707 a->setVisible(false);
710 QList<QDockWidget*> aStreamingViews = application()->desktop()->findChildren<QDockWidget*>("pqStreamingControls");
711 foreach(QDockWidget* aView, aStreamingViews) {
712 if (!myDockWidgets.contains(aView))
713 myDockWidgets[aView] = aView->isVisible();
716 /*if (pqImplementation::helpWindow) {
717 pqImplementation::helpWindow->hide();
721 menuMgr()->hide(myRecentMenuId);
722 menuMgr()->hide(mySourcesMenuId);
723 menuMgr()->hide(myFiltersMenuId);
724 menuMgr()->hide(myMacrosMenuId);
725 menuMgr()->hide(myToolbarsMenuId);
726 setMenuShown( false );
727 setToolShown( false );
729 saveDockWidgetsState();
731 SUIT_ExceptionHandler::removeCleanUpRoutine( paravisCleanUp );
734 qInstallMsgHandler(myOldMsgHandler);
736 restoreCommonWindowsState();
738 return LightApp_Module::deactivateModule( study );
743 \brief Called when application is closed.
745 Process finalize application functionality from ParaView in order to save server settings
746 and nullify application pointer if the application is being closed.
748 \param theApp application
750 void PVGUI_Module::onApplicationClosed( SUIT_Application* theApp )
752 PVViewer_ViewManager::ParaviewCleanup();
754 int aAppsNb = SUIT_Session::session()->applications().size();
756 deleteTemporaryFiles();
758 CAM_Module::onApplicationClosed(theApp);
763 \brief Deletes temporary files created during import operation from VISU
765 void PVGUI_Module::deleteTemporaryFiles()
767 foreach(QString aFile, myTemporaryFiles) {
768 if (QFile::exists(aFile)) {
769 QFile::remove(aFile);
776 \brief Called when study is closed.
778 Removes data model from the \a study.
780 \param study study being closed
782 void PVGUI_Module::studyClosed(SUIT_Study* study)
784 clearParaviewState();
786 LightApp_Module::studyClosed(study);
790 \brief Called when study is opened.
792 void PVGUI_Module::onModelOpened()
794 _PTR(Study) studyDS = PARAVIS::GetCStudy(this);
799 _PTR(SComponent) paravisComp =
800 studyDS->FindComponent(PARAVIS_MODULE_NAME);
805 _PTR(ChildIterator) anIter(studyDS->NewChildIterator(paravisComp));
806 for (; anIter->More(); anIter->Next()) {
807 _PTR(SObject) aSObj = anIter->Value();
808 _PTR(GenericAttribute) anAttr;
809 if (!aSObj->FindAttribute(anAttr, "AttributeLocalID")) {
812 _PTR(AttributeLocalID) anID(anAttr);
813 if (anID->Value() == PVSTATEID) {
820 \brief Returns IOR of current engine
822 QString PVGUI_Module::engineIOR() const
824 CORBA::String_var anIOR = GetCPPEngine()->GetIOR();
825 return QString(anIOR.in());
829 \brief Open file of format supported by ParaView
831 void PVGUI_Module::openFile(const char* theName)
835 pqLoadDataReaction::loadData(aFiles);
839 * Start trace invoking the newly introduced C++ API (PV 4.2)
840 * (inspired from pqTraceReaction::start())
842 void PVGUI_Module::startTrace()
844 vtkSMSessionProxyManager* pxm = pqActiveObjects::instance().activeServer()->proxyManager();
846 vtkSmartPointer<vtkSMProxy> proxy;
847 proxy.TakeReference(pxm->NewProxy("pythontracing", "PythonTraceOptions"));
850 vtkNew<vtkSMParaViewPipelineController> controller;
851 controller->InitializeProxy(proxy);
853 vtkSMTrace* trace = vtkSMTrace::StartTrace();
856 // Set manually the properties entered via the dialog box poping-up when requiring
857 // a trace start in PV4.2 (trace options)
858 trace->SetPropertiesToTraceOnCreate(vtkSMTrace::RECORD_USER_MODIFIED_PROPERTIES);
859 trace->SetFullyTraceSupplementalProxies(false);
863 void PVGUI_Module::stopTrace()
865 vtkSMTrace::StopTrace();
868 void PVGUI_Module::executeScript(const char *script)
871 pqPythonManager* manager = qobject_cast<pqPythonManager*>(
872 pqApplicationCore::instance()->manager("PYTHON_MANAGER"));
874 pqPythonDialog* pyDiag = manager->pythonShellDialog();
876 pyDiag->runString(script);
883 // * Debug function printing out the given interpreter's execution context
885 //void printInterpContext(PyInterp_Interp * interp )
887 // // Extract __smtraceString from interpreter's context
888 // const PyObject* ctxt = interp->getExecutionContext();
890 // PyObject* lst = PyDict_Keys((PyObject *)ctxt);
891 // Py_ssize_t siz = PyList_GET_SIZE(lst);
892 // for (Py_ssize_t i = 0; i < siz; i++)
894 // PyObject * elem = PyList_GetItem(lst, i);
895 // if (PyString_Check(elem))
897 // std::cout << "At pos:" << i << ", " << PyString_AsString(elem) << std::endl;
900 // std::cout << "At pos:" << i << ", not a string!" << std::endl;
906 \brief Returns trace string
908 static const QString MYReplaceStr("paraview.simple");
909 QString PVGUI_Module::getTraceString()
911 vtkSMTrace *tracer = vtkSMTrace::GetActiveTracer();
912 if (!tracer) // trace is not started
915 QString traceString(tracer->GetCurrentTrace());
916 std::stringstream nl; nl << std::endl; // surely there is some Qt trick to do that in a portable way??
917 QString end_line(nl.str().c_str());
918 // 'import pvsimple' is necessary to fix the first call to DisableFirstRenderCamera in the paraview trace
919 // 'ShowParaviewView()' ensure there is an opened viewing window (otherwise SEGFAULT!)
920 traceString = "import pvsimple" + end_line +
921 "pvsimple.ShowParaviewView()" + end_line + traceString;
923 // Replace import "paraview.simple" by "pvsimple"
924 if ((!traceString.isNull()) && traceString.length() != 0) {
925 int aPos = traceString.indexOf(MYReplaceStr);
927 traceString = traceString.replace(aPos, MYReplaceStr.length(), "pvsimple");
928 aPos = traceString.indexOf(MYReplaceStr, aPos);
936 \brief Saves trace string to disk file
938 void PVGUI_Module::saveTrace(const char* theName)
941 if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
942 MESSAGE( "Could not open file:" << theName );
945 QTextStream out(&file);
946 out << getTraceString();
951 \brief Saves ParaView state to a disk file
953 void PVGUI_Module::saveParaviewState(const char* theFileName)
955 pqApplicationCore::instance()->saveState(theFileName);
959 \brief Delete all objects for Paraview Pipeline Browser
961 void PVGUI_Module::clearParaviewState()
963 QAction* deleteAllAction = action(DeleteAllId);
964 if (deleteAllAction) {
965 deleteAllAction->activate(QAction::Trigger);
970 \brief Restores ParaView state from a disk file
972 If toClear == true, the current ojects will be deleted
974 void PVGUI_Module::loadParaviewState(const char* theFileName)
976 pqApplicationCore::instance()->loadState(theFileName, getActiveServer());
980 \brief Returns current active ParaView server
982 pqServer* PVGUI_Module::getActiveServer()
984 return pqApplicationCore::instance()->getActiveServer();
989 \brief Creates PARAVIS preference pane
991 void PVGUI_Module::createPreferences()
993 // Paraview settings tab
994 int aParaViewSettingsTab = addPreference( tr( "TIT_PVIEWSETTINGS" ) );
996 setPreferenceProperty(aParaViewSettingsTab, "stretch", false );
997 int aPanel = addPreference(QString(), aParaViewSettingsTab, LightApp_Preferences::UserDefined, PARAVIS_MODULE_NAME, "");
999 setPreferenceProperty(aPanel, "content", (qint64)(new PVGUI_ParaViewSettingsPane()));
1001 // Paravis settings tab
1002 int aParaVisSettingsTab = addPreference( tr( "TIT_PVISSETTINGS" ) );
1003 addPreference( tr( "PREF_STOP_TRACE" ), aParaVisSettingsTab, LightApp_Preferences::Bool, PARAVIS_MODULE_NAME, "stop_trace");
1005 addPreference( tr( "PREF_NO_EXT_PVSERVER" ), aParaVisSettingsTab, LightApp_Preferences::Bool, PARAVIS_MODULE_NAME, "no_ext_pv_server");
1007 int aSaveType = addPreference(tr( "PREF_SAVE_TYPE_LBL" ), aParaVisSettingsTab,
1008 LightApp_Preferences::Selector,
1009 PARAVIS_MODULE_NAME, "savestate_type");
1010 QList<QVariant> aIndices;
1011 QStringList aStrings;
1013 aStrings<<tr("PREF_SAVE_TYPE_0");
1014 aStrings<<tr("PREF_SAVE_TYPE_1");
1015 aStrings<<tr("PREF_SAVE_TYPE_2");
1016 setPreferenceProperty(aSaveType, "strings", aStrings);
1017 setPreferenceProperty(aSaveType, "indexes", aIndices);
1021 \brief Creates ParaViS context menu popup
1023 void PVGUI_Module::contextMenuPopup(const QString& theClient, QMenu* theMenu, QString& theTitle)
1025 LightApp_Module::contextMenuPopup(theClient, theMenu, theTitle);
1027 // Check if we are in Object Browser
1028 SUIT_DataBrowser* ob = getApp()->objectBrowser();
1029 bool isOBClient = (ob && theClient == ob->popupClientType());
1034 // Get list of selected objects
1035 LightApp_SelectionMgr* aSelectionMgr = getApp()->selectionMgr();
1036 SALOME_ListIO aListIO;
1037 aSelectionMgr->selectedObjects(aListIO);
1038 if (aListIO.Extent() == 1 && aListIO.First()->hasEntry()) {
1039 QString entry = QString(aListIO.First()->getEntry());
1042 SalomeApp_Study* activeStudy =
1043 dynamic_cast<SalomeApp_Study*>(getApp()->activeStudy());
1048 // Get SALOMEDS client study
1049 _PTR(Study) studyDS = activeStudy->studyDS();
1054 QString paravisDataType(PARAVIS_MODULE_NAME);
1055 if(activeStudy && activeStudy->isComponent(entry) &&
1056 activeStudy->componentDataType(entry) == paravisDataType) {
1057 // ParaViS module object
1058 theMenu->addSeparator();
1059 theMenu->addAction(action(SaveStatePopupId));
1062 // Try to get state object
1063 _PTR(SObject) stateSObj =
1064 studyDS->FindObjectID(entry.toLatin1().constData());
1070 _PTR(GenericAttribute) anAttr;
1071 if (!stateSObj->FindAttribute(anAttr, "AttributeLocalID")) {
1075 _PTR(AttributeLocalID) anID(anAttr);
1077 if (anID->Value() == PVSTATEID) {
1078 // Paraview state object
1079 theMenu->addSeparator();
1080 theMenu->addAction(action(AddStatePopupId));
1081 theMenu->addAction(action(CleanAndAddStatePopupId));
1082 theMenu->addSeparator();
1083 theMenu->addAction(action(ParaVisRenameId));
1084 theMenu->addAction(action(ParaVisDeleteId));
1091 \brief. Show ParaView python trace.
1093 void PVGUI_Module::onShowTrace()
1095 if (!myTraceWindow) {
1096 myTraceWindow = new pqPythonScriptEditor(getApp()->desktop());
1098 myTraceWindow->setText(getTraceString());
1099 myTraceWindow->show();
1100 myTraceWindow->raise();
1101 myTraceWindow->activateWindow();
1106 \brief. Re-initialize ParaView python trace.
1108 void PVGUI_Module::onRestartTrace()
1115 \brief Save state under the module root object.
1117 void PVGUI_Module::onSaveMultiState()
1119 // Create state study object
1121 // Get SALOMEDS client study
1122 _PTR(Study) studyDS = PARAVIS::GetCStudy(this);
1127 _PTR(SComponent) paravisComp =
1128 studyDS->FindComponent(PARAVIS_MODULE_NAME);
1133 // Unlock the study if it is locked
1134 bool isLocked = studyDS->GetProperties()->IsLocked();
1136 studyDS->GetProperties()->SetLocked(false);
1139 QString stateName = tr("SAVED_PARAVIEW_STATE_NAME") +
1140 QString::number(myStateCounter + 1);
1142 _PTR(StudyBuilder) studyBuilder = studyDS->NewBuilder();
1143 _PTR(SObject) newSObj = studyBuilder->NewObject(paravisComp);
1146 _PTR(GenericAttribute) anAttr;
1147 anAttr = studyBuilder->FindOrCreateAttribute(newSObj, "AttributeName");
1148 _PTR(AttributeName) nameAttr(anAttr);
1150 nameAttr->SetValue(stateName.toLatin1().constData());
1153 anAttr = studyBuilder->FindOrCreateAttribute(newSObj, "AttributeLocalID");
1154 _PTR(AttributeLocalID) localIdAttr(anAttr);
1156 localIdAttr->SetValue(PVSTATEID);
1159 QString stateEntry = QString::fromStdString(newSObj->GetID());
1161 // File name for state saving
1162 QString tmpDir = QString::fromStdString(SALOMEDS_Tool::GetTmpDir());
1163 QString fileName = QString("%1_paravisstate:%2").arg(tmpDir, stateEntry);
1165 anAttr = studyBuilder->FindOrCreateAttribute(newSObj, "AttributeString");
1166 _PTR(AttributeString) stringAttr(anAttr);
1168 stringAttr->SetValue(fileName.toLatin1().constData());
1170 // Lock the study back if necessary
1172 studyDS->GetProperties()->SetLocked(true);
1176 saveParaviewState(fileName.toLatin1().constData());
1177 myTemporaryFiles.append(fileName);
1179 // Increment the counter
1186 \brief Restore the selected state by merging with the current one.
1188 void PVGUI_Module::onAddState()
1190 loadSelectedState(false);
1194 \brief Clean the current state and restore the selected one.
1196 void PVGUI_Module::onCleanAddState()
1198 loadSelectedState(true);
1202 \brief Rename the selected object.
1204 void PVGUI_Module::onRename()
1206 LightApp_SelectionMgr* aSelectionMgr = getApp()->selectionMgr();
1207 SALOME_ListIO aListIO;
1208 aSelectionMgr->selectedObjects(aListIO);
1210 if (aListIO.Extent() == 1 && aListIO.First()->hasEntry()) {
1211 std::string entry = aListIO.First()->getEntry();
1213 // Get SALOMEDS client study
1214 _PTR(Study) studyDS = PARAVIS::GetCStudy(this);
1219 // Unlock the study if it is locked
1220 bool isLocked = studyDS->GetProperties()->IsLocked();
1222 studyDS->GetProperties()->SetLocked(false);
1225 // Rename the selected state object
1226 _PTR(SObject) stateSObj = studyDS->FindObjectID(entry);
1231 _PTR(GenericAttribute) anAttr;
1232 if (stateSObj->FindAttribute(anAttr, "AttributeName")) {
1233 _PTR(AttributeName) nameAttr (anAttr);
1235 LightApp_NameDlg::getName(getApp()->desktop(), nameAttr->Value().c_str());
1236 if (!newName.isEmpty()) {
1237 nameAttr->SetValue(newName.toLatin1().constData());
1238 aListIO.First()->setName(newName.toLatin1().constData());
1242 // Lock the study back if necessary
1244 studyDS->GetProperties()->SetLocked(true);
1247 // Update object browser
1254 \brief Delete the selected objects.
1256 void PVGUI_Module::onDelete()
1258 LightApp_SelectionMgr* aSelectionMgr = getApp()->selectionMgr();
1259 SALOME_ListIO aListIO;
1260 aSelectionMgr->selectedObjects(aListIO);
1262 if (aListIO.Extent() == 1 && aListIO.First()->hasEntry()) {
1263 std::string entry = aListIO.First()->getEntry();
1265 // Get SALOMEDS client study
1266 _PTR(Study) studyDS = PARAVIS::GetCStudy(this);
1271 // Unlock the study if it is locked
1272 bool isLocked = studyDS->GetProperties()->IsLocked();
1274 studyDS->GetProperties()->SetLocked(false);
1277 // Remove the selected state from the study
1278 _PTR(StudyBuilder) studyBuilder = studyDS->NewBuilder();
1279 _PTR(SObject) stateSObj = studyDS->FindObjectID(entry);
1280 studyBuilder->RemoveObject(stateSObj);
1282 // Lock the study back if necessary
1284 studyDS->GetProperties()->SetLocked(true);
1287 // Update object browser
1292 void PVGUI_Module::onPushTraceTimer()
1294 //MESSAGE("onPushTraceTimer(): Pushing trace to engine...");
1295 GetEngine()->PutPythonTraceStringToEngine(getTraceString().toStdString().c_str());
1299 \brief Discover help project files from the resources.
1300 \return name of the help file.
1302 QString PVGUI_Module::getHelpFileName() {
1303 QString aPVHome(getenv("PVHOME"));
1304 if (aPVHome.isNull()) {
1305 qWarning("Wariable PVHOME is not defined");
1308 QChar aSep = QDir::separator();
1309 //PARAVIEW_VERSION from the vtkPVConfig.h file
1310 QString aFileName = aPVHome + aSep + "share" + aSep + "doc" + aSep + "paraview-"+ PARAVIEW_VERSION + aSep + "paraview.qch";
1316 \brief Load selected paraview state
1318 If toClear == true, the current state will be cleared
1320 void PVGUI_Module::loadSelectedState(bool toClear)
1324 LightApp_SelectionMgr* aSelectionMgr = getApp()->selectionMgr();
1325 SALOME_ListIO aListIO;
1326 aSelectionMgr->selectedObjects(aListIO);
1328 if (aListIO.Extent() == 1 && aListIO.First()->hasEntry()) {
1329 std::string entry = aListIO.First()->getEntry();
1331 // Get SALOMEDS client study
1332 _PTR(Study) studyDS = PARAVIS::GetCStudy(this);
1338 _PTR(SObject) stateSObj = studyDS->FindObjectID(entry);
1339 _PTR(GenericAttribute) anAttr;
1340 if (!stateSObj->FindAttribute(anAttr, "AttributeLocalID")) {
1343 _PTR(AttributeLocalID) anID(anAttr);
1344 if (!anID->Value() == PVSTATEID) {
1348 // Get state file name
1349 if (stateSObj->FindAttribute(anAttr, "AttributeString")) {
1350 _PTR(AttributeString) aStringAttr(anAttr);
1351 QString stringValue(aStringAttr->Value().c_str());
1353 if (QFile::exists(stringValue)) {
1354 fileName = stringValue;
1359 if (!fileName.isEmpty()) {
1361 clearParaviewState();
1364 loadParaviewState(fileName.toLatin1().constData());
1367 SUIT_MessageBox::critical(getApp()->desktop(),
1369 tr("ERR_STATE_CANNOT_BE_RESTORED"));
1374 \fn CAM_Module* createModule();
1375 \brief Export module instance (factory function).
1376 \return new created instance of the module
1380 #define PVGUI_EXPORT __declspec(dllexport)
1382 #define PVGUI_EXPORT
1388 PVGUI_EXPORT CAM_Module* createModule() {
1389 return new PVGUI_Module();
1392 PVGUI_EXPORT char* getModuleVersion() {
1393 return (char*)PARAVIS_VERSION_STR;