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 PARAVIS_ORB::PARAVIS_Gen_var PVGUI_Module::MyEngine;
149 <h2>Building and installing PARAVIS</h2>
150 As any other SALOME module, PARAVIS requires PARAVIS_ROOT_DIR environment variable to be set to PARAVIS
151 installation directory.
152 Other variables needed for correct detection of ParaView location:
153 \li PVHOME - points at the ParaView installation directory tree
154 \li PVVERSION - number of ParaView version
156 It also requires common SALOME environment including GUI_ROOT_DIR and other prerequsites.
159 PARAVIS module can be launched using the following commands:
160 \li Full SALOME configuration
162 runSalome --modules="PARAVIS"
165 <h2>ParaView GUI integration</h2>
166 <h3>ParaView GUI integration overview</h3>
168 The main idea is to reuse ParaView GUI internal logic as much as possible, providing a layer
169 between it and SALOME GUI that hides the following SALOME GUI implementation details from ParaView:
171 \li SALOME GUI executable and Qt event loop
172 \li SALOME GUI desktop
173 \li Dock windows areas
174 \li SALOME menu and toolbar managers
176 Major part of the integration is implemented in PVGUI_Module class.
178 <h3>ParaView client initalization</h3>
180 ParaView client initalization is performed when an instance of PVGUI_Module class has been created
181 and \link PVGUI_Module::initialize() PVGUI_Module::initialize()\endlink method is called by SALOME GUI.
182 The actual client start-up is done in \link PVGUI_Module::pvInit() PVGUI_Module::pvInit()\endlink method.
185 <h3>Multi-view manager</h3>
187 SALOME GUI requires that each kind of view be implemnted with help of (at least) three classes. For ParaView multi-view manager
190 \li PVGUI_ViewManager - view manager class
191 \li PVGUI_Viewer - view model class
192 \li PVGUI_ViewWindow - view window class that acts as a parent for %pqViewManager
194 Single instances of PVGUI_ViewManager and PVGUI_ViewWindow classes are created by \link PVGUI_Module::showView()
195 PVGUI_Module::showView()\endlink method upon the first PARAVIS module activation. The same method hides the multi-view manager
196 when the module is deactivated (the user switches to another module or a study is closed).
197 A special trick is used to make PVGUI_ViewWindow the parent of %pqViewManager widget. It is created initally by %pqMainWindowCore
198 with the desktop as a parent, so when it is shown PVGUI_ViewWindow instance is passed to its setParent() method. In
199 \link PVGUI_ViewWindow::~PVGUI_ViewWindow() PVGUI_ViewWindow::~PVGUI_ViewWindow()\endlink the parent is nullified to avoid deletion
200 of %pqViewManager widget that would break %pqMainWindowCore class.
202 <h3>ParaView plugins</h3>
203 ParaView server and client plugins are managed by %pqMainWindowCore slots that has full access to PARAVIS menus and toolbars.
204 As a result they appears automatically in PARAVIS menus and toolbars if loaded successfully.
209 \brief Implementation
210 SALOME module wrapping ParaView GUI.
214 //ClientFindOrCreateParavisComponent(_PTR(Study) theStudyDocument)
216 // _PTR(SComponent) aSComponent = theStudyDocument->FindComponent("PARAVIS");
217 // if (!aSComponent) {
218 // _PTR(StudyBuilder) aStudyBuilder = theStudyDocument->NewBuilder();
219 // aStudyBuilder->NewCommand();
220 // int aLocked = theStudyDocument->GetProperties()->IsLocked();
221 // if (aLocked) theStudyDocument->GetProperties()->SetLocked(false);
222 // aSComponent = aStudyBuilder->NewComponent("PARAVIS");
223 // _PTR(GenericAttribute) anAttr =
224 // aStudyBuilder->FindOrCreateAttribute(aSComponent, "AttributeName");
225 // _PTR(AttributeName) aName (anAttr);
227 // ORB_INIT& init = *SINGLETON_<ORB_INIT>::Instance();
228 // CORBA::ORB_var anORB = init( qApp->argc(), qApp->argv() );
230 // SALOME_NamingService *NamingService = new SALOME_NamingService( anORB );
231 // CORBA::Object_var objVarN = NamingService->Resolve("/Kernel/ModulCatalog");
232 // SALOME_ModuleCatalog::ModuleCatalog_var Catalogue =
233 // SALOME_ModuleCatalog::ModuleCatalog::_narrow(objVarN);
234 // SALOME_ModuleCatalog::Acomponent_var Comp = Catalogue->GetComponent( "PARAVIS" );
235 // if (!Comp->_is_nil()) {
236 // aName->SetValue(Comp->componentusername());
239 // anAttr = aStudyBuilder->FindOrCreateAttribute(aSComponent, "AttributePixMap");
240 // _PTR(AttributePixMap) aPixmap (anAttr);
241 // aPixmap->SetPixMap( "pqAppIcon16.png" );
243 // // Create Attribute parameters for future using
244 // anAttr = aStudyBuilder->FindOrCreateAttribute(aSComponent, "AttributeParameter");
246 // aStudyBuilder->DefineComponentInstance(aSComponent, PVGUI_Module::GetCPPEngine()->GetIOR());
247 // if (aLocked) theStudyDocument->GetProperties()->SetLocked(true);
248 // aStudyBuilder->CommitCommand();
250 // return aSComponent;
254 Clean up function; used to stop ParaView progress events when
255 exception is caught by global exception handler.
257 void paravisCleanUp()
259 if ( pqApplicationCore::instance() ) {
260 pqServer* s = pqApplicationCore::instance()->getActiveServer();
261 if ( s ) s->session()->GetProgressHandler()->CleanupPendingProgress();
266 \brief Constructor. Sets the default name for the module.
268 PVGUI_Module::PVGUI_Module()
269 : SalomeApp_Module( PARAVIS_MODULE_NAME ),
270 mySelectionControlsTb( -1 ),
271 mySourcesMenuId( -1 ),
272 myFiltersMenuId( -1 ),
274 myToolbarsMenuId(-1),
284 Q_INIT_RESOURCE( PVGUI );
286 ParavisModule = this;
288 // Clear old copies of embedded macros files
289 QString aDestPath = QString( "%1/.config/%2/Macros" ).arg( QDir::homePath() ).arg( QApplication::applicationName() );
293 QDir aDestDir(aDestPath);
294 QStringList aDestFiles = aDestDir.entryList(aFilter, QDir::Files);
295 foreach (QString aMacrosPath, getEmbeddedMacrosList()) {
296 QString aMacrosName = QFileInfo(aMacrosPath).fileName();
297 if (aDestFiles.contains(aMacrosName)) {
298 aDestDir.remove(aMacrosName);
306 PVGUI_Module::~PVGUI_Module()
308 if (myPushTraceTimer)
309 delete myPushTraceTimer;
314 PVViewer_EngineWrapper * PVGUI_Module::GetEngine()
316 return PVViewer_EngineWrapper::GetInstance();
321 \brief Create data model.
322 \return module specific data model
324 CAM_DataModel* PVGUI_Module::createDataModel()
326 return new PVGUI_DataModel( this );
329 pqPVApplicationCore * PVGUI_Module::GetPVApplication()
331 return PVViewer_ViewManager::GetPVApplication();
335 \brief Initialize module. Creates menus, prepares context menu, etc.
336 \param app SALOME GUI application instance
338 void PVGUI_Module::initialize( CAM_Application* app )
340 LightApp_Module::initialize( app );
342 // Create ParaViS actions
344 // Create ParaViS menus
347 // Uncomment to debug ParaView initialization
348 // "aa" used instead of "i" as GDB doesn't like "i" variables :)
356 LightApp_Application* anApp = getApp();
357 SUIT_Desktop* aDesktop = anApp->desktop();
359 // Initialize ParaView client and associated behaviors
360 // and connect to externally launched pvserver
361 PVViewer_ViewManager::ParaviewInitApp(aDesktop, anApp->logWindow());
362 myGuiElements = PVViewer_GUIElements::GetInstance(aDesktop);
364 // Remember current state of desktop toolbars
365 QList<QToolBar*> foreignToolbars = aDesktop->findChildren<QToolBar*>();
369 // Behaviors and connection must be instanciated *after* widgets are in place
370 // In PARAVIS module we do not wait for PVViewer_ViewWindow to be instanciated to have this:
371 PVViewer_ViewManager::ParaviewInitBehaviors(true, aDesktop);
372 PVViewer_ViewManager::ConnectToExternalPVServer(aDesktop);
378 QList<QDockWidget*> activeDocks = aDesktop->findChildren<QDockWidget*>();
379 QList<QMenu*> activeMenus = aDesktop->findChildren<QMenu*>();
381 // Setup quick-launch shortcuts.
382 QShortcut *ctrlSpace = new QShortcut(Qt::CTRL + Qt::Key_Space, aDesktop);
383 QObject::connect(ctrlSpace, SIGNAL(activated()),
384 pqApplicationCore::instance(), SLOT(quickLaunch()));
386 // Find Plugin Dock Widgets
387 QList<QDockWidget*> currentDocks = aDesktop->findChildren<QDockWidget*>();
388 QList<QDockWidget*>::iterator i;
389 for (i = currentDocks.begin(); i != currentDocks.end(); ++i) {
390 if(!activeDocks.contains(*i)) {
391 myDockWidgets[*i] = false; // hidden by default
397 // [ABN] TODO: fix this - triggers a SEGFAULT at deactivation() time.
398 // QList<QMenu*> currentMenus = aDesktop->findChildren<QMenu*>();
399 // QList<QMenu*>::iterator im;
400 // for (im = currentMenus.begin(); im != currentMenus.end(); ++im) {
401 // if(!activeMenus.contains(*im)) {
402 // QString s = (*im)->title();
403 // std::cout << " MENU "<< s.toStdString() << std::endl;
404 // myMenus.append(*im);
408 PVViewer_ViewManager::ParaviewLoadConfigurations();
411 // Find created toolbars
412 QCoreApplication::processEvents();
414 QList<QToolBar*> allToolbars = aDesktop->findChildren<QToolBar*>();
415 foreach(QToolBar* aBar, allToolbars) {
416 if (!foreignToolbars.contains(aBar)) {
417 myToolbars[aBar] = true;
418 myToolbarBreaks[aBar] = false;
419 aBar->setVisible(false);
420 aBar->toggleViewAction()->setVisible(false);
426 SUIT_ResourceMgr* aResourceMgr = SUIT_Session::session()->resourceMgr();
427 bool isStop = aResourceMgr->booleanValue( PARAVIS_MODULE_NAME, "stop_trace", false );
430 // Start a timer to schedule asap:
432 myInitTimer = new QTimer(aDesktop);
433 QObject::connect(myInitTimer, SIGNAL(timeout()), this, SLOT(onInitTimer()) );
434 myInitTimer->setSingleShot(true);
435 myInitTimer->start(0);
437 // Another timer to regularly push the trace onto the engine:
438 myPushTraceTimer = new QTimer(aDesktop);
439 QObject::connect(myPushTraceTimer, SIGNAL(timeout()), this, SLOT(onPushTraceTimer()) );
440 myPushTraceTimer->setSingleShot(false);
441 myPushTraceTimer->start(500);
444 this->VTKConnect = vtkEventQtSlotConnect::New();
446 vtkProcessModule* pm = vtkProcessModule::GetProcessModule();
448 vtkPVSession* pvs = dynamic_cast<vtkPVSession*>(pm->GetSession());
450 vtkPVProgressHandler* ph = pvs->GetProgressHandler();
452 this->VTKConnect->Connect(ph, vtkCommand::StartEvent,
453 this, SLOT(onStartProgress()));
454 this->VTKConnect->Connect(ph, vtkCommand::EndEvent,
455 this, SLOT(onEndProgress()));
461 void PVGUI_Module::onStartProgress()
463 QApplication::setOverrideCursor(Qt::WaitCursor);
466 void PVGUI_Module::onEndProgress()
468 QApplication::restoreOverrideCursor();
471 void PVGUI_Module::onDataRepresentationUpdated() {
472 SalomeApp_Study* activeStudy = dynamic_cast<SalomeApp_Study*>(application()->activeStudy());
473 if(!activeStudy) return;
475 activeStudy->Modified();
479 \brief Initialisation timer event - trace start up
481 void PVGUI_Module::onInitTimer()
487 \brief Get list of embedded macros files
489 QStringList PVGUI_Module::getEmbeddedMacrosList()
491 QString aRootDir = getenv("PARAVIS_ROOT_DIR");
493 QString aSourcePath = aRootDir + "/bin/salome/Macro";
498 QDir aSourceDir(aSourcePath);
499 QStringList aSourceFiles = aSourceDir.entryList(aFilter, QDir::Files);
500 QStringList aFullPathSourceFiles;
501 foreach (QString aMacrosName, aSourceFiles) {
502 aFullPathSourceFiles << aSourceDir.absoluteFilePath(aMacrosName);
504 return aFullPathSourceFiles;
507 void PVGUI_Module::updateMacros()
509 pqPythonManager* aPythonManager = pqPVApplicationCore::instance()->pythonManager();
510 if(!aPythonManager) {
514 foreach (QString aStr, getEmbeddedMacrosList()) {
515 aPythonManager->addMacro(aStr);
521 \brief Get list of compliant dockable GUI elements
522 \param m map to be filled in ("type":"default_position")
524 void PVGUI_Module::windows( QMap<int, int>& m ) const
526 m.insert( LightApp_Application::WT_ObjectBrowser, Qt::LeftDockWidgetArea );
527 m.insert( LightApp_Application::WT_PyConsole, Qt::BottomDockWidgetArea );
528 // ParaView diagnostic output redirected here
529 m.insert( LightApp_Application::WT_LogWindow, Qt::BottomDockWidgetArea );
533 \brief Shows (toShow = true) or hides ParaView view window
535 void PVGUI_Module::showView( bool toShow )
537 LightApp_Application* anApp = getApp();
538 PVViewer_ViewManager* viewMgr =
539 dynamic_cast<PVViewer_ViewManager*>( anApp->getViewManager( PVViewer_Viewer::Type(), false ) );
541 viewMgr = new PVViewer_ViewManager( anApp->activeStudy(), anApp->desktop(), anApp->logWindow() );
542 anApp->addViewManager( viewMgr );
543 connect( viewMgr, SIGNAL( lastViewClosed( SUIT_ViewManager* ) ),
544 anApp, SLOT( onCloseView( SUIT_ViewManager* ) ) );
547 PVViewer_ViewWindow* pvWnd = dynamic_cast<PVViewer_ViewWindow*>( viewMgr->getActiveView() );
549 pvWnd = dynamic_cast<PVViewer_ViewWindow*>( viewMgr->createViewWindow() );
550 // this also connects to the pvserver and instantiates relevant PV behaviors
553 pvWnd->setShown( toShow );
554 if ( toShow ) pvWnd->setFocus();
558 \brief Slot to show help for proxy.
560 void PVGUI_Module::showHelpForProxy( const QString& groupname, const QString& proxyname )
562 pqHelpReaction::showProxyHelp(groupname, proxyname);
567 \brief Slot to show the waiting state.
569 void PVGUI_Module::onPreAccept()
571 getApp()->desktop()->statusBar()->showMessage(tr("STB_PREACCEPT"));
572 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
576 \brief Slot to show the ready state.
578 void PVGUI_Module::onPostAccept()
580 getApp()->desktop()->statusBar()->showMessage(tr("STB_POSTACCEPT"), 2000);
581 QTimer::singleShot(0, this, SLOT(endWaitCursor()));
585 \brief Slot to switch off wait cursor.
587 void PVGUI_Module::endWaitCursor()
589 QApplication::restoreOverrideCursor();
592 static void ParavisMessageOutput(QtMsgType type, const char *msg)
597 vtkOutputWindow::GetInstance()->DisplayText(msg);
600 vtkOutputWindow::GetInstance()->DisplayErrorText(msg);
603 vtkOutputWindow::GetInstance()->DisplayErrorText(msg);
606 vtkOutputWindow::GetInstance()->DisplayErrorText(msg);
612 \brief Activate module.
613 \param study current study
614 \return \c true if activaion is done successfully or 0 to prevent
617 bool PVGUI_Module::activateModule( SUIT_Study* study )
619 myOldMsgHandler = qInstallMsgHandler(ParavisMessageOutput);
621 SUIT_ExceptionHandler::addCleanUpRoutine( paravisCleanUp );
623 storeCommonWindowsState();
625 bool isDone = LightApp_Module::activateModule( study );
626 if ( !isDone ) return false;
629 if ( mySourcesMenuId != -1 ) menuMgr()->show(mySourcesMenuId);
630 if ( myFiltersMenuId != -1 ) menuMgr()->show(myFiltersMenuId);
631 if ( myMacrosMenuId != -1 ) menuMgr()->show(myMacrosMenuId);
632 if ( myToolbarsMenuId != -1 ) menuMgr()->show(myToolbarsMenuId);
634 // Update the various menus with the content pre-loaded in myGuiElements
635 QMenu* srcMenu = menuMgr()->findMenu( mySourcesMenuId );
636 myGuiElements->updateSourcesMenu(srcMenu);
637 QMenu* filtMenu = menuMgr()->findMenu( myFiltersMenuId );
638 myGuiElements->updateFiltersMenu(filtMenu);
639 QMenu* macMenu = menuMgr()->findMenu( myMacrosMenuId );
640 myGuiElements->updateMacrosMenu(macMenu);
642 setMenuShown( true );
643 setToolShown( true );
645 restoreDockWidgetsState();
647 QMenu* aMenu = menuMgr()->findMenu( myRecentMenuId );
649 QList<QAction*> anActns = aMenu->actions();
650 for (int i = 0; i < anActns.size(); ++i) {
651 QAction* a = anActns.at(i);
657 QList<QMenu*>::iterator it;
658 for (it = myMenus.begin(); it != myMenus.end(); ++it) {
659 QAction* a = (*it)->menuAction();
664 if ( myRecentMenuId != -1 ) menuMgr()->show(myRecentMenuId);
666 //ClientFindOrCreateParavisComponent(PARAVIS::GetCStudy(this));
673 \brief Deactivate module.
674 \param study current study
675 \return \c true if deactivaion is done successfully or 0 to prevent
676 deactivation on error
678 bool PVGUI_Module::deactivateModule( SUIT_Study* study )
680 MESSAGE("PARAVIS deactivation ...")
682 QMenu* aMenu = menuMgr()->findMenu( myRecentMenuId );
684 QList<QAction*> anActns = aMenu->actions();
685 for (int i = 0; i < anActns.size(); ++i) {
686 QAction* a = anActns.at(i);
688 a->setVisible(false);
692 QList<QMenu*>::iterator it;
693 for (it = myMenus.begin(); it != myMenus.end(); ++it) {
694 QAction* a = (*it)->menuAction();
696 a->setVisible(false);
699 QList<QDockWidget*> aStreamingViews = application()->desktop()->findChildren<QDockWidget*>("pqStreamingControls");
700 foreach(QDockWidget* aView, aStreamingViews) {
701 if (!myDockWidgets.contains(aView))
702 myDockWidgets[aView] = aView->isVisible();
705 /*if (pqImplementation::helpWindow) {
706 pqImplementation::helpWindow->hide();
710 menuMgr()->hide(myRecentMenuId);
711 menuMgr()->hide(mySourcesMenuId);
712 menuMgr()->hide(myFiltersMenuId);
713 menuMgr()->hide(myMacrosMenuId);
714 menuMgr()->hide(myToolbarsMenuId);
715 setMenuShown( false );
716 setToolShown( false );
718 saveDockWidgetsState();
720 SUIT_ExceptionHandler::removeCleanUpRoutine( paravisCleanUp );
723 qInstallMsgHandler(myOldMsgHandler);
725 restoreCommonWindowsState();
727 return LightApp_Module::deactivateModule( study );
732 \brief Called when application is closed.
734 Process finalize application functionality from ParaView in order to save server settings
735 and nullify application pointer if the application is being closed.
737 \param theApp application
739 void PVGUI_Module::onApplicationClosed( SUIT_Application* theApp )
741 PVViewer_ViewManager::ParaviewCleanup();
743 int aAppsNb = SUIT_Session::session()->applications().size();
745 deleteTemporaryFiles();
747 CAM_Module::onApplicationClosed(theApp);
752 \brief Deletes temporary files created during import operation from VISU
754 void PVGUI_Module::deleteTemporaryFiles()
756 foreach(QString aFile, myTemporaryFiles) {
757 if (QFile::exists(aFile)) {
758 QFile::remove(aFile);
765 \brief Called when study is closed.
767 Removes data model from the \a study.
769 \param study study being closed
771 void PVGUI_Module::studyClosed(SUIT_Study* study)
773 clearParaviewState();
775 LightApp_Module::studyClosed(study);
779 \brief Called when study is opened.
781 void PVGUI_Module::onModelOpened()
783 _PTR(Study) studyDS = PARAVIS::GetCStudy(this);
788 _PTR(SComponent) paravisComp =
789 studyDS->FindComponent(PARAVIS_MODULE_NAME);
794 _PTR(ChildIterator) anIter(studyDS->NewChildIterator(paravisComp));
795 for (; anIter->More(); anIter->Next()) {
796 _PTR(SObject) aSObj = anIter->Value();
797 _PTR(GenericAttribute) anAttr;
798 if (!aSObj->FindAttribute(anAttr, "AttributeLocalID")) {
801 _PTR(AttributeLocalID) anID(anAttr);
802 if (anID->Value() == PVSTATEID) {
809 \brief Returns IOR of current engine
811 QString PVGUI_Module::engineIOR() const
813 // CORBA::String_var anIOR = GetCPPEngine()->GetIOR();
814 // return QString(anIOR.in());
819 \brief Open file of format supported by ParaView
821 void PVGUI_Module::openFile(const char* theName)
825 pqLoadDataReaction::loadData(aFiles);
829 * Start trace invoking the newly introduced C++ API (PV 4.2)
830 * (inspired from pqTraceReaction::start())
832 void PVGUI_Module::startTrace()
834 vtkSMSessionProxyManager* pxm = pqActiveObjects::instance().activeServer()->proxyManager();
836 vtkSmartPointer<vtkSMProxy> proxy;
837 proxy.TakeReference(pxm->NewProxy("pythontracing", "PythonTraceOptions"));
840 vtkNew<vtkSMParaViewPipelineController> controller;
841 controller->InitializeProxy(proxy);
843 vtkSMTrace* trace = vtkSMTrace::StartTrace();
846 // Set manually the properties entered via the dialog box poping-up when requiring
847 // a trace start in PV4.2 (trace options)
848 trace->SetPropertiesToTraceOnCreate(vtkSMTrace::RECORD_USER_MODIFIED_PROPERTIES);
849 trace->SetFullyTraceSupplementalProxies(false);
853 void PVGUI_Module::stopTrace()
855 vtkSMTrace::StopTrace();
858 void PVGUI_Module::executeScript(const char *script)
861 pqPythonManager* manager = qobject_cast<pqPythonManager*>(
862 pqApplicationCore::instance()->manager("PYTHON_MANAGER"));
864 pqPythonDialog* pyDiag = manager->pythonShellDialog();
866 pyDiag->runString(script);
873 // * Debug function printing out the given interpreter's execution context
875 //void printInterpContext(PyInterp_Interp * interp )
877 // // Extract __smtraceString from interpreter's context
878 // const PyObject* ctxt = interp->getExecutionContext();
880 // PyObject* lst = PyDict_Keys((PyObject *)ctxt);
881 // Py_ssize_t siz = PyList_GET_SIZE(lst);
882 // for (Py_ssize_t i = 0; i < siz; i++)
884 // PyObject * elem = PyList_GetItem(lst, i);
885 // if (PyString_Check(elem))
887 // std::cout << "At pos:" << i << ", " << PyString_AsString(elem) << std::endl;
890 // std::cout << "At pos:" << i << ", not a string!" << std::endl;
896 \brief Returns trace string
898 static const QString MYReplaceStr("paraview.simple");
899 QString PVGUI_Module::getTraceString()
901 vtkSMTrace *tracer = vtkSMTrace::GetActiveTracer();
902 if (!tracer) // trace is not started
905 QString traceString(tracer->GetCurrentTrace());
906 std::stringstream nl; nl << std::endl; // surely there is some Qt trick to do that in a portable way??
907 QString end_line(nl.str().c_str());
908 // 'import pvsimple' is necessary to fix the first call to DisableFirstRenderCamera in the paraview trace
909 // 'ShowParaviewView()' ensure there is an opened viewing window (otherwise SEGFAULT!)
910 traceString = "import pvsimple" + end_line +
911 "pvsimple.ShowParaviewView()" + end_line + traceString;
913 // Replace import "paraview.simple" by "pvsimple"
914 if ((!traceString.isNull()) && traceString.length() != 0) {
915 int aPos = traceString.indexOf(MYReplaceStr);
917 traceString = traceString.replace(aPos, MYReplaceStr.length(), "pvsimple");
918 aPos = traceString.indexOf(MYReplaceStr, aPos);
926 \brief Saves trace string to disk file
928 void PVGUI_Module::saveTrace(const char* theName)
931 if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
932 MESSAGE( "Could not open file:" << theName );
935 QTextStream out(&file);
936 out << getTraceString();
941 \brief Saves ParaView state to a disk file
943 void PVGUI_Module::saveParaviewState(const char* theFileName)
945 pqApplicationCore::instance()->saveState(theFileName);
949 \brief Delete all objects for Paraview Pipeline Browser
951 void PVGUI_Module::clearParaviewState()
953 QAction* deleteAllAction = action(DeleteAllId);
954 if (deleteAllAction) {
955 deleteAllAction->activate(QAction::Trigger);
960 \brief Restores ParaView state from a disk file
962 If toClear == true, the current ojects will be deleted
964 void PVGUI_Module::loadParaviewState(const char* theFileName)
966 pqApplicationCore::instance()->loadState(theFileName, getActiveServer());
970 \brief Returns current active ParaView server
972 pqServer* PVGUI_Module::getActiveServer()
974 return pqApplicationCore::instance()->getActiveServer();
979 \brief Creates PARAVIS preference pane
981 void PVGUI_Module::createPreferences()
983 // Paraview settings tab
984 int aParaViewSettingsTab = addPreference( tr( "TIT_PVIEWSETTINGS" ) );
986 setPreferenceProperty(aParaViewSettingsTab, "stretch", false );
987 int aPanel = addPreference(QString(), aParaViewSettingsTab, LightApp_Preferences::UserDefined, PARAVIS_MODULE_NAME, "");
989 setPreferenceProperty(aPanel, "content", (qint64)(new PVGUI_ParaViewSettingsPane()));
991 // Paravis settings tab
992 int aParaVisSettingsTab = addPreference( tr( "TIT_PVISSETTINGS" ) );
993 addPreference( tr( "PREF_STOP_TRACE" ), aParaVisSettingsTab, LightApp_Preferences::Bool, PARAVIS_MODULE_NAME, "stop_trace");
995 addPreference( tr( "PREF_NO_EXT_PVSERVER" ), aParaVisSettingsTab, LightApp_Preferences::Bool, PARAVIS_MODULE_NAME, "no_ext_pv_server");
997 int aSaveType = addPreference(tr( "PREF_SAVE_TYPE_LBL" ), aParaVisSettingsTab,
998 LightApp_Preferences::Selector,
999 PARAVIS_MODULE_NAME, "savestate_type");
1000 QList<QVariant> aIndices;
1001 QStringList aStrings;
1003 aStrings<<tr("PREF_SAVE_TYPE_0");
1004 aStrings<<tr("PREF_SAVE_TYPE_1");
1005 aStrings<<tr("PREF_SAVE_TYPE_2");
1006 setPreferenceProperty(aSaveType, "strings", aStrings);
1007 setPreferenceProperty(aSaveType, "indexes", aIndices);
1011 \brief Creates ParaViS context menu popup
1013 void PVGUI_Module::contextMenuPopup(const QString& theClient, QMenu* theMenu, QString& theTitle)
1015 LightApp_Module::contextMenuPopup(theClient, theMenu, theTitle);
1017 // Check if we are in Object Browser
1018 SUIT_DataBrowser* ob = getApp()->objectBrowser();
1019 bool isOBClient = (ob && theClient == ob->popupClientType());
1024 // Get list of selected objects
1025 LightApp_SelectionMgr* aSelectionMgr = getApp()->selectionMgr();
1026 SALOME_ListIO aListIO;
1027 aSelectionMgr->selectedObjects(aListIO);
1028 if (aListIO.Extent() == 1 && aListIO.First()->hasEntry()) {
1029 QString entry = QString(aListIO.First()->getEntry());
1032 SalomeApp_Study* activeStudy =
1033 dynamic_cast<SalomeApp_Study*>(getApp()->activeStudy());
1038 // Get SALOMEDS client study
1039 _PTR(Study) studyDS = activeStudy->studyDS();
1044 QString paravisDataType(PARAVIS_MODULE_NAME);
1045 if(activeStudy && activeStudy->isComponent(entry) &&
1046 activeStudy->componentDataType(entry) == paravisDataType) {
1047 // ParaViS module object
1048 theMenu->addSeparator();
1049 theMenu->addAction(action(SaveStatePopupId));
1052 // Try to get state object
1053 _PTR(SObject) stateSObj =
1054 studyDS->FindObjectID(entry.toLatin1().constData());
1060 _PTR(GenericAttribute) anAttr;
1061 if (!stateSObj->FindAttribute(anAttr, "AttributeLocalID")) {
1065 _PTR(AttributeLocalID) anID(anAttr);
1067 if (anID->Value() == PVSTATEID) {
1068 // Paraview state object
1069 theMenu->addSeparator();
1070 theMenu->addAction(action(AddStatePopupId));
1071 theMenu->addAction(action(CleanAndAddStatePopupId));
1072 theMenu->addSeparator();
1073 theMenu->addAction(action(ParaVisRenameId));
1074 theMenu->addAction(action(ParaVisDeleteId));
1081 \brief. Show ParaView python trace.
1083 void PVGUI_Module::onShowTrace()
1085 if (!myTraceWindow) {
1086 myTraceWindow = new pqPythonScriptEditor(getApp()->desktop());
1088 myTraceWindow->setText(getTraceString());
1089 myTraceWindow->show();
1090 myTraceWindow->raise();
1091 myTraceWindow->activateWindow();
1096 \brief. Re-initialize ParaView python trace.
1098 void PVGUI_Module::onRestartTrace()
1105 \brief Save state under the module root object.
1107 void PVGUI_Module::onSaveMultiState()
1109 // Create state study object
1111 // Get SALOMEDS client study
1112 _PTR(Study) studyDS = PARAVIS::GetCStudy(this);
1117 _PTR(SComponent) paravisComp =
1118 studyDS->FindComponent(PARAVIS_MODULE_NAME);
1123 // Unlock the study if it is locked
1124 bool isLocked = studyDS->GetProperties()->IsLocked();
1126 studyDS->GetProperties()->SetLocked(false);
1129 QString stateName = tr("SAVED_PARAVIEW_STATE_NAME") +
1130 QString::number(myStateCounter + 1);
1132 _PTR(StudyBuilder) studyBuilder = studyDS->NewBuilder();
1133 _PTR(SObject) newSObj = studyBuilder->NewObject(paravisComp);
1136 _PTR(GenericAttribute) anAttr;
1137 anAttr = studyBuilder->FindOrCreateAttribute(newSObj, "AttributeName");
1138 _PTR(AttributeName) nameAttr(anAttr);
1140 nameAttr->SetValue(stateName.toLatin1().constData());
1143 anAttr = studyBuilder->FindOrCreateAttribute(newSObj, "AttributeLocalID");
1144 _PTR(AttributeLocalID) localIdAttr(anAttr);
1146 localIdAttr->SetValue(PVSTATEID);
1149 QString stateEntry = QString::fromStdString(newSObj->GetID());
1151 // File name for state saving
1152 QString tmpDir = QString::fromStdString(SALOMEDS_Tool::GetTmpDir());
1153 QString fileName = QString("%1_paravisstate:%2").arg(tmpDir, stateEntry);
1155 anAttr = studyBuilder->FindOrCreateAttribute(newSObj, "AttributeString");
1156 _PTR(AttributeString) stringAttr(anAttr);
1158 stringAttr->SetValue(fileName.toLatin1().constData());
1160 // Lock the study back if necessary
1162 studyDS->GetProperties()->SetLocked(true);
1166 saveParaviewState(fileName.toLatin1().constData());
1167 myTemporaryFiles.append(fileName);
1169 // Increment the counter
1176 \brief Restore the selected state by merging with the current one.
1178 void PVGUI_Module::onAddState()
1180 loadSelectedState(false);
1184 \brief Clean the current state and restore the selected one.
1186 void PVGUI_Module::onCleanAddState()
1188 loadSelectedState(true);
1192 \brief Rename the selected object.
1194 void PVGUI_Module::onRename()
1196 LightApp_SelectionMgr* aSelectionMgr = getApp()->selectionMgr();
1197 SALOME_ListIO aListIO;
1198 aSelectionMgr->selectedObjects(aListIO);
1200 if (aListIO.Extent() == 1 && aListIO.First()->hasEntry()) {
1201 std::string entry = aListIO.First()->getEntry();
1203 // Get SALOMEDS client study
1204 _PTR(Study) studyDS = PARAVIS::GetCStudy(this);
1209 // Unlock the study if it is locked
1210 bool isLocked = studyDS->GetProperties()->IsLocked();
1212 studyDS->GetProperties()->SetLocked(false);
1215 // Rename the selected state object
1216 _PTR(SObject) stateSObj = studyDS->FindObjectID(entry);
1221 _PTR(GenericAttribute) anAttr;
1222 if (stateSObj->FindAttribute(anAttr, "AttributeName")) {
1223 _PTR(AttributeName) nameAttr (anAttr);
1225 LightApp_NameDlg::getName(getApp()->desktop(), nameAttr->Value().c_str());
1226 if (!newName.isEmpty()) {
1227 nameAttr->SetValue(newName.toLatin1().constData());
1228 aListIO.First()->setName(newName.toLatin1().constData());
1232 // Lock the study back if necessary
1234 studyDS->GetProperties()->SetLocked(true);
1237 // Update object browser
1244 \brief Delete the selected objects.
1246 void PVGUI_Module::onDelete()
1248 LightApp_SelectionMgr* aSelectionMgr = getApp()->selectionMgr();
1249 SALOME_ListIO aListIO;
1250 aSelectionMgr->selectedObjects(aListIO);
1252 if (aListIO.Extent() == 1 && aListIO.First()->hasEntry()) {
1253 std::string entry = aListIO.First()->getEntry();
1255 // Get SALOMEDS client study
1256 _PTR(Study) studyDS = PARAVIS::GetCStudy(this);
1261 // Unlock the study if it is locked
1262 bool isLocked = studyDS->GetProperties()->IsLocked();
1264 studyDS->GetProperties()->SetLocked(false);
1267 // Remove the selected state from the study
1268 _PTR(StudyBuilder) studyBuilder = studyDS->NewBuilder();
1269 _PTR(SObject) stateSObj = studyDS->FindObjectID(entry);
1270 studyBuilder->RemoveObject(stateSObj);
1272 // Lock the study back if necessary
1274 studyDS->GetProperties()->SetLocked(true);
1277 // Update object browser
1282 void PVGUI_Module::onPushTraceTimer()
1284 //MESSAGE("onPushTraceTimer(): Pushing trace to engine...");
1285 GetEngine()->PutPythonTraceStringToEngine(getTraceString().toStdString().c_str());
1289 \brief Discover help project files from the resources.
1290 \return name of the help file.
1292 QString PVGUI_Module::getHelpFileName() {
1293 QString aPVHome(getenv("PVHOME"));
1294 if (aPVHome.isNull()) {
1295 qWarning("Wariable PVHOME is not defined");
1298 QChar aSep = QDir::separator();
1299 //PARAVIEW_VERSION from the vtkPVConfig.h file
1300 QString aFileName = aPVHome + aSep + "share" + aSep + "doc" + aSep + "paraview-"+ PARAVIEW_VERSION + aSep + "paraview.qch";
1306 \brief Load selected paraview state
1308 If toClear == true, the current state will be cleared
1310 void PVGUI_Module::loadSelectedState(bool toClear)
1314 LightApp_SelectionMgr* aSelectionMgr = getApp()->selectionMgr();
1315 SALOME_ListIO aListIO;
1316 aSelectionMgr->selectedObjects(aListIO);
1318 if (aListIO.Extent() == 1 && aListIO.First()->hasEntry()) {
1319 std::string entry = aListIO.First()->getEntry();
1321 // Get SALOMEDS client study
1322 _PTR(Study) studyDS = PARAVIS::GetCStudy(this);
1328 _PTR(SObject) stateSObj = studyDS->FindObjectID(entry);
1329 _PTR(GenericAttribute) anAttr;
1330 if (!stateSObj->FindAttribute(anAttr, "AttributeLocalID")) {
1333 _PTR(AttributeLocalID) anID(anAttr);
1334 if (!anID->Value() == PVSTATEID) {
1338 // Get state file name
1339 if (stateSObj->FindAttribute(anAttr, "AttributeString")) {
1340 _PTR(AttributeString) aStringAttr(anAttr);
1341 QString stringValue(aStringAttr->Value().c_str());
1343 if (QFile::exists(stringValue)) {
1344 fileName = stringValue;
1349 if (!fileName.isEmpty()) {
1351 clearParaviewState();
1354 loadParaviewState(fileName.toLatin1().constData());
1357 SUIT_MessageBox::critical(getApp()->desktop(),
1359 tr("ERR_STATE_CANNOT_BE_RESTORED"));
1364 \fn CAM_Module* createModule();
1365 \brief Export module instance (factory function).
1366 \return new created instance of the module
1370 #define PVGUI_EXPORT __declspec(dllexport)
1372 #define PVGUI_EXPORT
1378 PVGUI_EXPORT CAM_Module* createModule() {
1379 return new PVGUI_Module();
1382 PVGUI_EXPORT char* getModuleVersion() {
1383 return (char*)PARAVIS_VERSION_STR;