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 #include CORBA_SERVER_HEADER(SALOME_ModuleCatalog)
33 #include CORBA_SERVER_HEADER(SALOMEDS)
35 #include "PVViewer_ViewManager.h"
36 #include "PVViewer_ViewWindow.h"
37 #include "PVViewer_ViewModel.h"
38 #include "PVGUI_Tools.h"
39 #include "PVGUI_ParaViewSettingsPane.h"
40 #include "PVViewer_GUIElements.h"
41 #include "PVViewer_EngineWrapper.h"
42 #include "PVGUI_DataModel.h"
45 #include <utilities.h>
46 #include <SUIT_DataBrowser.h>
47 #include <SUIT_Desktop.h>
48 #include <SUIT_MessageBox.h>
49 #include <SUIT_ResourceMgr.h>
50 #include <SUIT_Session.h>
51 #include <SUIT_OverrideCursor.h>
52 #include <SUIT_ExceptionHandler.h>
54 #include <SALOME_LifeCycleCORBA.hxx>
55 #include <SALOMEDS_SObject.hxx>
57 #include <LightApp_SelectionMgr.h>
58 #include <LightApp_NameDlg.h>
59 #include <LightApp_Application.h>
60 #include <SalomeApp_Application.h> // should ultimately be a LightApp only
61 #include <SalomeApp_Study.h>
62 #include <SALOME_ListIO.hxx>
63 #include <SALOMEDS_Tool.hxx>
64 #include <Utils_ORB_INIT.hxx>
65 #include <Utils_SINGLETON.hxx>
67 #include <QtxActionMenuMgr.h>
68 #include <QtxActionToolMgr.h>
70 #include <PARAVIS_version.h>
76 #include <QApplication>
82 #include <QInputDialog>
86 #include <QStringList>
89 #include <QTextStream>
91 #include <QDockWidget>
92 #include <QHelpEngine>
95 #include <vtkPVConfig.h> // for symbol PARAVIEW_VERSION
96 #include <vtkProcessModule.h>
97 #include <vtkPVSession.h>
98 #include <vtkPVProgressHandler.h>
99 #include <vtkOutputWindow.h>
100 #include <vtkEventQtSlotConnect.h>
102 #include <vtkSMProxy.h>
103 #include <vtkSmartPointer.h>
104 #include <vtkSMSession.h>
105 #include <vtkSMTrace.h>
106 #include <vtkSMSessionProxyManager.h>
107 #include <vtkSMParaViewPipelineController.h>
109 #include <pqApplicationCore.h>
110 #include <pqPVApplicationCore.h>
111 #include <pqObjectBuilder.h>
112 #include <pqOptions.h>
113 #include <pqSettings.h>
114 #include <pqServer.h>
115 #include <pqUndoStack.h>
116 #include <pqTabbedMultiViewWidget.h>
117 #include <pqActiveObjects.h>
118 #include <pqHelpReaction.h>
119 #include <pqPluginManager.h>
120 #include <pqPythonDialog.h>
121 #include <pqPythonManager.h>
122 #include <pqLoadDataReaction.h>
123 #include <pqPythonScriptEditor.h>
124 #include <pqDataRepresentation.h>
125 #include <pqDisplayColorWidget.h>
126 #include <pqColorToolbar.h>
127 #include <pqScalarBarVisibilityReaction.h>
128 #include <pqServerResource.h>
129 #include <pqServerConnectReaction.h>
130 #include <pqPluginManager.h>
131 #include <pqVCRToolbar.h>
132 #include <pqAnimationScene.h>
133 #include <pqServerManagerModel.h>
134 #include <pqAnimationTimeToolbar.h>
136 //----------------------------------------------------------------------------
137 PVGUI_Module* ParavisModule = 0;
138 PVSERVER_ORB::PVSERVER_Gen_var PVGUI_Module::MyEngine;
142 This is the doxygen documentation of the ParaVis module.
143 If you are looking for general information about the structure of the module, you should
144 take a look at the <a href="../index.html">Sphinx documentation</a> first.
146 The integration of ParaView into SALOME is split in two parts:
147 \li the PVViewer in the GUI module (folder *src/PVViewer*)
148 \li the ParaVis module itself (the pages you are currently browsing)
153 \brief Implementation
154 SALOME module wrapping ParaView GUI.
158 ClientFindOrCreateParavisComponent(_PTR(Study) theStudyDocument)
160 _PTR(SComponent) aSComponent = theStudyDocument->FindComponent("PVSERVER");
162 _PTR(StudyBuilder) aStudyBuilder = theStudyDocument->NewBuilder();
163 aStudyBuilder->NewCommand();
164 int aLocked = theStudyDocument->GetProperties()->IsLocked();
165 if (aLocked) theStudyDocument->GetProperties()->SetLocked(false);
166 aSComponent = aStudyBuilder->NewComponent("PVSERVER");
167 _PTR(GenericAttribute) anAttr =
168 aStudyBuilder->FindOrCreateAttribute(aSComponent, "AttributeName");
169 _PTR(AttributeName) aName (anAttr);
171 ORB_INIT& init = *SINGLETON_<ORB_INIT>::Instance();
172 CORBA::ORB_var anORB = init( qApp->argc(), qApp->argv() );
174 SALOME_NamingService *NamingService = new SALOME_NamingService( anORB );
175 CORBA::Object_var objVarN = NamingService->Resolve("/Kernel/ModulCatalog");
176 SALOME_ModuleCatalog::ModuleCatalog_var Catalogue =
177 SALOME_ModuleCatalog::ModuleCatalog::_narrow(objVarN);
178 SALOME_ModuleCatalog::Acomponent_var Comp = Catalogue->GetComponent( "PVSERVER" );
179 if (!Comp->_is_nil()) {
180 aName->SetValue(Comp->componentusername());
183 anAttr = aStudyBuilder->FindOrCreateAttribute(aSComponent, "AttributePixMap");
184 _PTR(AttributePixMap) aPixmap (anAttr);
185 aPixmap->SetPixMap( "pqAppIcon16.png" );
187 // Create Attribute parameters for future using
188 anAttr = aStudyBuilder->FindOrCreateAttribute(aSComponent, "AttributeParameter");
190 aStudyBuilder->DefineComponentInstance(aSComponent, PVGUI_Module::GetCPPEngine()->GetIOR());
191 if (aLocked) theStudyDocument->GetProperties()->SetLocked(true);
192 aStudyBuilder->CommitCommand();
198 \brief Clean up function
200 Used to stop ParaView progress events when
201 exception is caught by global exception handler.
203 void paravisCleanUp()
205 if ( pqApplicationCore::instance() ) {
206 pqServer* s = pqApplicationCore::instance()->getActiveServer();
207 if ( s ) s->session()->GetProgressHandler()->CleanupPendingProgress();
212 \brief Constructor. Sets the default name for the module.
214 PVGUI_Module::PVGUI_Module()
215 : SalomeApp_Module( PARAVIS_MODULE_NAME ),
216 mySelectionControlsTb( -1 ),
217 mySourcesMenuId( -1 ),
218 myFiltersMenuId( -1 ),
220 myToolbarsMenuId(-1),
230 Q_INIT_RESOURCE( PVGUI );
232 ParavisModule = this;
234 // Clear old copies of embedded macros files
235 QString aDestPath = QString( "%1/.config/%2/Macros" ).arg( QDir::homePath() ).arg( QApplication::applicationName() );
239 QDir aDestDir(aDestPath);
240 QStringList aDestFiles = aDestDir.entryList(aFilter, QDir::Files);
241 foreach (QString aMacrosPath, getEmbeddedMacrosList()) {
242 QString aMacrosName = QFileInfo(aMacrosPath).fileName();
243 if (aDestFiles.contains(aMacrosName)) {
244 aDestDir.remove(aMacrosName);
252 PVGUI_Module::~PVGUI_Module()
254 if (myPushTraceTimer)
255 delete myPushTraceTimer;
261 * \brief Retrieve the PVSERVER CORBA engine.
262 * This uses the Python wrapper provided
263 * by the PVViewer code in GUI (class PVViewer_EngineWrapper).
266 PVViewer_EngineWrapper * PVGUI_Module::GetEngine()
268 return PVViewer_EngineWrapper::GetInstance();
272 * \brief Retrieve the PVSERVER CORBA engine.
273 * Uses directly the standard Salome C++ mechanisms
277 PVSERVER_ORB::PVSERVER_Gen_var PVGUI_Module::GetCPPEngine()
279 // initialize PARAVIS module engine (load, if necessary)
280 if ( CORBA::is_nil( MyEngine ) ) {
281 Engines::EngineComponent_var comp =
282 SalomeApp_Application::lcc()->FindOrLoad_Component( "FactoryServer", "PVSERVER" );
283 MyEngine = PVSERVER_ORB::PVSERVER_Gen::_narrow( comp );
289 \brief Create data model.
290 \return module specific data model
292 CAM_DataModel* PVGUI_Module::createDataModel()
294 return new PVGUI_DataModel( this );
298 * \brief Get the ParaView application singleton.
300 pqPVApplicationCore * PVGUI_Module::GetPVApplication()
302 return PVViewer_ViewManager::GetPVApplication();
306 \brief Initialize module. Creates menus, prepares context menu, etc.
307 \param app SALOME GUI application instance
309 void PVGUI_Module::initialize( CAM_Application* app )
311 LightApp_Module::initialize( app );
316 // Uncomment to debug ParaView initialization
317 // "aa" used instead of "i" as GDB doesn't like "i" variables :)
325 LightApp_Application* anApp = getApp();
326 SUIT_Desktop* aDesktop = anApp->desktop();
328 // Remember current state of desktop toolbars
329 QList<QToolBar*> foreignToolbars = aDesktop->findChildren<QToolBar*>();
331 // Initialize ParaView client and associated behaviors
332 // and connect to externally launched pvserver
333 PVViewer_ViewManager::ParaviewInitApp(aDesktop, anApp->logWindow());
334 myGuiElements = PVViewer_GUIElements::GetInstance(aDesktop);
336 // [ABN]: careful with the order of the GUI element creation, the loading of the configuration
337 // and the connection to the server. This order is very sensitive if one wants to make
338 // sure all menus, etc ... are correctly populated.
339 // Reference points are: ParaViewMainWindow.cxx and branded_paraview_initializer.cxx.in
346 PVViewer_ViewManager::ParaviewInitBehaviors(true, aDesktop);
348 QList<QDockWidget*> activeDocks = aDesktop->findChildren<QDockWidget*>();
349 QList<QMenu*> activeMenus = aDesktop->findChildren<QMenu*>();
351 // Setup quick-launch shortcuts.
352 QShortcut *ctrlSpace = new QShortcut(Qt::CTRL + Qt::Key_Space, aDesktop);
353 QObject::connect(ctrlSpace, SIGNAL(activated()),
354 pqApplicationCore::instance(), SLOT(quickLaunch()));
356 // Find Plugin Dock Widgets
357 QList<QDockWidget*> currentDocks = aDesktop->findChildren<QDockWidget*>();
358 QList<QDockWidget*>::iterator i;
359 for (i = currentDocks.begin(); i != currentDocks.end(); ++i) {
360 if(!activeDocks.contains(*i)) {
361 myDockWidgets[*i] = false; // hidden by default
367 // [ABN] TODO: fix this - triggers a SEGFAULT at deactivation() time.
368 // QList<QMenu*> currentMenus = aDesktop->findChildren<QMenu*>();
369 // QList<QMenu*>::iterator im;
370 // for (im = currentMenus.begin(); im != currentMenus.end(); ++im) {
371 // if(!activeMenus.contains(*im)) {
372 // QString s = (*im)->title();
373 // std::cout << " MENU "<< s.toStdString() << std::endl;
374 // myMenus.append(*im);
378 // Connect after toolbar creation, etc ... as some activations of the toolbars is triggered
379 // by the ServerConnection event:
380 PVViewer_ViewManager::ParaviewLoadConfigurations(true);
381 PVViewer_ViewManager::ConnectToExternalPVServer(aDesktop);
384 // Find created toolbars
385 QCoreApplication::processEvents();
387 // process PVViewer toolbars (might be added by PVViewer created BEFORE activating ParaVis)
388 QList<QToolBar*> pvToolbars = myGuiElements->getToolbars();
389 foreach(QToolBar* aBar, pvToolbars) {
390 if (!myToolbars.contains(aBar)) {
391 myToolbars[aBar] = true;
392 myToolbarBreaks[aBar] = false;
393 aBar->setVisible(false);
394 aBar->toggleViewAction()->setVisible(false);
398 // process other toolbars (possibly added by Paraview)
399 QList<QToolBar*> allToolbars = aDesktop->findChildren<QToolBar*>();
400 foreach(QToolBar* aBar, allToolbars) {
401 if (!foreignToolbars.contains(aBar) && !myToolbars.contains(aBar)) {
402 myToolbars[aBar] = true;
403 myToolbarBreaks[aBar] = false;
404 aBar->setVisible(false);
405 aBar->toggleViewAction()->setVisible(false);
411 SUIT_ResourceMgr* aResourceMgr = SUIT_Session::session()->resourceMgr();
412 bool isStop = aResourceMgr->booleanValue( PARAVIS_MODULE_NAME, "stop_trace", false );
415 // Start a timer to schedule asap:
417 myInitTimer = new QTimer(aDesktop);
418 QObject::connect(myInitTimer, SIGNAL(timeout()), this, SLOT(onInitTimer()) );
419 myInitTimer->setSingleShot(true);
420 myInitTimer->start(0);
422 // Another timer to regularly push the trace onto the engine:
423 myPushTraceTimer = new QTimer(aDesktop);
424 QObject::connect(myPushTraceTimer, SIGNAL(timeout()), this, SLOT(onPushTraceTimer()) );
425 myPushTraceTimer->setSingleShot(false);
426 myPushTraceTimer->start(500);
429 this->VTKConnect = vtkEventQtSlotConnect::New();
431 vtkProcessModule* pm = vtkProcessModule::GetProcessModule();
433 vtkPVSession* pvs = dynamic_cast<vtkPVSession*>(pm->GetSession());
435 vtkPVProgressHandler* ph = pvs->GetProgressHandler();
437 this->VTKConnect->Connect(ph, vtkCommand::StartEvent,
438 this, SLOT(onStartProgress()));
439 this->VTKConnect->Connect(ph, vtkCommand::EndEvent,
440 this, SLOT(onEndProgress()));
448 * Little trick to force the proper update of the timesteps/time range when the module is initialized.
449 * This is otherwise not properly working when PARAVIS is activated after a PVViewer has already been
452 void PVGUI_Module::fixAnimationScene()
454 pqServer* server = pqActiveObjects::instance().activeServer();
455 pqApplicationCore * app = pqApplicationCore::instance();
456 pqPipelineSource * src = app->getObjectBuilder()->createSource(QString("sources"), QString("TimeSource"),server);
457 app->getObjectBuilder()->destroy(src);
461 * \brief Slot called when the progress bar starts.
463 void PVGUI_Module::onStartProgress()
465 QApplication::setOverrideCursor(Qt::WaitCursor);
469 * \brief Slot called when the progress bar is done.
471 void PVGUI_Module::onEndProgress()
473 QApplication::restoreOverrideCursor();
476 void PVGUI_Module::onDataRepresentationUpdated() {
477 SalomeApp_Study* activeStudy = dynamic_cast<SalomeApp_Study*>(application()->activeStudy());
478 if(!activeStudy) return;
480 activeStudy->Modified();
484 \brief Initialisation timer event - Starts up the Python trace
486 void PVGUI_Module::onInitTimer()
492 \brief Get list of embedded macros files
494 QStringList PVGUI_Module::getEmbeddedMacrosList()
496 QString aRootDir = getenv("PARAVIS_ROOT_DIR");
498 QString aSourcePath = aRootDir + "/bin/salome/Macro";
503 QDir aSourceDir(aSourcePath);
504 QStringList aSourceFiles = aSourceDir.entryList(aFilter, QDir::Files);
505 QStringList aFullPathSourceFiles;
506 foreach (QString aMacrosName, aSourceFiles) {
507 aFullPathSourceFiles << aSourceDir.absoluteFilePath(aMacrosName);
509 return aFullPathSourceFiles;
513 \brief Update the list of embedded macros
515 void PVGUI_Module::updateMacros()
517 pqPythonManager* aPythonManager = pqPVApplicationCore::instance()->pythonManager();
518 if(!aPythonManager) {
522 foreach (QString aStr, getEmbeddedMacrosList()) {
523 aPythonManager->addMacro(aStr);
529 \brief Get list of compliant dockable GUI elements
530 \param m map to be filled in ("type":"default_position")
532 void PVGUI_Module::windows( QMap<int, int>& m ) const
534 m.insert( LightApp_Application::WT_ObjectBrowser, Qt::LeftDockWidgetArea );
535 m.insert( LightApp_Application::WT_PyConsole, Qt::BottomDockWidgetArea );
536 // ParaView diagnostic output redirected here
537 m.insert( LightApp_Application::WT_LogWindow, Qt::BottomDockWidgetArea );
541 \brief Shows (toShow = true) or hides ParaView view window
543 void PVGUI_Module::showView( bool toShow )
545 LightApp_Application* anApp = getApp();
546 PVViewer_ViewManager* viewMgr =
547 dynamic_cast<PVViewer_ViewManager*>( anApp->getViewManager( PVViewer_Viewer::Type(), false ) );
549 viewMgr = new PVViewer_ViewManager( anApp->activeStudy(), anApp->desktop(), anApp->logWindow() );
550 anApp->addViewManager( viewMgr );
551 connect( viewMgr, SIGNAL( lastViewClosed( SUIT_ViewManager* ) ),
552 anApp, SLOT( onCloseView( SUIT_ViewManager* ) ) );
555 PVViewer_ViewWindow* pvWnd = dynamic_cast<PVViewer_ViewWindow*>( viewMgr->getActiveView() );
557 pvWnd = dynamic_cast<PVViewer_ViewWindow*>( viewMgr->createViewWindow() );
558 // this also connects to the pvserver and instantiates relevant PV behaviors
561 pvWnd->setShown( toShow );
562 if ( toShow ) pvWnd->setFocus();
566 \brief Slot to show help for proxy.
568 void PVGUI_Module::showHelpForProxy( const QString& groupname, const QString& proxyname )
570 pqHelpReaction::showProxyHelp(groupname, proxyname);
575 \brief Slot to show the waiting state.
577 void PVGUI_Module::onPreAccept()
579 getApp()->desktop()->statusBar()->showMessage(tr("STB_PREACCEPT"));
580 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
584 \brief Slot to show the ready state.
586 void PVGUI_Module::onPostAccept()
588 getApp()->desktop()->statusBar()->showMessage(tr("STB_POSTACCEPT"), 2000);
589 QTimer::singleShot(0, this, SLOT(endWaitCursor()));
593 \brief Slot to switch off wait cursor.
595 void PVGUI_Module::endWaitCursor()
597 QApplication::restoreOverrideCursor();
601 \brief Handler method for the output of messages.
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 * \brief Starts Python trace.
841 * Start trace invoking the newly introduced C++ API (PV 4.2)
842 * (inspired from pqTraceReaction::start())
844 void PVGUI_Module::startTrace()
846 vtkSMSessionProxyManager* pxm = pqActiveObjects::instance().activeServer()->proxyManager();
848 vtkSmartPointer<vtkSMProxy> proxy;
849 proxy.TakeReference(pxm->NewProxy("pythontracing", "PythonTraceOptions"));
852 vtkNew<vtkSMParaViewPipelineController> controller;
853 controller->InitializeProxy(proxy);
855 vtkSMTrace* trace = vtkSMTrace::StartTrace();
858 // Set manually the properties entered via the dialog box poping-up when requiring
859 // a trace start in PV4.2 (trace options)
860 trace->SetPropertiesToTraceOnCreate(vtkSMTrace::RECORD_USER_MODIFIED_PROPERTIES);
861 trace->SetFullyTraceSupplementalProxies(false);
866 * \brief Stops Python trace.
868 void PVGUI_Module::stopTrace()
870 vtkSMTrace::StopTrace();
874 * \brief Execute a Python script.
876 void PVGUI_Module::executeScript(const char *script)
879 pqPythonManager* manager = qobject_cast<pqPythonManager*>(
880 pqApplicationCore::instance()->manager("PYTHON_MANAGER"));
882 pqPythonDialog* pyDiag = manager->pythonShellDialog();
884 pyDiag->runString(script);
891 // * Debug function printing out the given interpreter's execution context
893 //void printInterpContext(PyInterp_Interp * interp )
895 // // Extract __smtraceString from interpreter's context
896 // const PyObject* ctxt = interp->getExecutionContext();
898 // PyObject* lst = PyDict_Keys((PyObject *)ctxt);
899 // Py_ssize_t siz = PyList_GET_SIZE(lst);
900 // for (Py_ssize_t i = 0; i < siz; i++)
902 // PyObject * elem = PyList_GetItem(lst, i);
903 // if (PyString_Check(elem))
905 // std::cout << "At pos:" << i << ", " << PyString_AsString(elem) << std::endl;
908 // std::cout << "At pos:" << i << ", not a string!" << std::endl;
914 \brief Returns trace string
916 static const QString MYReplaceStr("paraview.simple");
917 QString PVGUI_Module::getTraceString()
919 vtkSMTrace *tracer = vtkSMTrace::GetActiveTracer();
920 if (!tracer) // trace is not started
923 QString traceString(tracer->GetCurrentTrace());
924 std::stringstream nl; nl << std::endl; // surely there is some Qt trick to do that in a portable way??
925 QString end_line(nl.str().c_str());
926 // 'import pvsimple' is necessary to fix the first call to DisableFirstRenderCamera in the paraview trace
927 // 'ShowParaviewView()' ensure there is an opened viewing window (otherwise SEGFAULT!)
928 traceString = "import pvsimple" + end_line +
929 "pvsimple.ShowParaviewView()" + end_line + traceString;
931 // Replace import "paraview.simple" by "pvsimple"
932 if ((!traceString.isNull()) && traceString.length() != 0) {
933 int aPos = traceString.indexOf(MYReplaceStr);
935 traceString = traceString.replace(aPos, MYReplaceStr.length(), "pvsimple");
936 aPos = traceString.indexOf(MYReplaceStr, aPos);
944 \brief Saves trace string to disk file
946 void PVGUI_Module::saveTrace(const char* theName)
949 if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
950 MESSAGE( "Could not open file:" << theName );
953 QTextStream out(&file);
954 out << getTraceString();
959 \brief Saves ParaView state to a disk file
961 void PVGUI_Module::saveParaviewState(const char* theFileName)
963 pqApplicationCore::instance()->saveState(theFileName);
967 \brief Delete all objects for Paraview Pipeline Browser
969 void PVGUI_Module::clearParaviewState()
971 QAction* deleteAllAction = action(DeleteAllId);
972 if (deleteAllAction) {
973 deleteAllAction->activate(QAction::Trigger);
978 \brief Restores ParaView state from a disk file
980 If toClear == true, the current ojects will be deleted
982 void PVGUI_Module::loadParaviewState(const char* theFileName)
984 pqApplicationCore::instance()->loadState(theFileName, getActiveServer());
988 \brief Returns current active ParaView server
990 pqServer* PVGUI_Module::getActiveServer()
992 return pqApplicationCore::instance()->getActiveServer();
997 \brief Creates PARAVIS preferences panel.
999 void PVGUI_Module::createPreferences()
1001 // Paraview settings tab
1002 int aParaViewSettingsTab = addPreference( tr( "TIT_PVIEWSETTINGS" ) );
1004 setPreferenceProperty(aParaViewSettingsTab, "stretch", false );
1005 int aPanel = addPreference(QString(), aParaViewSettingsTab, LightApp_Preferences::UserDefined, PARAVIS_MODULE_NAME, "");
1007 setPreferenceProperty(aPanel, "content", (qint64)(new PVGUI_ParaViewSettingsPane(0, getApp())));
1009 // Paravis settings tab
1010 int aParaVisSettingsTab = addPreference( tr( "TIT_PVISSETTINGS" ) );
1011 addPreference( tr( "PREF_STOP_TRACE" ), aParaVisSettingsTab, LightApp_Preferences::Bool, PARAVIS_MODULE_NAME, "stop_trace");
1013 addPreference( tr( "PREF_NO_EXT_PVSERVER" ), aParaVisSettingsTab, LightApp_Preferences::Bool, PARAVIS_MODULE_NAME, "no_ext_pv_server");
1015 int aSaveType = addPreference(tr( "PREF_SAVE_TYPE_LBL" ), aParaVisSettingsTab,
1016 LightApp_Preferences::Selector,
1017 PARAVIS_MODULE_NAME, "savestate_type");
1018 QList<QVariant> aIndices;
1019 QStringList aStrings;
1021 aStrings<<tr("PREF_SAVE_TYPE_0");
1022 aStrings<<tr("PREF_SAVE_TYPE_1");
1023 aStrings<<tr("PREF_SAVE_TYPE_2");
1024 setPreferenceProperty(aSaveType, "strings", aStrings);
1025 setPreferenceProperty(aSaveType, "indexes", aIndices);
1029 \brief Creates ParaViS context menu popup
1031 void PVGUI_Module::contextMenuPopup(const QString& theClient, QMenu* theMenu, QString& theTitle)
1033 LightApp_Module::contextMenuPopup(theClient, theMenu, theTitle);
1035 // Check if we are in Object Browser
1036 SUIT_DataBrowser* ob = getApp()->objectBrowser();
1037 bool isOBClient = (ob && theClient == ob->popupClientType());
1042 // Get list of selected objects
1043 LightApp_SelectionMgr* aSelectionMgr = getApp()->selectionMgr();
1044 SALOME_ListIO aListIO;
1045 aSelectionMgr->selectedObjects(aListIO);
1046 if (aListIO.Extent() == 1 && aListIO.First()->hasEntry()) {
1047 QString entry = QString(aListIO.First()->getEntry());
1050 SalomeApp_Study* activeStudy =
1051 dynamic_cast<SalomeApp_Study*>(getApp()->activeStudy());
1056 // Get SALOMEDS client study
1057 _PTR(Study) studyDS = activeStudy->studyDS();
1062 QString paravisDataType(PARAVIS_MODULE_NAME);
1063 if(activeStudy && activeStudy->isComponent(entry) &&
1064 activeStudy->componentDataType(entry) == paravisDataType) {
1065 // ParaViS module object
1066 theMenu->addSeparator();
1067 theMenu->addAction(action(SaveStatePopupId));
1070 // Try to get state object
1071 _PTR(SObject) stateSObj =
1072 studyDS->FindObjectID(entry.toLatin1().constData());
1078 _PTR(GenericAttribute) anAttr;
1079 if (!stateSObj->FindAttribute(anAttr, "AttributeLocalID")) {
1083 _PTR(AttributeLocalID) anID(anAttr);
1085 if (anID->Value() == PVSTATEID) {
1086 // Paraview state object
1087 theMenu->addSeparator();
1088 theMenu->addAction(action(AddStatePopupId));
1089 theMenu->addAction(action(CleanAndAddStatePopupId));
1090 theMenu->addSeparator();
1091 theMenu->addAction(action(ParaVisRenameId));
1092 theMenu->addAction(action(ParaVisDeleteId));
1099 \brief. Show ParaView python trace.
1101 void PVGUI_Module::onShowTrace()
1103 if (!myTraceWindow) {
1104 myTraceWindow = new pqPythonScriptEditor(getApp()->desktop());
1106 myTraceWindow->setText(getTraceString());
1107 myTraceWindow->show();
1108 myTraceWindow->raise();
1109 myTraceWindow->activateWindow();
1114 \brief. Re-initialize ParaView python trace.
1116 void PVGUI_Module::onRestartTrace()
1123 \brief Save state under the module root object.
1125 void PVGUI_Module::onSaveMultiState()
1127 // Create state study object
1129 // Get SALOMEDS client study
1130 _PTR(Study) studyDS = PARAVIS::GetCStudy(this);
1135 _PTR(SComponent) paravisComp =
1136 studyDS->FindComponent(PARAVIS_MODULE_NAME);
1141 // Unlock the study if it is locked
1142 bool isLocked = studyDS->GetProperties()->IsLocked();
1144 studyDS->GetProperties()->SetLocked(false);
1147 QString stateName = tr("SAVED_PARAVIEW_STATE_NAME") +
1148 QString::number(myStateCounter + 1);
1150 _PTR(StudyBuilder) studyBuilder = studyDS->NewBuilder();
1151 _PTR(SObject) newSObj = studyBuilder->NewObject(paravisComp);
1154 _PTR(GenericAttribute) anAttr;
1155 anAttr = studyBuilder->FindOrCreateAttribute(newSObj, "AttributeName");
1156 _PTR(AttributeName) nameAttr(anAttr);
1158 nameAttr->SetValue(stateName.toLatin1().constData());
1161 anAttr = studyBuilder->FindOrCreateAttribute(newSObj, "AttributeLocalID");
1162 _PTR(AttributeLocalID) localIdAttr(anAttr);
1164 localIdAttr->SetValue(PVSTATEID);
1167 QString stateEntry = QString::fromStdString(newSObj->GetID());
1169 // File name for state saving
1170 QString tmpDir = QString::fromStdString(SALOMEDS_Tool::GetTmpDir());
1171 QString fileName = QString("%1_paravisstate:%2").arg(tmpDir, stateEntry);
1173 anAttr = studyBuilder->FindOrCreateAttribute(newSObj, "AttributeString");
1174 _PTR(AttributeString) stringAttr(anAttr);
1176 stringAttr->SetValue(fileName.toLatin1().constData());
1178 // Lock the study back if necessary
1180 studyDS->GetProperties()->SetLocked(true);
1184 saveParaviewState(fileName.toLatin1().constData());
1185 myTemporaryFiles.append(fileName);
1187 // Increment the counter
1194 \brief Restore the selected state by merging with the current one.
1196 void PVGUI_Module::onAddState()
1198 loadSelectedState(false);
1202 \brief Clean the current state and restore the selected one.
1204 void PVGUI_Module::onCleanAddState()
1206 loadSelectedState(true);
1210 \brief Rename the selected object.
1212 void PVGUI_Module::onRename()
1214 LightApp_SelectionMgr* aSelectionMgr = getApp()->selectionMgr();
1215 SALOME_ListIO aListIO;
1216 aSelectionMgr->selectedObjects(aListIO);
1218 if (aListIO.Extent() == 1 && aListIO.First()->hasEntry()) {
1219 std::string entry = aListIO.First()->getEntry();
1221 // Get SALOMEDS client study
1222 _PTR(Study) studyDS = PARAVIS::GetCStudy(this);
1227 // Unlock the study if it is locked
1228 bool isLocked = studyDS->GetProperties()->IsLocked();
1230 studyDS->GetProperties()->SetLocked(false);
1233 // Rename the selected state object
1234 _PTR(SObject) stateSObj = studyDS->FindObjectID(entry);
1239 _PTR(GenericAttribute) anAttr;
1240 if (stateSObj->FindAttribute(anAttr, "AttributeName")) {
1241 _PTR(AttributeName) nameAttr (anAttr);
1243 LightApp_NameDlg::getName(getApp()->desktop(), nameAttr->Value().c_str());
1244 if (!newName.isEmpty()) {
1245 nameAttr->SetValue(newName.toLatin1().constData());
1246 aListIO.First()->setName(newName.toLatin1().constData());
1250 // Lock the study back if necessary
1252 studyDS->GetProperties()->SetLocked(true);
1255 // Update object browser
1262 \brief Delete the selected objects.
1264 void PVGUI_Module::onDelete()
1266 LightApp_SelectionMgr* aSelectionMgr = getApp()->selectionMgr();
1267 SALOME_ListIO aListIO;
1268 aSelectionMgr->selectedObjects(aListIO);
1270 if (aListIO.Extent() == 1 && aListIO.First()->hasEntry()) {
1271 std::string entry = aListIO.First()->getEntry();
1273 // Get SALOMEDS client study
1274 _PTR(Study) studyDS = PARAVIS::GetCStudy(this);
1279 // Unlock the study if it is locked
1280 bool isLocked = studyDS->GetProperties()->IsLocked();
1282 studyDS->GetProperties()->SetLocked(false);
1285 // Remove the selected state from the study
1286 _PTR(StudyBuilder) studyBuilder = studyDS->NewBuilder();
1287 _PTR(SObject) stateSObj = studyDS->FindObjectID(entry);
1288 studyBuilder->RemoveObject(stateSObj);
1290 // Lock the study back if necessary
1292 studyDS->GetProperties()->SetLocked(true);
1295 // Update object browser
1301 * \brief Slot called everytime the Python trace is pushed onto the CORBA engine.
1303 void PVGUI_Module::onPushTraceTimer()
1305 //MESSAGE("onPushTraceTimer(): Pushing trace to engine...");
1306 GetEngine()->PutPythonTraceStringToEngine(getTraceString().toStdString().c_str());
1310 \brief Discover help project files from the resources.
1311 \return name of the help file.
1313 QString PVGUI_Module::getHelpFileName() {
1314 QString aPVHome(getenv("PVHOME"));
1315 if (aPVHome.isNull()) {
1316 qWarning("Wariable PVHOME is not defined");
1319 QChar aSep = QDir::separator();
1320 //PARAVIEW_VERSION from the vtkPVConfig.h file
1321 QString aFileName = aPVHome + aSep + "share" + aSep + "doc" + aSep + "paraview-"+ PARAVIEW_VERSION + aSep + "paraview.qch";
1327 \brief Load selected paraview state
1329 If toClear == true, the current state will be cleared
1331 void PVGUI_Module::loadSelectedState(bool toClear)
1335 LightApp_SelectionMgr* aSelectionMgr = getApp()->selectionMgr();
1336 SALOME_ListIO aListIO;
1337 aSelectionMgr->selectedObjects(aListIO);
1339 if (aListIO.Extent() == 1 && aListIO.First()->hasEntry()) {
1340 std::string entry = aListIO.First()->getEntry();
1342 // Get SALOMEDS client study
1343 _PTR(Study) studyDS = PARAVIS::GetCStudy(this);
1349 _PTR(SObject) stateSObj = studyDS->FindObjectID(entry);
1350 _PTR(GenericAttribute) anAttr;
1351 if (!stateSObj->FindAttribute(anAttr, "AttributeLocalID")) {
1354 _PTR(AttributeLocalID) anID(anAttr);
1355 if (!anID->Value() == PVSTATEID) {
1359 // Get state file name
1360 if (stateSObj->FindAttribute(anAttr, "AttributeString")) {
1361 _PTR(AttributeString) aStringAttr(anAttr);
1362 QString stringValue(aStringAttr->Value().c_str());
1364 if (QFile::exists(stringValue)) {
1365 fileName = stringValue;
1370 if (!fileName.isEmpty()) {
1372 clearParaviewState();
1375 loadParaviewState(fileName.toLatin1().constData());
1378 SUIT_MessageBox::critical(getApp()->desktop(),
1380 tr("ERR_STATE_CANNOT_BE_RESTORED"));
1385 \fn CAM_Module* createModule();
1386 \brief Export module instance (factory function).
1387 \return new created instance of the module
1391 #define PVGUI_EXPORT __declspec(dllexport)
1393 #define PVGUI_EXPORT
1399 PVGUI_EXPORT CAM_Module* createModule() {
1400 return new PVGUI_Module();
1403 PVGUI_EXPORT char* getModuleVersion() {
1404 return (char*)PARAVIS_VERSION_STR;