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>
135 #include <pqPluginManager.h>
136 #include <pqVCRToolbar.h>
137 #include <pqAnimationScene.h>
138 #include <pqServerManagerModel.h>
139 #include <pqAnimationTimeToolbar.h>
141 //#include <PVViewer_EngineWrapper.h>
144 //----------------------------------------------------------------------------
145 PVGUI_Module* ParavisModule = 0;
146 PVSERVER_ORB::PVSERVER_Gen_var PVGUI_Module::MyEngine;
150 TODO TODO update this:
152 <h2>Building and installing PARAVIS</h2>
153 As any other SALOME module, PARAVIS requires PARAVIS_ROOT_DIR environment variable to be set to PARAVIS
154 installation directory.
155 Other variables needed for correct detection of ParaView location:
156 \li PVHOME - points at the ParaView installation directory tree
157 \li PVVERSION - number of ParaView version
159 It also requires common SALOME environment including GUI_ROOT_DIR and other prerequsites.
162 PARAVIS module can be launched using the following commands:
163 \li Full SALOME configuration
165 runSalome --modules="PARAVIS"
168 <h2>ParaView GUI integration</h2>
169 <h3>ParaView GUI integration overview</h3>
171 The main idea is to reuse ParaView GUI internal logic as much as possible, providing a layer
172 between it and SALOME GUI that hides the following SALOME GUI implementation details from ParaView:
174 \li SALOME GUI executable and Qt event loop
175 \li SALOME GUI desktop
176 \li Dock windows areas
177 \li SALOME menu and toolbar managers
179 Major part of the integration is implemented in PVGUI_Module class.
181 <h3>ParaView client initalization</h3>
183 ParaView client initalization is performed when an instance of PVGUI_Module class has been created
184 and \link PVGUI_Module::initialize() PVGUI_Module::initialize()\endlink method is called by SALOME GUI.
185 The actual client start-up is done in \link PVGUI_Module::pvInit() PVGUI_Module::pvInit()\endlink method.
188 <h3>Multi-view manager</h3>
190 SALOME GUI requires that each kind of view be implemnted with help of (at least) three classes. For ParaView multi-view manager
193 \li PVGUI_ViewManager - view manager class
194 \li PVGUI_Viewer - view model class
195 \li PVGUI_ViewWindow - view window class that acts as a parent for %pqViewManager
197 Single instances of PVGUI_ViewManager and PVGUI_ViewWindow classes are created by \link PVGUI_Module::showView()
198 PVGUI_Module::showView()\endlink method upon the first PARAVIS module activation. The same method hides the multi-view manager
199 when the module is deactivated (the user switches to another module or a study is closed).
200 A special trick is used to make PVGUI_ViewWindow the parent of %pqViewManager widget. It is created initally by %pqMainWindowCore
201 with the desktop as a parent, so when it is shown PVGUI_ViewWindow instance is passed to its setParent() method. In
202 \link PVGUI_ViewWindow::~PVGUI_ViewWindow() PVGUI_ViewWindow::~PVGUI_ViewWindow()\endlink the parent is nullified to avoid deletion
203 of %pqViewManager widget that would break %pqMainWindowCore class.
205 <h3>ParaView plugins</h3>
206 ParaView server and client plugins are managed by %pqMainWindowCore slots that has full access to PARAVIS menus and toolbars.
207 As a result they appears automatically in PARAVIS menus and toolbars if loaded successfully.
212 \brief Implementation
213 SALOME module wrapping ParaView GUI.
217 ClientFindOrCreateParavisComponent(_PTR(Study) theStudyDocument)
219 _PTR(SComponent) aSComponent = theStudyDocument->FindComponent("PVSERVER");
221 _PTR(StudyBuilder) aStudyBuilder = theStudyDocument->NewBuilder();
222 aStudyBuilder->NewCommand();
223 int aLocked = theStudyDocument->GetProperties()->IsLocked();
224 if (aLocked) theStudyDocument->GetProperties()->SetLocked(false);
225 aSComponent = aStudyBuilder->NewComponent("PVSERVER");
226 _PTR(GenericAttribute) anAttr =
227 aStudyBuilder->FindOrCreateAttribute(aSComponent, "AttributeName");
228 _PTR(AttributeName) aName (anAttr);
230 ORB_INIT& init = *SINGLETON_<ORB_INIT>::Instance();
231 CORBA::ORB_var anORB = init( qApp->argc(), qApp->argv() );
233 SALOME_NamingService *NamingService = new SALOME_NamingService( anORB );
234 CORBA::Object_var objVarN = NamingService->Resolve("/Kernel/ModulCatalog");
235 SALOME_ModuleCatalog::ModuleCatalog_var Catalogue =
236 SALOME_ModuleCatalog::ModuleCatalog::_narrow(objVarN);
237 SALOME_ModuleCatalog::Acomponent_var Comp = Catalogue->GetComponent( "PVSERVER" );
238 if (!Comp->_is_nil()) {
239 aName->SetValue(Comp->componentusername());
242 anAttr = aStudyBuilder->FindOrCreateAttribute(aSComponent, "AttributePixMap");
243 _PTR(AttributePixMap) aPixmap (anAttr);
244 aPixmap->SetPixMap( "pqAppIcon16.png" );
246 // Create Attribute parameters for future using
247 anAttr = aStudyBuilder->FindOrCreateAttribute(aSComponent, "AttributeParameter");
249 aStudyBuilder->DefineComponentInstance(aSComponent, PVGUI_Module::GetCPPEngine()->GetIOR());
250 if (aLocked) theStudyDocument->GetProperties()->SetLocked(true);
251 aStudyBuilder->CommitCommand();
257 Clean up function; used to stop ParaView progress events when
258 exception is caught by global exception handler.
260 void paravisCleanUp()
262 if ( pqApplicationCore::instance() ) {
263 pqServer* s = pqApplicationCore::instance()->getActiveServer();
264 if ( s ) s->session()->GetProgressHandler()->CleanupPendingProgress();
269 \brief Constructor. Sets the default name for the module.
271 PVGUI_Module::PVGUI_Module()
272 : SalomeApp_Module( PARAVIS_MODULE_NAME ),
273 mySelectionControlsTb( -1 ),
274 mySourcesMenuId( -1 ),
275 myFiltersMenuId( -1 ),
277 myToolbarsMenuId(-1),
287 Q_INIT_RESOURCE( PVGUI );
289 ParavisModule = this;
291 // Clear old copies of embedded macros files
292 QString aDestPath = QString( "%1/.config/%2/Macros" ).arg( QDir::homePath() ).arg( QApplication::applicationName() );
296 QDir aDestDir(aDestPath);
297 QStringList aDestFiles = aDestDir.entryList(aFilter, QDir::Files);
298 foreach (QString aMacrosPath, getEmbeddedMacrosList()) {
299 QString aMacrosName = QFileInfo(aMacrosPath).fileName();
300 if (aDestFiles.contains(aMacrosName)) {
301 aDestDir.remove(aMacrosName);
309 PVGUI_Module::~PVGUI_Module()
311 if (myPushTraceTimer)
312 delete myPushTraceTimer;
317 PVViewer_EngineWrapper * PVGUI_Module::GetEngine()
319 return PVViewer_EngineWrapper::GetInstance();
322 PVSERVER_ORB::PVSERVER_Gen_var PVGUI_Module::GetCPPEngine()
324 // initialize PARAVIS module engine (load, if necessary)
325 if ( CORBA::is_nil( MyEngine ) ) {
326 Engines::EngineComponent_var comp =
327 SalomeApp_Application::lcc()->FindOrLoad_Component( "FactoryServer", "PVSERVER" );
328 MyEngine = PVSERVER_ORB::PVSERVER_Gen::_narrow( comp );
334 \brief Create data model.
335 \return module specific data model
337 CAM_DataModel* PVGUI_Module::createDataModel()
339 return new PVGUI_DataModel( this );
342 pqPVApplicationCore * PVGUI_Module::GetPVApplication()
344 return PVViewer_ViewManager::GetPVApplication();
348 \brief Initialize module. Creates menus, prepares context menu, etc.
349 \param app SALOME GUI application instance
351 void PVGUI_Module::initialize( CAM_Application* app )
353 LightApp_Module::initialize( app );
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 // Remember current state of desktop toolbars
371 QList<QToolBar*> foreignToolbars = aDesktop->findChildren<QToolBar*>();
373 // Initialize ParaView client and associated behaviors
374 // and connect to externally launched pvserver
375 PVViewer_ViewManager::ParaviewInitApp(aDesktop, anApp->logWindow());
376 myGuiElements = PVViewer_GUIElements::GetInstance(aDesktop);
378 // [ABN]: careful with the order of the GUI element creation, the loading of the configuration
379 // and the connection to the server. This order is very sensitive if one wants to make
380 // sure all menus, etc ... are correctly populated.
381 // Reference points are: ParaViewMainWindow.cxx and branded_paraview_initializer.cxx.in
388 PVViewer_ViewManager::ParaviewInitBehaviors(true, aDesktop);
390 QList<QDockWidget*> activeDocks = aDesktop->findChildren<QDockWidget*>();
391 QList<QMenu*> activeMenus = aDesktop->findChildren<QMenu*>();
393 // Setup quick-launch shortcuts.
394 QShortcut *ctrlSpace = new QShortcut(Qt::CTRL + Qt::Key_Space, aDesktop);
395 QObject::connect(ctrlSpace, SIGNAL(activated()),
396 pqApplicationCore::instance(), SLOT(quickLaunch()));
398 // Find Plugin Dock Widgets
399 QList<QDockWidget*> currentDocks = aDesktop->findChildren<QDockWidget*>();
400 QList<QDockWidget*>::iterator i;
401 for (i = currentDocks.begin(); i != currentDocks.end(); ++i) {
402 if(!activeDocks.contains(*i)) {
403 myDockWidgets[*i] = false; // hidden by default
409 // [ABN] TODO: fix this - triggers a SEGFAULT at deactivation() time.
410 // QList<QMenu*> currentMenus = aDesktop->findChildren<QMenu*>();
411 // QList<QMenu*>::iterator im;
412 // for (im = currentMenus.begin(); im != currentMenus.end(); ++im) {
413 // if(!activeMenus.contains(*im)) {
414 // QString s = (*im)->title();
415 // std::cout << " MENU "<< s.toStdString() << std::endl;
416 // myMenus.append(*im);
420 // Connect after toolbar creation, etc ... as some activations of the toolbars is triggered
421 // by the ServerConnection event:
422 PVViewer_ViewManager::ParaviewLoadConfigurations(true);
423 PVViewer_ViewManager::ConnectToExternalPVServer(aDesktop);
426 // Find created toolbars
427 QCoreApplication::processEvents();
429 QList<QToolBar*> allToolbars = aDesktop->findChildren<QToolBar*>();
430 foreach(QToolBar* aBar, allToolbars) {
431 if (!foreignToolbars.contains(aBar)) {
432 myToolbars[aBar] = true;
433 myToolbarBreaks[aBar] = false;
434 aBar->setVisible(false);
435 aBar->toggleViewAction()->setVisible(false);
441 SUIT_ResourceMgr* aResourceMgr = SUIT_Session::session()->resourceMgr();
442 bool isStop = aResourceMgr->booleanValue( PARAVIS_MODULE_NAME, "stop_trace", false );
445 // Start a timer to schedule asap:
447 myInitTimer = new QTimer(aDesktop);
448 QObject::connect(myInitTimer, SIGNAL(timeout()), this, SLOT(onInitTimer()) );
449 myInitTimer->setSingleShot(true);
450 myInitTimer->start(0);
452 // Another timer to regularly push the trace onto the engine:
453 myPushTraceTimer = new QTimer(aDesktop);
454 QObject::connect(myPushTraceTimer, SIGNAL(timeout()), this, SLOT(onPushTraceTimer()) );
455 myPushTraceTimer->setSingleShot(false);
456 myPushTraceTimer->start(500);
459 this->VTKConnect = vtkEventQtSlotConnect::New();
461 vtkProcessModule* pm = vtkProcessModule::GetProcessModule();
463 vtkPVSession* pvs = dynamic_cast<vtkPVSession*>(pm->GetSession());
465 vtkPVProgressHandler* ph = pvs->GetProgressHandler();
467 this->VTKConnect->Connect(ph, vtkCommand::StartEvent,
468 this, SLOT(onStartProgress()));
469 this->VTKConnect->Connect(ph, vtkCommand::EndEvent,
470 this, SLOT(onEndProgress()));
479 * Little trick to force the proper update of the timesteps/time range when the module is initialized.
480 * This is otherwise not properly working when PARAVIS is activated after a PVViewer has already been
483 void PVGUI_Module::fixAnimationScene()
485 pqServer* server = pqActiveObjects::instance().activeServer();
486 pqApplicationCore * app = pqApplicationCore::instance();
487 pqPipelineSource * src = app->getObjectBuilder()->createSource(QString("sources"), QString("TimeSource"),server);
488 app->getObjectBuilder()->destroy(src);
491 void PVGUI_Module::onStartProgress()
493 QApplication::setOverrideCursor(Qt::WaitCursor);
496 void PVGUI_Module::onEndProgress()
498 QApplication::restoreOverrideCursor();
501 void PVGUI_Module::onDataRepresentationUpdated() {
502 SalomeApp_Study* activeStudy = dynamic_cast<SalomeApp_Study*>(application()->activeStudy());
503 if(!activeStudy) return;
505 activeStudy->Modified();
509 \brief Initialisation timer event - trace start up
511 void PVGUI_Module::onInitTimer()
517 \brief Get list of embedded macros files
519 QStringList PVGUI_Module::getEmbeddedMacrosList()
521 QString aRootDir = getenv("PARAVIS_ROOT_DIR");
523 QString aSourcePath = aRootDir + "/bin/salome/Macro";
528 QDir aSourceDir(aSourcePath);
529 QStringList aSourceFiles = aSourceDir.entryList(aFilter, QDir::Files);
530 QStringList aFullPathSourceFiles;
531 foreach (QString aMacrosName, aSourceFiles) {
532 aFullPathSourceFiles << aSourceDir.absoluteFilePath(aMacrosName);
534 return aFullPathSourceFiles;
537 void PVGUI_Module::updateMacros()
539 pqPythonManager* aPythonManager = pqPVApplicationCore::instance()->pythonManager();
540 if(!aPythonManager) {
544 foreach (QString aStr, getEmbeddedMacrosList()) {
545 aPythonManager->addMacro(aStr);
551 \brief Get list of compliant dockable GUI elements
552 \param m map to be filled in ("type":"default_position")
554 void PVGUI_Module::windows( QMap<int, int>& m ) const
556 m.insert( LightApp_Application::WT_ObjectBrowser, Qt::LeftDockWidgetArea );
557 m.insert( LightApp_Application::WT_PyConsole, Qt::BottomDockWidgetArea );
558 // ParaView diagnostic output redirected here
559 m.insert( LightApp_Application::WT_LogWindow, Qt::BottomDockWidgetArea );
563 \brief Shows (toShow = true) or hides ParaView view window
565 void PVGUI_Module::showView( bool toShow )
567 LightApp_Application* anApp = getApp();
568 PVViewer_ViewManager* viewMgr =
569 dynamic_cast<PVViewer_ViewManager*>( anApp->getViewManager( PVViewer_Viewer::Type(), false ) );
571 viewMgr = new PVViewer_ViewManager( anApp->activeStudy(), anApp->desktop(), anApp->logWindow() );
572 anApp->addViewManager( viewMgr );
573 connect( viewMgr, SIGNAL( lastViewClosed( SUIT_ViewManager* ) ),
574 anApp, SLOT( onCloseView( SUIT_ViewManager* ) ) );
577 PVViewer_ViewWindow* pvWnd = dynamic_cast<PVViewer_ViewWindow*>( viewMgr->getActiveView() );
579 pvWnd = dynamic_cast<PVViewer_ViewWindow*>( viewMgr->createViewWindow() );
580 // this also connects to the pvserver and instantiates relevant PV behaviors
583 pvWnd->setShown( toShow );
584 if ( toShow ) pvWnd->setFocus();
588 \brief Slot to show help for proxy.
590 void PVGUI_Module::showHelpForProxy( const QString& groupname, const QString& proxyname )
592 pqHelpReaction::showProxyHelp(groupname, proxyname);
597 \brief Slot to show the waiting state.
599 void PVGUI_Module::onPreAccept()
601 getApp()->desktop()->statusBar()->showMessage(tr("STB_PREACCEPT"));
602 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
606 \brief Slot to show the ready state.
608 void PVGUI_Module::onPostAccept()
610 getApp()->desktop()->statusBar()->showMessage(tr("STB_POSTACCEPT"), 2000);
611 QTimer::singleShot(0, this, SLOT(endWaitCursor()));
615 \brief Slot to switch off wait cursor.
617 void PVGUI_Module::endWaitCursor()
619 QApplication::restoreOverrideCursor();
622 static void ParavisMessageOutput(QtMsgType type, const char *msg)
627 vtkOutputWindow::GetInstance()->DisplayText(msg);
630 vtkOutputWindow::GetInstance()->DisplayErrorText(msg);
633 vtkOutputWindow::GetInstance()->DisplayErrorText(msg);
636 vtkOutputWindow::GetInstance()->DisplayErrorText(msg);
642 \brief Activate module.
643 \param study current study
644 \return \c true if activaion is done successfully or 0 to prevent
647 bool PVGUI_Module::activateModule( SUIT_Study* study )
649 myOldMsgHandler = qInstallMsgHandler(ParavisMessageOutput);
651 SUIT_ExceptionHandler::addCleanUpRoutine( paravisCleanUp );
653 storeCommonWindowsState();
655 bool isDone = LightApp_Module::activateModule( study );
656 if ( !isDone ) return false;
659 if ( mySourcesMenuId != -1 ) menuMgr()->show(mySourcesMenuId);
660 if ( myFiltersMenuId != -1 ) menuMgr()->show(myFiltersMenuId);
661 if ( myMacrosMenuId != -1 ) menuMgr()->show(myMacrosMenuId);
662 if ( myToolbarsMenuId != -1 ) menuMgr()->show(myToolbarsMenuId);
664 // Update the various menus with the content pre-loaded in myGuiElements
665 // QMenu* srcMenu = menuMgr()->findMenu( mySourcesMenuId );
666 // myGuiElements->updateSourcesMenu(srcMenu);
667 // QMenu* filtMenu = menuMgr()->findMenu( myFiltersMenuId );
668 // myGuiElements->updateFiltersMenu(filtMenu);
669 // QMenu* macMenu = menuMgr()->findMenu( myMacrosMenuId );
670 // myGuiElements->updateMacrosMenu(macMenu);
672 setMenuShown( true );
673 setToolShown( true );
675 restoreDockWidgetsState();
677 QMenu* aMenu = menuMgr()->findMenu( myRecentMenuId );
679 QList<QAction*> anActns = aMenu->actions();
680 for (int i = 0; i < anActns.size(); ++i) {
681 QAction* a = anActns.at(i);
687 QList<QMenu*>::iterator it;
688 for (it = myMenus.begin(); it != myMenus.end(); ++it) {
689 QAction* a = (*it)->menuAction();
694 if ( myRecentMenuId != -1 ) menuMgr()->show(myRecentMenuId);
696 ClientFindOrCreateParavisComponent(PARAVIS::GetCStudy(this));
703 \brief Deactivate module.
704 \param study current study
705 \return \c true if deactivaion is done successfully or 0 to prevent
706 deactivation on error
708 bool PVGUI_Module::deactivateModule( SUIT_Study* study )
710 MESSAGE("PARAVIS deactivation ...")
712 QMenu* aMenu = menuMgr()->findMenu( myRecentMenuId );
714 QList<QAction*> anActns = aMenu->actions();
715 for (int i = 0; i < anActns.size(); ++i) {
716 QAction* a = anActns.at(i);
718 a->setVisible(false);
722 QList<QMenu*>::iterator it;
723 for (it = myMenus.begin(); it != myMenus.end(); ++it) {
724 QAction* a = (*it)->menuAction();
726 a->setVisible(false);
729 QList<QDockWidget*> aStreamingViews = application()->desktop()->findChildren<QDockWidget*>("pqStreamingControls");
730 foreach(QDockWidget* aView, aStreamingViews) {
731 if (!myDockWidgets.contains(aView))
732 myDockWidgets[aView] = aView->isVisible();
735 /*if (pqImplementation::helpWindow) {
736 pqImplementation::helpWindow->hide();
740 menuMgr()->hide(myRecentMenuId);
741 menuMgr()->hide(mySourcesMenuId);
742 menuMgr()->hide(myFiltersMenuId);
743 menuMgr()->hide(myMacrosMenuId);
744 menuMgr()->hide(myToolbarsMenuId);
745 setMenuShown( false );
746 setToolShown( false );
748 saveDockWidgetsState();
750 SUIT_ExceptionHandler::removeCleanUpRoutine( paravisCleanUp );
753 qInstallMsgHandler(myOldMsgHandler);
755 restoreCommonWindowsState();
757 return LightApp_Module::deactivateModule( study );
762 \brief Called when application is closed.
764 Process finalize application functionality from ParaView in order to save server settings
765 and nullify application pointer if the application is being closed.
767 \param theApp application
769 void PVGUI_Module::onApplicationClosed( SUIT_Application* theApp )
771 PVViewer_ViewManager::ParaviewCleanup();
773 int aAppsNb = SUIT_Session::session()->applications().size();
775 deleteTemporaryFiles();
777 CAM_Module::onApplicationClosed(theApp);
782 \brief Deletes temporary files created during import operation from VISU
784 void PVGUI_Module::deleteTemporaryFiles()
786 foreach(QString aFile, myTemporaryFiles) {
787 if (QFile::exists(aFile)) {
788 QFile::remove(aFile);
795 \brief Called when study is closed.
797 Removes data model from the \a study.
799 \param study study being closed
801 void PVGUI_Module::studyClosed(SUIT_Study* study)
803 clearParaviewState();
805 LightApp_Module::studyClosed(study);
809 \brief Called when study is opened.
811 void PVGUI_Module::onModelOpened()
813 _PTR(Study) studyDS = PARAVIS::GetCStudy(this);
818 _PTR(SComponent) paravisComp =
819 studyDS->FindComponent(PARAVIS_MODULE_NAME);
824 _PTR(ChildIterator) anIter(studyDS->NewChildIterator(paravisComp));
825 for (; anIter->More(); anIter->Next()) {
826 _PTR(SObject) aSObj = anIter->Value();
827 _PTR(GenericAttribute) anAttr;
828 if (!aSObj->FindAttribute(anAttr, "AttributeLocalID")) {
831 _PTR(AttributeLocalID) anID(anAttr);
832 if (anID->Value() == PVSTATEID) {
839 \brief Returns IOR of current engine
841 QString PVGUI_Module::engineIOR() const
843 CORBA::String_var anIOR = GetCPPEngine()->GetIOR();
844 return QString(anIOR.in());
848 \brief Open file of format supported by ParaView
850 void PVGUI_Module::openFile(const char* theName)
854 pqLoadDataReaction::loadData(aFiles);
858 * Start trace invoking the newly introduced C++ API (PV 4.2)
859 * (inspired from pqTraceReaction::start())
861 void PVGUI_Module::startTrace()
863 vtkSMSessionProxyManager* pxm = pqActiveObjects::instance().activeServer()->proxyManager();
865 vtkSmartPointer<vtkSMProxy> proxy;
866 proxy.TakeReference(pxm->NewProxy("pythontracing", "PythonTraceOptions"));
869 vtkNew<vtkSMParaViewPipelineController> controller;
870 controller->InitializeProxy(proxy);
872 vtkSMTrace* trace = vtkSMTrace::StartTrace();
875 // Set manually the properties entered via the dialog box poping-up when requiring
876 // a trace start in PV4.2 (trace options)
877 trace->SetPropertiesToTraceOnCreate(vtkSMTrace::RECORD_USER_MODIFIED_PROPERTIES);
878 trace->SetFullyTraceSupplementalProxies(false);
882 void PVGUI_Module::stopTrace()
884 vtkSMTrace::StopTrace();
887 void PVGUI_Module::executeScript(const char *script)
890 pqPythonManager* manager = qobject_cast<pqPythonManager*>(
891 pqApplicationCore::instance()->manager("PYTHON_MANAGER"));
893 pqPythonDialog* pyDiag = manager->pythonShellDialog();
895 pyDiag->runString(script);
902 // * Debug function printing out the given interpreter's execution context
904 //void printInterpContext(PyInterp_Interp * interp )
906 // // Extract __smtraceString from interpreter's context
907 // const PyObject* ctxt = interp->getExecutionContext();
909 // PyObject* lst = PyDict_Keys((PyObject *)ctxt);
910 // Py_ssize_t siz = PyList_GET_SIZE(lst);
911 // for (Py_ssize_t i = 0; i < siz; i++)
913 // PyObject * elem = PyList_GetItem(lst, i);
914 // if (PyString_Check(elem))
916 // std::cout << "At pos:" << i << ", " << PyString_AsString(elem) << std::endl;
919 // std::cout << "At pos:" << i << ", not a string!" << std::endl;
925 \brief Returns trace string
927 static const QString MYReplaceStr("paraview.simple");
928 QString PVGUI_Module::getTraceString()
930 vtkSMTrace *tracer = vtkSMTrace::GetActiveTracer();
931 if (!tracer) // trace is not started
934 QString traceString(tracer->GetCurrentTrace());
935 std::stringstream nl; nl << std::endl; // surely there is some Qt trick to do that in a portable way??
936 QString end_line(nl.str().c_str());
937 // 'import pvsimple' is necessary to fix the first call to DisableFirstRenderCamera in the paraview trace
938 // 'ShowParaviewView()' ensure there is an opened viewing window (otherwise SEGFAULT!)
939 traceString = "import pvsimple" + end_line +
940 "pvsimple.ShowParaviewView()" + end_line + traceString;
942 // Replace import "paraview.simple" by "pvsimple"
943 if ((!traceString.isNull()) && traceString.length() != 0) {
944 int aPos = traceString.indexOf(MYReplaceStr);
946 traceString = traceString.replace(aPos, MYReplaceStr.length(), "pvsimple");
947 aPos = traceString.indexOf(MYReplaceStr, aPos);
955 \brief Saves trace string to disk file
957 void PVGUI_Module::saveTrace(const char* theName)
960 if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
961 MESSAGE( "Could not open file:" << theName );
964 QTextStream out(&file);
965 out << getTraceString();
970 \brief Saves ParaView state to a disk file
972 void PVGUI_Module::saveParaviewState(const char* theFileName)
974 pqApplicationCore::instance()->saveState(theFileName);
978 \brief Delete all objects for Paraview Pipeline Browser
980 void PVGUI_Module::clearParaviewState()
982 QAction* deleteAllAction = action(DeleteAllId);
983 if (deleteAllAction) {
984 deleteAllAction->activate(QAction::Trigger);
989 \brief Restores ParaView state from a disk file
991 If toClear == true, the current ojects will be deleted
993 void PVGUI_Module::loadParaviewState(const char* theFileName)
995 pqApplicationCore::instance()->loadState(theFileName, getActiveServer());
999 \brief Returns current active ParaView server
1001 pqServer* PVGUI_Module::getActiveServer()
1003 return pqApplicationCore::instance()->getActiveServer();
1008 \brief Creates PARAVIS preference pane
1010 void PVGUI_Module::createPreferences()
1012 // Paraview settings tab
1013 int aParaViewSettingsTab = addPreference( tr( "TIT_PVIEWSETTINGS" ) );
1015 setPreferenceProperty(aParaViewSettingsTab, "stretch", false );
1016 int aPanel = addPreference(QString(), aParaViewSettingsTab, LightApp_Preferences::UserDefined, PARAVIS_MODULE_NAME, "");
1018 setPreferenceProperty(aPanel, "content", (qint64)(new PVGUI_ParaViewSettingsPane(0, getApp())));
1020 // Paravis settings tab
1021 int aParaVisSettingsTab = addPreference( tr( "TIT_PVISSETTINGS" ) );
1022 addPreference( tr( "PREF_STOP_TRACE" ), aParaVisSettingsTab, LightApp_Preferences::Bool, PARAVIS_MODULE_NAME, "stop_trace");
1024 addPreference( tr( "PREF_NO_EXT_PVSERVER" ), aParaVisSettingsTab, LightApp_Preferences::Bool, PARAVIS_MODULE_NAME, "no_ext_pv_server");
1026 int aSaveType = addPreference(tr( "PREF_SAVE_TYPE_LBL" ), aParaVisSettingsTab,
1027 LightApp_Preferences::Selector,
1028 PARAVIS_MODULE_NAME, "savestate_type");
1029 QList<QVariant> aIndices;
1030 QStringList aStrings;
1032 aStrings<<tr("PREF_SAVE_TYPE_0");
1033 aStrings<<tr("PREF_SAVE_TYPE_1");
1034 aStrings<<tr("PREF_SAVE_TYPE_2");
1035 setPreferenceProperty(aSaveType, "strings", aStrings);
1036 setPreferenceProperty(aSaveType, "indexes", aIndices);
1040 \brief Creates ParaViS context menu popup
1042 void PVGUI_Module::contextMenuPopup(const QString& theClient, QMenu* theMenu, QString& theTitle)
1044 LightApp_Module::contextMenuPopup(theClient, theMenu, theTitle);
1046 // Check if we are in Object Browser
1047 SUIT_DataBrowser* ob = getApp()->objectBrowser();
1048 bool isOBClient = (ob && theClient == ob->popupClientType());
1053 // Get list of selected objects
1054 LightApp_SelectionMgr* aSelectionMgr = getApp()->selectionMgr();
1055 SALOME_ListIO aListIO;
1056 aSelectionMgr->selectedObjects(aListIO);
1057 if (aListIO.Extent() == 1 && aListIO.First()->hasEntry()) {
1058 QString entry = QString(aListIO.First()->getEntry());
1061 SalomeApp_Study* activeStudy =
1062 dynamic_cast<SalomeApp_Study*>(getApp()->activeStudy());
1067 // Get SALOMEDS client study
1068 _PTR(Study) studyDS = activeStudy->studyDS();
1073 QString paravisDataType(PARAVIS_MODULE_NAME);
1074 if(activeStudy && activeStudy->isComponent(entry) &&
1075 activeStudy->componentDataType(entry) == paravisDataType) {
1076 // ParaViS module object
1077 theMenu->addSeparator();
1078 theMenu->addAction(action(SaveStatePopupId));
1081 // Try to get state object
1082 _PTR(SObject) stateSObj =
1083 studyDS->FindObjectID(entry.toLatin1().constData());
1089 _PTR(GenericAttribute) anAttr;
1090 if (!stateSObj->FindAttribute(anAttr, "AttributeLocalID")) {
1094 _PTR(AttributeLocalID) anID(anAttr);
1096 if (anID->Value() == PVSTATEID) {
1097 // Paraview state object
1098 theMenu->addSeparator();
1099 theMenu->addAction(action(AddStatePopupId));
1100 theMenu->addAction(action(CleanAndAddStatePopupId));
1101 theMenu->addSeparator();
1102 theMenu->addAction(action(ParaVisRenameId));
1103 theMenu->addAction(action(ParaVisDeleteId));
1110 \brief. Show ParaView python trace.
1112 void PVGUI_Module::onShowTrace()
1114 if (!myTraceWindow) {
1115 myTraceWindow = new pqPythonScriptEditor(getApp()->desktop());
1117 myTraceWindow->setText(getTraceString());
1118 myTraceWindow->show();
1119 myTraceWindow->raise();
1120 myTraceWindow->activateWindow();
1125 \brief. Re-initialize ParaView python trace.
1127 void PVGUI_Module::onRestartTrace()
1134 \brief Save state under the module root object.
1136 void PVGUI_Module::onSaveMultiState()
1138 // Create state study object
1140 // Get SALOMEDS client study
1141 _PTR(Study) studyDS = PARAVIS::GetCStudy(this);
1146 _PTR(SComponent) paravisComp =
1147 studyDS->FindComponent(PARAVIS_MODULE_NAME);
1152 // Unlock the study if it is locked
1153 bool isLocked = studyDS->GetProperties()->IsLocked();
1155 studyDS->GetProperties()->SetLocked(false);
1158 QString stateName = tr("SAVED_PARAVIEW_STATE_NAME") +
1159 QString::number(myStateCounter + 1);
1161 _PTR(StudyBuilder) studyBuilder = studyDS->NewBuilder();
1162 _PTR(SObject) newSObj = studyBuilder->NewObject(paravisComp);
1165 _PTR(GenericAttribute) anAttr;
1166 anAttr = studyBuilder->FindOrCreateAttribute(newSObj, "AttributeName");
1167 _PTR(AttributeName) nameAttr(anAttr);
1169 nameAttr->SetValue(stateName.toLatin1().constData());
1172 anAttr = studyBuilder->FindOrCreateAttribute(newSObj, "AttributeLocalID");
1173 _PTR(AttributeLocalID) localIdAttr(anAttr);
1175 localIdAttr->SetValue(PVSTATEID);
1178 QString stateEntry = QString::fromStdString(newSObj->GetID());
1180 // File name for state saving
1181 QString tmpDir = QString::fromStdString(SALOMEDS_Tool::GetTmpDir());
1182 QString fileName = QString("%1_paravisstate:%2").arg(tmpDir, stateEntry);
1184 anAttr = studyBuilder->FindOrCreateAttribute(newSObj, "AttributeString");
1185 _PTR(AttributeString) stringAttr(anAttr);
1187 stringAttr->SetValue(fileName.toLatin1().constData());
1189 // Lock the study back if necessary
1191 studyDS->GetProperties()->SetLocked(true);
1195 saveParaviewState(fileName.toLatin1().constData());
1196 myTemporaryFiles.append(fileName);
1198 // Increment the counter
1205 \brief Restore the selected state by merging with the current one.
1207 void PVGUI_Module::onAddState()
1209 loadSelectedState(false);
1213 \brief Clean the current state and restore the selected one.
1215 void PVGUI_Module::onCleanAddState()
1217 loadSelectedState(true);
1221 \brief Rename the selected object.
1223 void PVGUI_Module::onRename()
1225 LightApp_SelectionMgr* aSelectionMgr = getApp()->selectionMgr();
1226 SALOME_ListIO aListIO;
1227 aSelectionMgr->selectedObjects(aListIO);
1229 if (aListIO.Extent() == 1 && aListIO.First()->hasEntry()) {
1230 std::string entry = aListIO.First()->getEntry();
1232 // Get SALOMEDS client study
1233 _PTR(Study) studyDS = PARAVIS::GetCStudy(this);
1238 // Unlock the study if it is locked
1239 bool isLocked = studyDS->GetProperties()->IsLocked();
1241 studyDS->GetProperties()->SetLocked(false);
1244 // Rename the selected state object
1245 _PTR(SObject) stateSObj = studyDS->FindObjectID(entry);
1250 _PTR(GenericAttribute) anAttr;
1251 if (stateSObj->FindAttribute(anAttr, "AttributeName")) {
1252 _PTR(AttributeName) nameAttr (anAttr);
1254 LightApp_NameDlg::getName(getApp()->desktop(), nameAttr->Value().c_str());
1255 if (!newName.isEmpty()) {
1256 nameAttr->SetValue(newName.toLatin1().constData());
1257 aListIO.First()->setName(newName.toLatin1().constData());
1261 // Lock the study back if necessary
1263 studyDS->GetProperties()->SetLocked(true);
1266 // Update object browser
1273 \brief Delete the selected objects.
1275 void PVGUI_Module::onDelete()
1277 LightApp_SelectionMgr* aSelectionMgr = getApp()->selectionMgr();
1278 SALOME_ListIO aListIO;
1279 aSelectionMgr->selectedObjects(aListIO);
1281 if (aListIO.Extent() == 1 && aListIO.First()->hasEntry()) {
1282 std::string entry = aListIO.First()->getEntry();
1284 // Get SALOMEDS client study
1285 _PTR(Study) studyDS = PARAVIS::GetCStudy(this);
1290 // Unlock the study if it is locked
1291 bool isLocked = studyDS->GetProperties()->IsLocked();
1293 studyDS->GetProperties()->SetLocked(false);
1296 // Remove the selected state from the study
1297 _PTR(StudyBuilder) studyBuilder = studyDS->NewBuilder();
1298 _PTR(SObject) stateSObj = studyDS->FindObjectID(entry);
1299 studyBuilder->RemoveObject(stateSObj);
1301 // Lock the study back if necessary
1303 studyDS->GetProperties()->SetLocked(true);
1306 // Update object browser
1311 void PVGUI_Module::onPushTraceTimer()
1313 //MESSAGE("onPushTraceTimer(): Pushing trace to engine...");
1314 GetEngine()->PutPythonTraceStringToEngine(getTraceString().toStdString().c_str());
1318 \brief Discover help project files from the resources.
1319 \return name of the help file.
1321 QString PVGUI_Module::getHelpFileName() {
1322 QString aPVHome(getenv("PVHOME"));
1323 if (aPVHome.isNull()) {
1324 qWarning("Wariable PVHOME is not defined");
1327 QChar aSep = QDir::separator();
1328 //PARAVIEW_VERSION from the vtkPVConfig.h file
1329 QString aFileName = aPVHome + aSep + "share" + aSep + "doc" + aSep + "paraview-"+ PARAVIEW_VERSION + aSep + "paraview.qch";
1335 \brief Load selected paraview state
1337 If toClear == true, the current state will be cleared
1339 void PVGUI_Module::loadSelectedState(bool toClear)
1343 LightApp_SelectionMgr* aSelectionMgr = getApp()->selectionMgr();
1344 SALOME_ListIO aListIO;
1345 aSelectionMgr->selectedObjects(aListIO);
1347 if (aListIO.Extent() == 1 && aListIO.First()->hasEntry()) {
1348 std::string entry = aListIO.First()->getEntry();
1350 // Get SALOMEDS client study
1351 _PTR(Study) studyDS = PARAVIS::GetCStudy(this);
1357 _PTR(SObject) stateSObj = studyDS->FindObjectID(entry);
1358 _PTR(GenericAttribute) anAttr;
1359 if (!stateSObj->FindAttribute(anAttr, "AttributeLocalID")) {
1362 _PTR(AttributeLocalID) anID(anAttr);
1363 if (!anID->Value() == PVSTATEID) {
1367 // Get state file name
1368 if (stateSObj->FindAttribute(anAttr, "AttributeString")) {
1369 _PTR(AttributeString) aStringAttr(anAttr);
1370 QString stringValue(aStringAttr->Value().c_str());
1372 if (QFile::exists(stringValue)) {
1373 fileName = stringValue;
1378 if (!fileName.isEmpty()) {
1380 clearParaviewState();
1383 loadParaviewState(fileName.toLatin1().constData());
1386 SUIT_MessageBox::critical(getApp()->desktop(),
1388 tr("ERR_STATE_CANNOT_BE_RESTORED"));
1393 \fn CAM_Module* createModule();
1394 \brief Export module instance (factory function).
1395 \return new created instance of the module
1399 #define PVGUI_EXPORT __declspec(dllexport)
1401 #define PVGUI_EXPORT
1407 PVGUI_EXPORT CAM_Module* createModule() {
1408 return new PVGUI_Module();
1411 PVGUI_EXPORT char* getModuleVersion() {
1412 return (char*)PARAVIS_VERSION_STR;