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 //#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 // process PVViewer toolbars (might be added by PVViewer created BEFORE activating ParaVis)
430 QList<QToolBar*> pvToolbars = myGuiElements->getToolbars();
431 foreach(QToolBar* aBar, pvToolbars) {
432 if (!myToolbars.contains(aBar)) {
433 myToolbars[aBar] = true;
434 myToolbarBreaks[aBar] = false;
435 aBar->setVisible(false);
436 aBar->toggleViewAction()->setVisible(false);
440 // process other toolbars (possibly added by Paraview)
441 QList<QToolBar*> allToolbars = aDesktop->findChildren<QToolBar*>();
442 foreach(QToolBar* aBar, allToolbars) {
443 if (!foreignToolbars.contains(aBar) && !myToolbars.contains(aBar)) {
444 myToolbars[aBar] = true;
445 myToolbarBreaks[aBar] = false;
446 aBar->setVisible(false);
447 aBar->toggleViewAction()->setVisible(false);
453 SUIT_ResourceMgr* aResourceMgr = SUIT_Session::session()->resourceMgr();
454 bool isStop = aResourceMgr->booleanValue( PARAVIS_MODULE_NAME, "stop_trace", false );
457 // Start a timer to schedule asap:
459 myInitTimer = new QTimer(aDesktop);
460 QObject::connect(myInitTimer, SIGNAL(timeout()), this, SLOT(onInitTimer()) );
461 myInitTimer->setSingleShot(true);
462 myInitTimer->start(0);
464 // Another timer to regularly push the trace onto the engine:
465 myPushTraceTimer = new QTimer(aDesktop);
466 QObject::connect(myPushTraceTimer, SIGNAL(timeout()), this, SLOT(onPushTraceTimer()) );
467 myPushTraceTimer->setSingleShot(false);
468 myPushTraceTimer->start(500);
471 this->VTKConnect = vtkEventQtSlotConnect::New();
473 vtkProcessModule* pm = vtkProcessModule::GetProcessModule();
475 vtkPVSession* pvs = dynamic_cast<vtkPVSession*>(pm->GetSession());
477 vtkPVProgressHandler* ph = pvs->GetProgressHandler();
479 this->VTKConnect->Connect(ph, vtkCommand::StartEvent,
480 this, SLOT(onStartProgress()));
481 this->VTKConnect->Connect(ph, vtkCommand::EndEvent,
482 this, SLOT(onEndProgress()));
491 * Little trick to force the proper update of the timesteps/time range when the module is initialized.
492 * This is otherwise not properly working when PARAVIS is activated after a PVViewer has already been
495 void PVGUI_Module::fixAnimationScene()
497 pqServer* server = pqActiveObjects::instance().activeServer();
498 pqApplicationCore * app = pqApplicationCore::instance();
499 pqPipelineSource * src = app->getObjectBuilder()->createSource(QString("sources"), QString("TimeSource"),server);
500 app->getObjectBuilder()->destroy(src);
503 void PVGUI_Module::onStartProgress()
505 QApplication::setOverrideCursor(Qt::WaitCursor);
508 void PVGUI_Module::onEndProgress()
510 QApplication::restoreOverrideCursor();
513 void PVGUI_Module::onDataRepresentationUpdated() {
514 SalomeApp_Study* activeStudy = dynamic_cast<SalomeApp_Study*>(application()->activeStudy());
515 if(!activeStudy) return;
517 activeStudy->Modified();
521 \brief Initialisation timer event - trace start up
523 void PVGUI_Module::onInitTimer()
529 \brief Get list of embedded macros files
531 QStringList PVGUI_Module::getEmbeddedMacrosList()
533 QString aRootDir = getenv("PARAVIS_ROOT_DIR");
535 QString aSourcePath = aRootDir + "/bin/salome/Macro";
540 QDir aSourceDir(aSourcePath);
541 QStringList aSourceFiles = aSourceDir.entryList(aFilter, QDir::Files);
542 QStringList aFullPathSourceFiles;
543 foreach (QString aMacrosName, aSourceFiles) {
544 aFullPathSourceFiles << aSourceDir.absoluteFilePath(aMacrosName);
546 return aFullPathSourceFiles;
549 void PVGUI_Module::updateMacros()
551 pqPythonManager* aPythonManager = pqPVApplicationCore::instance()->pythonManager();
552 if(!aPythonManager) {
556 foreach (QString aStr, getEmbeddedMacrosList()) {
557 aPythonManager->addMacro(aStr);
563 \brief Get list of compliant dockable GUI elements
564 \param m map to be filled in ("type":"default_position")
566 void PVGUI_Module::windows( QMap<int, int>& m ) const
568 m.insert( LightApp_Application::WT_ObjectBrowser, Qt::LeftDockWidgetArea );
569 m.insert( LightApp_Application::WT_PyConsole, Qt::BottomDockWidgetArea );
570 // ParaView diagnostic output redirected here
571 m.insert( LightApp_Application::WT_LogWindow, Qt::BottomDockWidgetArea );
575 \brief Shows (toShow = true) or hides ParaView view window
577 void PVGUI_Module::showView( bool toShow )
579 LightApp_Application* anApp = getApp();
580 PVViewer_ViewManager* viewMgr =
581 dynamic_cast<PVViewer_ViewManager*>( anApp->getViewManager( PVViewer_Viewer::Type(), false ) );
583 viewMgr = new PVViewer_ViewManager( anApp->activeStudy(), anApp->desktop(), anApp->logWindow() );
584 anApp->addViewManager( viewMgr );
585 connect( viewMgr, SIGNAL( lastViewClosed( SUIT_ViewManager* ) ),
586 anApp, SLOT( onCloseView( SUIT_ViewManager* ) ) );
589 PVViewer_ViewWindow* pvWnd = dynamic_cast<PVViewer_ViewWindow*>( viewMgr->getActiveView() );
591 pvWnd = dynamic_cast<PVViewer_ViewWindow*>( viewMgr->createViewWindow() );
592 // this also connects to the pvserver and instantiates relevant PV behaviors
595 pvWnd->setShown( toShow );
596 if ( toShow ) pvWnd->setFocus();
600 \brief Slot to show help for proxy.
602 void PVGUI_Module::showHelpForProxy( const QString& groupname, const QString& proxyname )
604 pqHelpReaction::showProxyHelp(groupname, proxyname);
609 \brief Slot to show the waiting state.
611 void PVGUI_Module::onPreAccept()
613 getApp()->desktop()->statusBar()->showMessage(tr("STB_PREACCEPT"));
614 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
618 \brief Slot to show the ready state.
620 void PVGUI_Module::onPostAccept()
622 getApp()->desktop()->statusBar()->showMessage(tr("STB_POSTACCEPT"), 2000);
623 QTimer::singleShot(0, this, SLOT(endWaitCursor()));
627 \brief Slot to switch off wait cursor.
629 void PVGUI_Module::endWaitCursor()
631 QApplication::restoreOverrideCursor();
634 static void ParavisMessageOutput(QtMsgType type, const char *msg)
639 vtkOutputWindow::GetInstance()->DisplayText(msg);
642 vtkOutputWindow::GetInstance()->DisplayErrorText(msg);
645 vtkOutputWindow::GetInstance()->DisplayErrorText(msg);
648 vtkOutputWindow::GetInstance()->DisplayErrorText(msg);
654 \brief Activate module.
655 \param study current study
656 \return \c true if activaion is done successfully or 0 to prevent
659 bool PVGUI_Module::activateModule( SUIT_Study* study )
661 myOldMsgHandler = qInstallMsgHandler(ParavisMessageOutput);
663 SUIT_ExceptionHandler::addCleanUpRoutine( paravisCleanUp );
665 storeCommonWindowsState();
667 bool isDone = LightApp_Module::activateModule( study );
668 if ( !isDone ) return false;
671 if ( mySourcesMenuId != -1 ) menuMgr()->show(mySourcesMenuId);
672 if ( myFiltersMenuId != -1 ) menuMgr()->show(myFiltersMenuId);
673 if ( myMacrosMenuId != -1 ) menuMgr()->show(myMacrosMenuId);
674 if ( myToolbarsMenuId != -1 ) menuMgr()->show(myToolbarsMenuId);
676 // Update the various menus with the content pre-loaded in myGuiElements
677 // QMenu* srcMenu = menuMgr()->findMenu( mySourcesMenuId );
678 // myGuiElements->updateSourcesMenu(srcMenu);
679 // QMenu* filtMenu = menuMgr()->findMenu( myFiltersMenuId );
680 // myGuiElements->updateFiltersMenu(filtMenu);
681 // QMenu* macMenu = menuMgr()->findMenu( myMacrosMenuId );
682 // myGuiElements->updateMacrosMenu(macMenu);
684 setMenuShown( true );
685 setToolShown( true );
687 restoreDockWidgetsState();
689 QMenu* aMenu = menuMgr()->findMenu( myRecentMenuId );
691 QList<QAction*> anActns = aMenu->actions();
692 for (int i = 0; i < anActns.size(); ++i) {
693 QAction* a = anActns.at(i);
699 QList<QMenu*>::iterator it;
700 for (it = myMenus.begin(); it != myMenus.end(); ++it) {
701 QAction* a = (*it)->menuAction();
706 if ( myRecentMenuId != -1 ) menuMgr()->show(myRecentMenuId);
708 ClientFindOrCreateParavisComponent(PARAVIS::GetCStudy(this));
715 \brief Deactivate module.
716 \param study current study
717 \return \c true if deactivaion is done successfully or 0 to prevent
718 deactivation on error
720 bool PVGUI_Module::deactivateModule( SUIT_Study* study )
722 MESSAGE("PARAVIS deactivation ...")
724 QMenu* aMenu = menuMgr()->findMenu( myRecentMenuId );
726 QList<QAction*> anActns = aMenu->actions();
727 for (int i = 0; i < anActns.size(); ++i) {
728 QAction* a = anActns.at(i);
730 a->setVisible(false);
734 QList<QMenu*>::iterator it;
735 for (it = myMenus.begin(); it != myMenus.end(); ++it) {
736 QAction* a = (*it)->menuAction();
738 a->setVisible(false);
741 QList<QDockWidget*> aStreamingViews = application()->desktop()->findChildren<QDockWidget*>("pqStreamingControls");
742 foreach(QDockWidget* aView, aStreamingViews) {
743 if (!myDockWidgets.contains(aView))
744 myDockWidgets[aView] = aView->isVisible();
747 /*if (pqImplementation::helpWindow) {
748 pqImplementation::helpWindow->hide();
752 menuMgr()->hide(myRecentMenuId);
753 menuMgr()->hide(mySourcesMenuId);
754 menuMgr()->hide(myFiltersMenuId);
755 menuMgr()->hide(myMacrosMenuId);
756 menuMgr()->hide(myToolbarsMenuId);
757 setMenuShown( false );
758 setToolShown( false );
760 saveDockWidgetsState();
762 SUIT_ExceptionHandler::removeCleanUpRoutine( paravisCleanUp );
765 qInstallMsgHandler(myOldMsgHandler);
767 restoreCommonWindowsState();
769 return LightApp_Module::deactivateModule( study );
774 \brief Called when application is closed.
776 Process finalize application functionality from ParaView in order to save server settings
777 and nullify application pointer if the application is being closed.
779 \param theApp application
781 void PVGUI_Module::onApplicationClosed( SUIT_Application* theApp )
783 PVViewer_ViewManager::ParaviewCleanup();
785 int aAppsNb = SUIT_Session::session()->applications().size();
787 deleteTemporaryFiles();
789 CAM_Module::onApplicationClosed(theApp);
794 \brief Deletes temporary files created during import operation from VISU
796 void PVGUI_Module::deleteTemporaryFiles()
798 foreach(QString aFile, myTemporaryFiles) {
799 if (QFile::exists(aFile)) {
800 QFile::remove(aFile);
807 \brief Called when study is closed.
809 Removes data model from the \a study.
811 \param study study being closed
813 void PVGUI_Module::studyClosed(SUIT_Study* study)
815 clearParaviewState();
817 LightApp_Module::studyClosed(study);
821 \brief Called when study is opened.
823 void PVGUI_Module::onModelOpened()
825 _PTR(Study) studyDS = PARAVIS::GetCStudy(this);
830 _PTR(SComponent) paravisComp =
831 studyDS->FindComponent(PARAVIS_MODULE_NAME);
836 _PTR(ChildIterator) anIter(studyDS->NewChildIterator(paravisComp));
837 for (; anIter->More(); anIter->Next()) {
838 _PTR(SObject) aSObj = anIter->Value();
839 _PTR(GenericAttribute) anAttr;
840 if (!aSObj->FindAttribute(anAttr, "AttributeLocalID")) {
843 _PTR(AttributeLocalID) anID(anAttr);
844 if (anID->Value() == PVSTATEID) {
851 \brief Returns IOR of current engine
853 QString PVGUI_Module::engineIOR() const
855 CORBA::String_var anIOR = GetCPPEngine()->GetIOR();
856 return QString(anIOR.in());
860 \brief Open file of format supported by ParaView
862 void PVGUI_Module::openFile(const char* theName)
866 pqLoadDataReaction::loadData(aFiles);
870 * Start trace invoking the newly introduced C++ API (PV 4.2)
871 * (inspired from pqTraceReaction::start())
873 void PVGUI_Module::startTrace()
875 vtkSMSessionProxyManager* pxm = pqActiveObjects::instance().activeServer()->proxyManager();
877 vtkSmartPointer<vtkSMProxy> proxy;
878 proxy.TakeReference(pxm->NewProxy("pythontracing", "PythonTraceOptions"));
881 vtkNew<vtkSMParaViewPipelineController> controller;
882 controller->InitializeProxy(proxy);
884 vtkSMTrace* trace = vtkSMTrace::StartTrace();
887 // Set manually the properties entered via the dialog box poping-up when requiring
888 // a trace start in PV4.2 (trace options)
889 trace->SetPropertiesToTraceOnCreate(vtkSMTrace::RECORD_USER_MODIFIED_PROPERTIES);
890 trace->SetFullyTraceSupplementalProxies(false);
894 void PVGUI_Module::stopTrace()
896 vtkSMTrace::StopTrace();
899 void PVGUI_Module::executeScript(const char *script)
902 pqPythonManager* manager = qobject_cast<pqPythonManager*>(
903 pqApplicationCore::instance()->manager("PYTHON_MANAGER"));
905 pqPythonDialog* pyDiag = manager->pythonShellDialog();
907 pyDiag->runString(script);
914 // * Debug function printing out the given interpreter's execution context
916 //void printInterpContext(PyInterp_Interp * interp )
918 // // Extract __smtraceString from interpreter's context
919 // const PyObject* ctxt = interp->getExecutionContext();
921 // PyObject* lst = PyDict_Keys((PyObject *)ctxt);
922 // Py_ssize_t siz = PyList_GET_SIZE(lst);
923 // for (Py_ssize_t i = 0; i < siz; i++)
925 // PyObject * elem = PyList_GetItem(lst, i);
926 // if (PyString_Check(elem))
928 // std::cout << "At pos:" << i << ", " << PyString_AsString(elem) << std::endl;
931 // std::cout << "At pos:" << i << ", not a string!" << std::endl;
937 \brief Returns trace string
939 static const QString MYReplaceStr("paraview.simple");
940 QString PVGUI_Module::getTraceString()
942 vtkSMTrace *tracer = vtkSMTrace::GetActiveTracer();
943 if (!tracer) // trace is not started
946 QString traceString(tracer->GetCurrentTrace());
947 std::stringstream nl; nl << std::endl; // surely there is some Qt trick to do that in a portable way??
948 QString end_line(nl.str().c_str());
949 // 'import pvsimple' is necessary to fix the first call to DisableFirstRenderCamera in the paraview trace
950 // 'ShowParaviewView()' ensure there is an opened viewing window (otherwise SEGFAULT!)
951 traceString = "import pvsimple" + end_line +
952 "pvsimple.ShowParaviewView()" + end_line + traceString;
954 // Replace import "paraview.simple" by "pvsimple"
955 if ((!traceString.isNull()) && traceString.length() != 0) {
956 int aPos = traceString.indexOf(MYReplaceStr);
958 traceString = traceString.replace(aPos, MYReplaceStr.length(), "pvsimple");
959 aPos = traceString.indexOf(MYReplaceStr, aPos);
967 \brief Saves trace string to disk file
969 void PVGUI_Module::saveTrace(const char* theName)
972 if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
973 MESSAGE( "Could not open file:" << theName );
976 QTextStream out(&file);
977 out << getTraceString();
982 \brief Saves ParaView state to a disk file
984 void PVGUI_Module::saveParaviewState(const char* theFileName)
986 pqApplicationCore::instance()->saveState(theFileName);
990 \brief Delete all objects for Paraview Pipeline Browser
992 void PVGUI_Module::clearParaviewState()
994 QAction* deleteAllAction = action(DeleteAllId);
995 if (deleteAllAction) {
996 deleteAllAction->activate(QAction::Trigger);
1001 \brief Restores ParaView state from a disk file
1003 If toClear == true, the current ojects will be deleted
1005 void PVGUI_Module::loadParaviewState(const char* theFileName)
1007 pqApplicationCore::instance()->loadState(theFileName, getActiveServer());
1011 \brief Returns current active ParaView server
1013 pqServer* PVGUI_Module::getActiveServer()
1015 return pqApplicationCore::instance()->getActiveServer();
1020 \brief Creates PARAVIS preference pane
1022 void PVGUI_Module::createPreferences()
1024 // Paraview settings tab
1025 int aParaViewSettingsTab = addPreference( tr( "TIT_PVIEWSETTINGS" ) );
1027 setPreferenceProperty(aParaViewSettingsTab, "stretch", false );
1028 int aPanel = addPreference(QString(), aParaViewSettingsTab, LightApp_Preferences::UserDefined, PARAVIS_MODULE_NAME, "");
1030 setPreferenceProperty(aPanel, "content", (qint64)(new PVGUI_ParaViewSettingsPane(0, getApp())));
1032 // Paravis settings tab
1033 int aParaVisSettingsTab = addPreference( tr( "TIT_PVISSETTINGS" ) );
1034 addPreference( tr( "PREF_STOP_TRACE" ), aParaVisSettingsTab, LightApp_Preferences::Bool, PARAVIS_MODULE_NAME, "stop_trace");
1036 addPreference( tr( "PREF_NO_EXT_PVSERVER" ), aParaVisSettingsTab, LightApp_Preferences::Bool, PARAVIS_MODULE_NAME, "no_ext_pv_server");
1038 int aSaveType = addPreference(tr( "PREF_SAVE_TYPE_LBL" ), aParaVisSettingsTab,
1039 LightApp_Preferences::Selector,
1040 PARAVIS_MODULE_NAME, "savestate_type");
1041 QList<QVariant> aIndices;
1042 QStringList aStrings;
1044 aStrings<<tr("PREF_SAVE_TYPE_0");
1045 aStrings<<tr("PREF_SAVE_TYPE_1");
1046 aStrings<<tr("PREF_SAVE_TYPE_2");
1047 setPreferenceProperty(aSaveType, "strings", aStrings);
1048 setPreferenceProperty(aSaveType, "indexes", aIndices);
1052 \brief Creates ParaViS context menu popup
1054 void PVGUI_Module::contextMenuPopup(const QString& theClient, QMenu* theMenu, QString& theTitle)
1056 LightApp_Module::contextMenuPopup(theClient, theMenu, theTitle);
1058 // Check if we are in Object Browser
1059 SUIT_DataBrowser* ob = getApp()->objectBrowser();
1060 bool isOBClient = (ob && theClient == ob->popupClientType());
1065 // Get list of selected objects
1066 LightApp_SelectionMgr* aSelectionMgr = getApp()->selectionMgr();
1067 SALOME_ListIO aListIO;
1068 aSelectionMgr->selectedObjects(aListIO);
1069 if (aListIO.Extent() == 1 && aListIO.First()->hasEntry()) {
1070 QString entry = QString(aListIO.First()->getEntry());
1073 SalomeApp_Study* activeStudy =
1074 dynamic_cast<SalomeApp_Study*>(getApp()->activeStudy());
1079 // Get SALOMEDS client study
1080 _PTR(Study) studyDS = activeStudy->studyDS();
1085 QString paravisDataType(PARAVIS_MODULE_NAME);
1086 if(activeStudy && activeStudy->isComponent(entry) &&
1087 activeStudy->componentDataType(entry) == paravisDataType) {
1088 // ParaViS module object
1089 theMenu->addSeparator();
1090 theMenu->addAction(action(SaveStatePopupId));
1093 // Try to get state object
1094 _PTR(SObject) stateSObj =
1095 studyDS->FindObjectID(entry.toLatin1().constData());
1101 _PTR(GenericAttribute) anAttr;
1102 if (!stateSObj->FindAttribute(anAttr, "AttributeLocalID")) {
1106 _PTR(AttributeLocalID) anID(anAttr);
1108 if (anID->Value() == PVSTATEID) {
1109 // Paraview state object
1110 theMenu->addSeparator();
1111 theMenu->addAction(action(AddStatePopupId));
1112 theMenu->addAction(action(CleanAndAddStatePopupId));
1113 theMenu->addSeparator();
1114 theMenu->addAction(action(ParaVisRenameId));
1115 theMenu->addAction(action(ParaVisDeleteId));
1122 \brief. Show ParaView python trace.
1124 void PVGUI_Module::onShowTrace()
1126 if (!myTraceWindow) {
1127 myTraceWindow = new pqPythonScriptEditor(getApp()->desktop());
1129 myTraceWindow->setText(getTraceString());
1130 myTraceWindow->show();
1131 myTraceWindow->raise();
1132 myTraceWindow->activateWindow();
1137 \brief. Re-initialize ParaView python trace.
1139 void PVGUI_Module::onRestartTrace()
1146 \brief Save state under the module root object.
1148 void PVGUI_Module::onSaveMultiState()
1150 // Create state study object
1152 // Get SALOMEDS client study
1153 _PTR(Study) studyDS = PARAVIS::GetCStudy(this);
1158 _PTR(SComponent) paravisComp =
1159 studyDS->FindComponent(PARAVIS_MODULE_NAME);
1164 // Unlock the study if it is locked
1165 bool isLocked = studyDS->GetProperties()->IsLocked();
1167 studyDS->GetProperties()->SetLocked(false);
1170 QString stateName = tr("SAVED_PARAVIEW_STATE_NAME") +
1171 QString::number(myStateCounter + 1);
1173 _PTR(StudyBuilder) studyBuilder = studyDS->NewBuilder();
1174 _PTR(SObject) newSObj = studyBuilder->NewObject(paravisComp);
1177 _PTR(GenericAttribute) anAttr;
1178 anAttr = studyBuilder->FindOrCreateAttribute(newSObj, "AttributeName");
1179 _PTR(AttributeName) nameAttr(anAttr);
1181 nameAttr->SetValue(stateName.toLatin1().constData());
1184 anAttr = studyBuilder->FindOrCreateAttribute(newSObj, "AttributeLocalID");
1185 _PTR(AttributeLocalID) localIdAttr(anAttr);
1187 localIdAttr->SetValue(PVSTATEID);
1190 QString stateEntry = QString::fromStdString(newSObj->GetID());
1192 // File name for state saving
1193 QString tmpDir = QString::fromStdString(SALOMEDS_Tool::GetTmpDir());
1194 QString fileName = QString("%1_paravisstate:%2").arg(tmpDir, stateEntry);
1196 anAttr = studyBuilder->FindOrCreateAttribute(newSObj, "AttributeString");
1197 _PTR(AttributeString) stringAttr(anAttr);
1199 stringAttr->SetValue(fileName.toLatin1().constData());
1201 // Lock the study back if necessary
1203 studyDS->GetProperties()->SetLocked(true);
1207 saveParaviewState(fileName.toLatin1().constData());
1208 myTemporaryFiles.append(fileName);
1210 // Increment the counter
1217 \brief Restore the selected state by merging with the current one.
1219 void PVGUI_Module::onAddState()
1221 loadSelectedState(false);
1225 \brief Clean the current state and restore the selected one.
1227 void PVGUI_Module::onCleanAddState()
1229 loadSelectedState(true);
1233 \brief Rename the selected object.
1235 void PVGUI_Module::onRename()
1237 LightApp_SelectionMgr* aSelectionMgr = getApp()->selectionMgr();
1238 SALOME_ListIO aListIO;
1239 aSelectionMgr->selectedObjects(aListIO);
1241 if (aListIO.Extent() == 1 && aListIO.First()->hasEntry()) {
1242 std::string entry = aListIO.First()->getEntry();
1244 // Get SALOMEDS client study
1245 _PTR(Study) studyDS = PARAVIS::GetCStudy(this);
1250 // Unlock the study if it is locked
1251 bool isLocked = studyDS->GetProperties()->IsLocked();
1253 studyDS->GetProperties()->SetLocked(false);
1256 // Rename the selected state object
1257 _PTR(SObject) stateSObj = studyDS->FindObjectID(entry);
1262 _PTR(GenericAttribute) anAttr;
1263 if (stateSObj->FindAttribute(anAttr, "AttributeName")) {
1264 _PTR(AttributeName) nameAttr (anAttr);
1266 LightApp_NameDlg::getName(getApp()->desktop(), nameAttr->Value().c_str());
1267 if (!newName.isEmpty()) {
1268 nameAttr->SetValue(newName.toLatin1().constData());
1269 aListIO.First()->setName(newName.toLatin1().constData());
1273 // Lock the study back if necessary
1275 studyDS->GetProperties()->SetLocked(true);
1278 // Update object browser
1285 \brief Delete the selected objects.
1287 void PVGUI_Module::onDelete()
1289 LightApp_SelectionMgr* aSelectionMgr = getApp()->selectionMgr();
1290 SALOME_ListIO aListIO;
1291 aSelectionMgr->selectedObjects(aListIO);
1293 if (aListIO.Extent() == 1 && aListIO.First()->hasEntry()) {
1294 std::string entry = aListIO.First()->getEntry();
1296 // Get SALOMEDS client study
1297 _PTR(Study) studyDS = PARAVIS::GetCStudy(this);
1302 // Unlock the study if it is locked
1303 bool isLocked = studyDS->GetProperties()->IsLocked();
1305 studyDS->GetProperties()->SetLocked(false);
1308 // Remove the selected state from the study
1309 _PTR(StudyBuilder) studyBuilder = studyDS->NewBuilder();
1310 _PTR(SObject) stateSObj = studyDS->FindObjectID(entry);
1311 studyBuilder->RemoveObject(stateSObj);
1313 // Lock the study back if necessary
1315 studyDS->GetProperties()->SetLocked(true);
1318 // Update object browser
1323 void PVGUI_Module::onPushTraceTimer()
1325 //MESSAGE("onPushTraceTimer(): Pushing trace to engine...");
1326 GetEngine()->PutPythonTraceStringToEngine(getTraceString().toStdString().c_str());
1330 \brief Discover help project files from the resources.
1331 \return name of the help file.
1333 QString PVGUI_Module::getHelpFileName() {
1334 QString aPVHome(getenv("PVHOME"));
1335 if (aPVHome.isNull()) {
1336 qWarning("Wariable PVHOME is not defined");
1339 QChar aSep = QDir::separator();
1340 //PARAVIEW_VERSION from the vtkPVConfig.h file
1341 QString aFileName = aPVHome + aSep + "share" + aSep + "doc" + aSep + "paraview-"+ PARAVIEW_VERSION + aSep + "paraview.qch";
1347 \brief Load selected paraview state
1349 If toClear == true, the current state will be cleared
1351 void PVGUI_Module::loadSelectedState(bool toClear)
1355 LightApp_SelectionMgr* aSelectionMgr = getApp()->selectionMgr();
1356 SALOME_ListIO aListIO;
1357 aSelectionMgr->selectedObjects(aListIO);
1359 if (aListIO.Extent() == 1 && aListIO.First()->hasEntry()) {
1360 std::string entry = aListIO.First()->getEntry();
1362 // Get SALOMEDS client study
1363 _PTR(Study) studyDS = PARAVIS::GetCStudy(this);
1369 _PTR(SObject) stateSObj = studyDS->FindObjectID(entry);
1370 _PTR(GenericAttribute) anAttr;
1371 if (!stateSObj->FindAttribute(anAttr, "AttributeLocalID")) {
1374 _PTR(AttributeLocalID) anID(anAttr);
1375 if (!anID->Value() == PVSTATEID) {
1379 // Get state file name
1380 if (stateSObj->FindAttribute(anAttr, "AttributeString")) {
1381 _PTR(AttributeString) aStringAttr(anAttr);
1382 QString stringValue(aStringAttr->Value().c_str());
1384 if (QFile::exists(stringValue)) {
1385 fileName = stringValue;
1390 if (!fileName.isEmpty()) {
1392 clearParaviewState();
1395 loadParaviewState(fileName.toLatin1().constData());
1398 SUIT_MessageBox::critical(getApp()->desktop(),
1400 tr("ERR_STATE_CANNOT_BE_RESTORED"));
1405 \fn CAM_Module* createModule();
1406 \brief Export module instance (factory function).
1407 \return new created instance of the module
1411 #define PVGUI_EXPORT __declspec(dllexport)
1413 #define PVGUI_EXPORT
1419 PVGUI_EXPORT CAM_Module* createModule() {
1420 return new PVGUI_Module();
1423 PVGUI_EXPORT char* getModuleVersion() {
1424 return (char*)PARAVIS_VERSION_STR;