1 // PARAVIS : ParaView wrapper SALOME module
3 // Copyright (C) 2010-2014 CEA/DEN, EDF R&D
5 // This library is free software; you can redistribute it and/or
6 // modify it under the terms of the GNU Lesser General Public
7 // License as published by the Free Software Foundation; either
8 // version 2.1 of the License, or (at your option) any later version.
10 // This library is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 // Lesser General Public License for more details.
15 // You should have received a copy of the GNU Lesser General Public
16 // License along with this library; if not, write to the Free Software
17 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 // File : PVGUI_Module.cxx
23 #define PARAVIS_MODULE_NAME "PARAVIS"
25 #include <Standard_math.hxx> // E.A. must be included before Python.h to fix compilation on windows
27 #undef HAVE_FINITE // VSR: avoid compilation warning on Linux : "HAVE_FINITE" redefined
29 #include <vtkPython.h> // Python first
30 #include "PVGUI_Module.h"
32 //#ifdef PARAVIS_WITH_FULL_CORBA
33 //# include "PARAVIS_Gen_i.hh"
36 #include CORBA_SERVER_HEADER(SALOME_ModuleCatalog)
37 #include CORBA_SERVER_HEADER(SALOMEDS)
39 #include "PVViewer_ViewManager.h"
40 #include "PVViewer_ViewWindow.h"
41 #include "PVViewer_ViewModel.h"
42 #include "PVGUI_Tools.h"
43 #include "PVGUI_ParaViewSettingsPane.h"
44 #include "PVViewer_GUIElements.h"
45 #include "PVViewer_EngineWrapper.h"
46 #include "PVGUI_DataModel.h"
49 #include <utilities.h>
50 #include <SUIT_DataBrowser.h>
51 #include <SUIT_Desktop.h>
52 #include <SUIT_MessageBox.h>
53 #include <SUIT_ResourceMgr.h>
54 #include <SUIT_Session.h>
55 #include <SUIT_OverrideCursor.h>
56 #include <SUIT_ExceptionHandler.h>
58 #include <SALOME_LifeCycleCORBA.hxx>
59 #include <SALOMEDS_SObject.hxx>
61 #include <LightApp_SelectionMgr.h>
62 #include <LightApp_NameDlg.h>
63 #include <LightApp_Application.h>
64 #include <SalomeApp_Application.h> // should ultimately be a LightApp only
65 #include <SalomeApp_Study.h>
66 #include <SALOME_ListIO.hxx>
67 #include <SALOMEDS_Tool.hxx>
68 #include <Utils_ORB_INIT.hxx>
69 #include <Utils_SINGLETON.hxx>
71 #include <QtxActionMenuMgr.h>
72 #include <QtxActionToolMgr.h>
74 #include <PARAVIS_version.h>
80 #include <QApplication>
86 #include <QInputDialog>
90 #include <QStringList>
93 #include <QTextStream>
95 #include <QDockWidget>
96 #include <QHelpEngine>
99 #include <vtkPVConfig.h> // for symbol PARAVIEW_VERSION
100 #include <vtkProcessModule.h>
101 #include <vtkPVSession.h>
102 #include <vtkPVProgressHandler.h>
103 #include <vtkOutputWindow.h>
104 #include <vtkEventQtSlotConnect.h>
106 #include <vtkSMProxy.h>
107 #include <vtkSmartPointer.h>
108 #include <vtkSMSession.h>
109 #include <vtkSMTrace.h>
110 #include <vtkSMSessionProxyManager.h>
111 #include <vtkSMParaViewPipelineController.h>
113 #include <pqApplicationCore.h>
114 #include <pqPVApplicationCore.h>
115 #include <pqActiveView.h>
116 #include <pqObjectBuilder.h>
117 #include <pqOptions.h>
118 #include <pqSettings.h>
119 #include <pqServer.h>
120 #include <pqUndoStack.h>
121 #include <pqTabbedMultiViewWidget.h>
122 #include <pqActiveObjects.h>
123 #include <pqHelpReaction.h>
124 #include <pqPluginManager.h>
125 #include <pqPythonDialog.h>
126 #include <pqPythonManager.h>
127 #include <pqLoadDataReaction.h>
128 #include <pqPythonScriptEditor.h>
129 #include <pqDataRepresentation.h>
130 #include <pqDisplayColorWidget.h>
131 #include <pqColorToolbar.h>
132 #include <pqScalarBarVisibilityReaction.h>
133 #include <pqServerResource.h>
134 #include <pqServerConnectReaction.h>
137 #include <PyInterp_Interp.h>
139 #include <PVViewer_EngineWrapper.h>
142 //----------------------------------------------------------------------------
143 PVGUI_Module* ParavisModule = 0;
144 PVSERVER_ORB::PVSERVER_Gen_var PVGUI_Module::MyEngine;
148 TODO TODO update this:
150 <h2>Building and installing PARAVIS</h2>
151 As any other SALOME module, PARAVIS requires PARAVIS_ROOT_DIR environment variable to be set to PARAVIS
152 installation directory.
153 Other variables needed for correct detection of ParaView location:
154 \li PVHOME - points at the ParaView installation directory tree
155 \li PVVERSION - number of ParaView version
157 It also requires common SALOME environment including GUI_ROOT_DIR and other prerequsites.
160 PARAVIS module can be launched using the following commands:
161 \li Full SALOME configuration
163 runSalome --modules="PARAVIS"
166 <h2>ParaView GUI integration</h2>
167 <h3>ParaView GUI integration overview</h3>
169 The main idea is to reuse ParaView GUI internal logic as much as possible, providing a layer
170 between it and SALOME GUI that hides the following SALOME GUI implementation details from ParaView:
172 \li SALOME GUI executable and Qt event loop
173 \li SALOME GUI desktop
174 \li Dock windows areas
175 \li SALOME menu and toolbar managers
177 Major part of the integration is implemented in PVGUI_Module class.
179 <h3>ParaView client initalization</h3>
181 ParaView client initalization is performed when an instance of PVGUI_Module class has been created
182 and \link PVGUI_Module::initialize() PVGUI_Module::initialize()\endlink method is called by SALOME GUI.
183 The actual client start-up is done in \link PVGUI_Module::pvInit() PVGUI_Module::pvInit()\endlink method.
186 <h3>Multi-view manager</h3>
188 SALOME GUI requires that each kind of view be implemnted with help of (at least) three classes. For ParaView multi-view manager
191 \li PVGUI_ViewManager - view manager class
192 \li PVGUI_Viewer - view model class
193 \li PVGUI_ViewWindow - view window class that acts as a parent for %pqViewManager
195 Single instances of PVGUI_ViewManager and PVGUI_ViewWindow classes are created by \link PVGUI_Module::showView()
196 PVGUI_Module::showView()\endlink method upon the first PARAVIS module activation. The same method hides the multi-view manager
197 when the module is deactivated (the user switches to another module or a study is closed).
198 A special trick is used to make PVGUI_ViewWindow the parent of %pqViewManager widget. It is created initally by %pqMainWindowCore
199 with the desktop as a parent, so when it is shown PVGUI_ViewWindow instance is passed to its setParent() method. In
200 \link PVGUI_ViewWindow::~PVGUI_ViewWindow() PVGUI_ViewWindow::~PVGUI_ViewWindow()\endlink the parent is nullified to avoid deletion
201 of %pqViewManager widget that would break %pqMainWindowCore class.
203 <h3>ParaView plugins</h3>
204 ParaView server and client plugins are managed by %pqMainWindowCore slots that has full access to PARAVIS menus and toolbars.
205 As a result they appears automatically in PARAVIS menus and toolbars if loaded successfully.
210 \brief Implementation
211 SALOME module wrapping ParaView GUI.
215 ClientFindOrCreateParavisComponent(_PTR(Study) theStudyDocument)
217 _PTR(SComponent) aSComponent = theStudyDocument->FindComponent("PVSERVER");
219 _PTR(StudyBuilder) aStudyBuilder = theStudyDocument->NewBuilder();
220 aStudyBuilder->NewCommand();
221 int aLocked = theStudyDocument->GetProperties()->IsLocked();
222 if (aLocked) theStudyDocument->GetProperties()->SetLocked(false);
223 aSComponent = aStudyBuilder->NewComponent("PVSERVER");
224 _PTR(GenericAttribute) anAttr =
225 aStudyBuilder->FindOrCreateAttribute(aSComponent, "AttributeName");
226 _PTR(AttributeName) aName (anAttr);
228 ORB_INIT& init = *SINGLETON_<ORB_INIT>::Instance();
229 CORBA::ORB_var anORB = init( qApp->argc(), qApp->argv() );
231 SALOME_NamingService *NamingService = new SALOME_NamingService( anORB );
232 CORBA::Object_var objVarN = NamingService->Resolve("/Kernel/ModulCatalog");
233 SALOME_ModuleCatalog::ModuleCatalog_var Catalogue =
234 SALOME_ModuleCatalog::ModuleCatalog::_narrow(objVarN);
235 SALOME_ModuleCatalog::Acomponent_var Comp = Catalogue->GetComponent( "PVSERVER" );
236 if (!Comp->_is_nil()) {
237 aName->SetValue(Comp->componentusername());
240 anAttr = aStudyBuilder->FindOrCreateAttribute(aSComponent, "AttributePixMap");
241 _PTR(AttributePixMap) aPixmap (anAttr);
242 aPixmap->SetPixMap( "pqAppIcon16.png" );
244 // Create Attribute parameters for future using
245 anAttr = aStudyBuilder->FindOrCreateAttribute(aSComponent, "AttributeParameter");
247 aStudyBuilder->DefineComponentInstance(aSComponent, PVGUI_Module::GetCPPEngine()->GetIOR());
248 if (aLocked) theStudyDocument->GetProperties()->SetLocked(true);
249 aStudyBuilder->CommitCommand();
255 Clean up function; used to stop ParaView progress events when
256 exception is caught by global exception handler.
258 void paravisCleanUp()
260 if ( pqApplicationCore::instance() ) {
261 pqServer* s = pqApplicationCore::instance()->getActiveServer();
262 if ( s ) s->session()->GetProgressHandler()->CleanupPendingProgress();
267 \brief Constructor. Sets the default name for the module.
269 PVGUI_Module::PVGUI_Module()
270 : SalomeApp_Module( PARAVIS_MODULE_NAME ),
271 mySelectionControlsTb( -1 ),
272 mySourcesMenuId( -1 ),
273 myFiltersMenuId( -1 ),
275 myToolbarsMenuId(-1),
285 Q_INIT_RESOURCE( PVGUI );
287 ParavisModule = this;
289 // Clear old copies of embedded macros files
290 QString aDestPath = QString( "%1/.config/%2/Macros" ).arg( QDir::homePath() ).arg( QApplication::applicationName() );
294 QDir aDestDir(aDestPath);
295 QStringList aDestFiles = aDestDir.entryList(aFilter, QDir::Files);
296 foreach (QString aMacrosPath, getEmbeddedMacrosList()) {
297 QString aMacrosName = QFileInfo(aMacrosPath).fileName();
298 if (aDestFiles.contains(aMacrosName)) {
299 aDestDir.remove(aMacrosName);
307 PVGUI_Module::~PVGUI_Module()
309 if (myPushTraceTimer)
310 delete myPushTraceTimer;
315 PVViewer_EngineWrapper * PVGUI_Module::GetEngine()
317 return PVViewer_EngineWrapper::GetInstance();
320 PVSERVER_ORB::PVSERVER_Gen_var PVGUI_Module::GetCPPEngine()
322 // initialize PARAVIS module engine (load, if necessary)
323 if ( CORBA::is_nil( MyEngine ) ) {
324 Engines::EngineComponent_var comp =
325 SalomeApp_Application::lcc()->FindOrLoad_Component( "FactoryServer", "PVSERVER" );
326 MyEngine = PVSERVER_ORB::PVSERVER_Gen::_narrow( comp );
332 \brief Create data model.
333 \return module specific data model
335 CAM_DataModel* PVGUI_Module::createDataModel()
337 return new PVGUI_DataModel( this );
340 pqPVApplicationCore * PVGUI_Module::GetPVApplication()
342 return PVViewer_ViewManager::GetPVApplication();
346 \brief Initialize module. Creates menus, prepares context menu, etc.
347 \param app SALOME GUI application instance
349 void PVGUI_Module::initialize( CAM_Application* app )
351 LightApp_Module::initialize( app );
356 // Uncomment to debug ParaView initialization
357 // "aa" used instead of "i" as GDB doesn't like "i" variables :)
365 LightApp_Application* anApp = getApp();
366 SUIT_Desktop* aDesktop = anApp->desktop();
368 // Initialize ParaView client and associated behaviors
369 // and connect to externally launched pvserver
370 PVViewer_ViewManager::ParaviewInitApp(aDesktop, anApp->logWindow());
371 myGuiElements = PVViewer_GUIElements::GetInstance(aDesktop);
373 // Remember current state of desktop toolbars
374 QList<QToolBar*> foreignToolbars = aDesktop->findChildren<QToolBar*>();
376 // [ABN]: careful with the order of the GUI element creation, the loading of the configuration
377 // and the connection to the server. This order is very sensitive if one wants to make
378 // sure all menus, etc ... are correctly populated.
379 // Reference points are: ParaViewMainWindow.cxx and branded_paraview_initializer.cxx.in
386 PVViewer_ViewManager::ParaviewInitBehaviors(true, aDesktop);
388 QList<QDockWidget*> activeDocks = aDesktop->findChildren<QDockWidget*>();
389 QList<QMenu*> activeMenus = aDesktop->findChildren<QMenu*>();
391 // Setup quick-launch shortcuts.
392 QShortcut *ctrlSpace = new QShortcut(Qt::CTRL + Qt::Key_Space, aDesktop);
393 QObject::connect(ctrlSpace, SIGNAL(activated()),
394 pqApplicationCore::instance(), SLOT(quickLaunch()));
396 // Find Plugin Dock Widgets
397 QList<QDockWidget*> currentDocks = aDesktop->findChildren<QDockWidget*>();
398 QList<QDockWidget*>::iterator i;
399 for (i = currentDocks.begin(); i != currentDocks.end(); ++i) {
400 if(!activeDocks.contains(*i)) {
401 myDockWidgets[*i] = false; // hidden by default
407 // [ABN] TODO: fix this - triggers a SEGFAULT at deactivation() time.
408 // QList<QMenu*> currentMenus = aDesktop->findChildren<QMenu*>();
409 // QList<QMenu*>::iterator im;
410 // for (im = currentMenus.begin(); im != currentMenus.end(); ++im) {
411 // if(!activeMenus.contains(*im)) {
412 // QString s = (*im)->title();
413 // std::cout << " MENU "<< s.toStdString() << std::endl;
414 // myMenus.append(*im);
418 // Connect after toolbar creation, etc ... as some activations of the toolbars is triggered
419 // by the ServerConnection event:
420 PVViewer_ViewManager::ParaviewLoadConfigurations(true);
421 PVViewer_ViewManager::ConnectToExternalPVServer(aDesktop);
424 // Find created toolbars
425 QCoreApplication::processEvents();
427 QList<QToolBar*> allToolbars = aDesktop->findChildren<QToolBar*>();
428 foreach(QToolBar* aBar, allToolbars) {
429 if (!foreignToolbars.contains(aBar)) {
430 myToolbars[aBar] = true;
431 myToolbarBreaks[aBar] = false;
432 aBar->setVisible(false);
433 aBar->toggleViewAction()->setVisible(false);
439 SUIT_ResourceMgr* aResourceMgr = SUIT_Session::session()->resourceMgr();
440 bool isStop = aResourceMgr->booleanValue( PARAVIS_MODULE_NAME, "stop_trace", false );
443 // Start a timer to schedule asap:
445 myInitTimer = new QTimer(aDesktop);
446 QObject::connect(myInitTimer, SIGNAL(timeout()), this, SLOT(onInitTimer()) );
447 myInitTimer->setSingleShot(true);
448 myInitTimer->start(0);
450 // Another timer to regularly push the trace onto the engine:
451 myPushTraceTimer = new QTimer(aDesktop);
452 QObject::connect(myPushTraceTimer, SIGNAL(timeout()), this, SLOT(onPushTraceTimer()) );
453 myPushTraceTimer->setSingleShot(false);
454 myPushTraceTimer->start(500);
457 this->VTKConnect = vtkEventQtSlotConnect::New();
459 vtkProcessModule* pm = vtkProcessModule::GetProcessModule();
461 vtkPVSession* pvs = dynamic_cast<vtkPVSession*>(pm->GetSession());
463 vtkPVProgressHandler* ph = pvs->GetProgressHandler();
465 this->VTKConnect->Connect(ph, vtkCommand::StartEvent,
466 this, SLOT(onStartProgress()));
467 this->VTKConnect->Connect(ph, vtkCommand::EndEvent,
468 this, SLOT(onEndProgress()));
474 void PVGUI_Module::onStartProgress()
476 QApplication::setOverrideCursor(Qt::WaitCursor);
479 void PVGUI_Module::onEndProgress()
481 QApplication::restoreOverrideCursor();
484 void PVGUI_Module::onDataRepresentationUpdated() {
485 SalomeApp_Study* activeStudy = dynamic_cast<SalomeApp_Study*>(application()->activeStudy());
486 if(!activeStudy) return;
488 activeStudy->Modified();
492 \brief Initialisation timer event - trace start up
494 void PVGUI_Module::onInitTimer()
500 \brief Get list of embedded macros files
502 QStringList PVGUI_Module::getEmbeddedMacrosList()
504 QString aRootDir = getenv("PARAVIS_ROOT_DIR");
506 QString aSourcePath = aRootDir + "/bin/salome/Macro";
511 QDir aSourceDir(aSourcePath);
512 QStringList aSourceFiles = aSourceDir.entryList(aFilter, QDir::Files);
513 QStringList aFullPathSourceFiles;
514 foreach (QString aMacrosName, aSourceFiles) {
515 aFullPathSourceFiles << aSourceDir.absoluteFilePath(aMacrosName);
517 return aFullPathSourceFiles;
520 void PVGUI_Module::updateMacros()
522 pqPythonManager* aPythonManager = pqPVApplicationCore::instance()->pythonManager();
523 if(!aPythonManager) {
527 foreach (QString aStr, getEmbeddedMacrosList()) {
528 aPythonManager->addMacro(aStr);
534 \brief Get list of compliant dockable GUI elements
535 \param m map to be filled in ("type":"default_position")
537 void PVGUI_Module::windows( QMap<int, int>& m ) const
539 m.insert( LightApp_Application::WT_ObjectBrowser, Qt::LeftDockWidgetArea );
540 m.insert( LightApp_Application::WT_PyConsole, Qt::BottomDockWidgetArea );
541 // ParaView diagnostic output redirected here
542 m.insert( LightApp_Application::WT_LogWindow, Qt::BottomDockWidgetArea );
546 \brief Shows (toShow = true) or hides ParaView view window
548 void PVGUI_Module::showView( bool toShow )
550 LightApp_Application* anApp = getApp();
551 PVViewer_ViewManager* viewMgr =
552 dynamic_cast<PVViewer_ViewManager*>( anApp->getViewManager( PVViewer_Viewer::Type(), false ) );
554 viewMgr = new PVViewer_ViewManager( anApp->activeStudy(), anApp->desktop(), anApp->logWindow() );
555 anApp->addViewManager( viewMgr );
556 connect( viewMgr, SIGNAL( lastViewClosed( SUIT_ViewManager* ) ),
557 anApp, SLOT( onCloseView( SUIT_ViewManager* ) ) );
560 PVViewer_ViewWindow* pvWnd = dynamic_cast<PVViewer_ViewWindow*>( viewMgr->getActiveView() );
562 pvWnd = dynamic_cast<PVViewer_ViewWindow*>( viewMgr->createViewWindow() );
563 // this also connects to the pvserver and instantiates relevant PV behaviors
566 pvWnd->setShown( toShow );
567 if ( toShow ) pvWnd->setFocus();
571 \brief Slot to show help for proxy.
573 void PVGUI_Module::showHelpForProxy( const QString& groupname, const QString& proxyname )
575 pqHelpReaction::showProxyHelp(groupname, proxyname);
580 \brief Slot to show the waiting state.
582 void PVGUI_Module::onPreAccept()
584 getApp()->desktop()->statusBar()->showMessage(tr("STB_PREACCEPT"));
585 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
589 \brief Slot to show the ready state.
591 void PVGUI_Module::onPostAccept()
593 getApp()->desktop()->statusBar()->showMessage(tr("STB_POSTACCEPT"), 2000);
594 QTimer::singleShot(0, this, SLOT(endWaitCursor()));
598 \brief Slot to switch off wait cursor.
600 void PVGUI_Module::endWaitCursor()
602 QApplication::restoreOverrideCursor();
605 static void ParavisMessageOutput(QtMsgType type, const char *msg)
610 vtkOutputWindow::GetInstance()->DisplayText(msg);
613 vtkOutputWindow::GetInstance()->DisplayErrorText(msg);
616 vtkOutputWindow::GetInstance()->DisplayErrorText(msg);
619 vtkOutputWindow::GetInstance()->DisplayErrorText(msg);
625 \brief Activate module.
626 \param study current study
627 \return \c true if activaion is done successfully or 0 to prevent
630 bool PVGUI_Module::activateModule( SUIT_Study* study )
632 myOldMsgHandler = qInstallMsgHandler(ParavisMessageOutput);
634 SUIT_ExceptionHandler::addCleanUpRoutine( paravisCleanUp );
636 storeCommonWindowsState();
638 bool isDone = LightApp_Module::activateModule( study );
639 if ( !isDone ) return false;
642 if ( mySourcesMenuId != -1 ) menuMgr()->show(mySourcesMenuId);
643 if ( myFiltersMenuId != -1 ) menuMgr()->show(myFiltersMenuId);
644 if ( myMacrosMenuId != -1 ) menuMgr()->show(myMacrosMenuId);
645 if ( myToolbarsMenuId != -1 ) menuMgr()->show(myToolbarsMenuId);
647 // Update the various menus with the content pre-loaded in myGuiElements
648 // QMenu* srcMenu = menuMgr()->findMenu( mySourcesMenuId );
649 // myGuiElements->updateSourcesMenu(srcMenu);
650 // QMenu* filtMenu = menuMgr()->findMenu( myFiltersMenuId );
651 // myGuiElements->updateFiltersMenu(filtMenu);
652 // QMenu* macMenu = menuMgr()->findMenu( myMacrosMenuId );
653 // myGuiElements->updateMacrosMenu(macMenu);
655 setMenuShown( true );
656 setToolShown( true );
658 restoreDockWidgetsState();
660 QMenu* aMenu = menuMgr()->findMenu( myRecentMenuId );
662 QList<QAction*> anActns = aMenu->actions();
663 for (int i = 0; i < anActns.size(); ++i) {
664 QAction* a = anActns.at(i);
670 QList<QMenu*>::iterator it;
671 for (it = myMenus.begin(); it != myMenus.end(); ++it) {
672 QAction* a = (*it)->menuAction();
677 if ( myRecentMenuId != -1 ) menuMgr()->show(myRecentMenuId);
679 ClientFindOrCreateParavisComponent(PARAVIS::GetCStudy(this));
686 \brief Deactivate module.
687 \param study current study
688 \return \c true if deactivaion is done successfully or 0 to prevent
689 deactivation on error
691 bool PVGUI_Module::deactivateModule( SUIT_Study* study )
693 MESSAGE("PARAVIS deactivation ...")
695 QMenu* aMenu = menuMgr()->findMenu( myRecentMenuId );
697 QList<QAction*> anActns = aMenu->actions();
698 for (int i = 0; i < anActns.size(); ++i) {
699 QAction* a = anActns.at(i);
701 a->setVisible(false);
705 QList<QMenu*>::iterator it;
706 for (it = myMenus.begin(); it != myMenus.end(); ++it) {
707 QAction* a = (*it)->menuAction();
709 a->setVisible(false);
712 QList<QDockWidget*> aStreamingViews = application()->desktop()->findChildren<QDockWidget*>("pqStreamingControls");
713 foreach(QDockWidget* aView, aStreamingViews) {
714 if (!myDockWidgets.contains(aView))
715 myDockWidgets[aView] = aView->isVisible();
718 /*if (pqImplementation::helpWindow) {
719 pqImplementation::helpWindow->hide();
723 menuMgr()->hide(myRecentMenuId);
724 menuMgr()->hide(mySourcesMenuId);
725 menuMgr()->hide(myFiltersMenuId);
726 menuMgr()->hide(myMacrosMenuId);
727 menuMgr()->hide(myToolbarsMenuId);
728 setMenuShown( false );
729 setToolShown( false );
731 saveDockWidgetsState();
733 SUIT_ExceptionHandler::removeCleanUpRoutine( paravisCleanUp );
736 qInstallMsgHandler(myOldMsgHandler);
738 restoreCommonWindowsState();
740 return LightApp_Module::deactivateModule( study );
745 \brief Called when application is closed.
747 Process finalize application functionality from ParaView in order to save server settings
748 and nullify application pointer if the application is being closed.
750 \param theApp application
752 void PVGUI_Module::onApplicationClosed( SUIT_Application* theApp )
754 PVViewer_ViewManager::ParaviewCleanup();
756 int aAppsNb = SUIT_Session::session()->applications().size();
758 deleteTemporaryFiles();
760 CAM_Module::onApplicationClosed(theApp);
765 \brief Deletes temporary files created during import operation from VISU
767 void PVGUI_Module::deleteTemporaryFiles()
769 foreach(QString aFile, myTemporaryFiles) {
770 if (QFile::exists(aFile)) {
771 QFile::remove(aFile);
778 \brief Called when study is closed.
780 Removes data model from the \a study.
782 \param study study being closed
784 void PVGUI_Module::studyClosed(SUIT_Study* study)
786 clearParaviewState();
788 LightApp_Module::studyClosed(study);
792 \brief Called when study is opened.
794 void PVGUI_Module::onModelOpened()
796 _PTR(Study) studyDS = PARAVIS::GetCStudy(this);
801 _PTR(SComponent) paravisComp =
802 studyDS->FindComponent(PARAVIS_MODULE_NAME);
807 _PTR(ChildIterator) anIter(studyDS->NewChildIterator(paravisComp));
808 for (; anIter->More(); anIter->Next()) {
809 _PTR(SObject) aSObj = anIter->Value();
810 _PTR(GenericAttribute) anAttr;
811 if (!aSObj->FindAttribute(anAttr, "AttributeLocalID")) {
814 _PTR(AttributeLocalID) anID(anAttr);
815 if (anID->Value() == PVSTATEID) {
822 \brief Returns IOR of current engine
824 QString PVGUI_Module::engineIOR() const
826 CORBA::String_var anIOR = GetCPPEngine()->GetIOR();
827 return QString(anIOR.in());
831 \brief Open file of format supported by ParaView
833 void PVGUI_Module::openFile(const char* theName)
837 pqLoadDataReaction::loadData(aFiles);
841 * Start trace invoking the newly introduced C++ API (PV 4.2)
842 * (inspired from pqTraceReaction::start())
844 void PVGUI_Module::startTrace()
846 vtkSMSessionProxyManager* pxm = pqActiveObjects::instance().activeServer()->proxyManager();
848 vtkSmartPointer<vtkSMProxy> proxy;
849 proxy.TakeReference(pxm->NewProxy("pythontracing", "PythonTraceOptions"));
852 vtkNew<vtkSMParaViewPipelineController> controller;
853 controller->InitializeProxy(proxy);
855 vtkSMTrace* trace = vtkSMTrace::StartTrace();
858 // Set manually the properties entered via the dialog box poping-up when requiring
859 // a trace start in PV4.2 (trace options)
860 trace->SetPropertiesToTraceOnCreate(vtkSMTrace::RECORD_USER_MODIFIED_PROPERTIES);
861 trace->SetFullyTraceSupplementalProxies(false);
865 void PVGUI_Module::stopTrace()
867 vtkSMTrace::StopTrace();
870 void PVGUI_Module::executeScript(const char *script)
873 pqPythonManager* manager = qobject_cast<pqPythonManager*>(
874 pqApplicationCore::instance()->manager("PYTHON_MANAGER"));
876 pqPythonDialog* pyDiag = manager->pythonShellDialog();
878 pyDiag->runString(script);
885 // * Debug function printing out the given interpreter's execution context
887 //void printInterpContext(PyInterp_Interp * interp )
889 // // Extract __smtraceString from interpreter's context
890 // const PyObject* ctxt = interp->getExecutionContext();
892 // PyObject* lst = PyDict_Keys((PyObject *)ctxt);
893 // Py_ssize_t siz = PyList_GET_SIZE(lst);
894 // for (Py_ssize_t i = 0; i < siz; i++)
896 // PyObject * elem = PyList_GetItem(lst, i);
897 // if (PyString_Check(elem))
899 // std::cout << "At pos:" << i << ", " << PyString_AsString(elem) << std::endl;
902 // std::cout << "At pos:" << i << ", not a string!" << std::endl;
908 \brief Returns trace string
910 static const QString MYReplaceStr("paraview.simple");
911 QString PVGUI_Module::getTraceString()
913 vtkSMTrace *tracer = vtkSMTrace::GetActiveTracer();
914 if (!tracer) // trace is not started
917 QString traceString(tracer->GetCurrentTrace());
918 std::stringstream nl; nl << std::endl; // surely there is some Qt trick to do that in a portable way??
919 QString end_line(nl.str().c_str());
920 // 'import pvsimple' is necessary to fix the first call to DisableFirstRenderCamera in the paraview trace
921 // 'ShowParaviewView()' ensure there is an opened viewing window (otherwise SEGFAULT!)
922 traceString = "import pvsimple" + end_line +
923 "pvsimple.ShowParaviewView()" + end_line + traceString;
925 // Replace import "paraview.simple" by "pvsimple"
926 if ((!traceString.isNull()) && traceString.length() != 0) {
927 int aPos = traceString.indexOf(MYReplaceStr);
929 traceString = traceString.replace(aPos, MYReplaceStr.length(), "pvsimple");
930 aPos = traceString.indexOf(MYReplaceStr, aPos);
938 \brief Saves trace string to disk file
940 void PVGUI_Module::saveTrace(const char* theName)
943 if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
944 MESSAGE( "Could not open file:" << theName );
947 QTextStream out(&file);
948 out << getTraceString();
953 \brief Saves ParaView state to a disk file
955 void PVGUI_Module::saveParaviewState(const char* theFileName)
957 pqApplicationCore::instance()->saveState(theFileName);
961 \brief Delete all objects for Paraview Pipeline Browser
963 void PVGUI_Module::clearParaviewState()
965 QAction* deleteAllAction = action(DeleteAllId);
966 if (deleteAllAction) {
967 deleteAllAction->activate(QAction::Trigger);
972 \brief Restores ParaView state from a disk file
974 If toClear == true, the current ojects will be deleted
976 void PVGUI_Module::loadParaviewState(const char* theFileName)
978 pqApplicationCore::instance()->loadState(theFileName, getActiveServer());
982 \brief Returns current active ParaView server
984 pqServer* PVGUI_Module::getActiveServer()
986 return pqApplicationCore::instance()->getActiveServer();
991 \brief Creates PARAVIS preference pane
993 void PVGUI_Module::createPreferences()
995 // Paraview settings tab
996 int aParaViewSettingsTab = addPreference( tr( "TIT_PVIEWSETTINGS" ) );
998 setPreferenceProperty(aParaViewSettingsTab, "stretch", false );
999 int aPanel = addPreference(QString(), aParaViewSettingsTab, LightApp_Preferences::UserDefined, PARAVIS_MODULE_NAME, "");
1001 setPreferenceProperty(aPanel, "content", (qint64)(new PVGUI_ParaViewSettingsPane(0, getApp())));
1003 // Paravis settings tab
1004 int aParaVisSettingsTab = addPreference( tr( "TIT_PVISSETTINGS" ) );
1005 addPreference( tr( "PREF_STOP_TRACE" ), aParaVisSettingsTab, LightApp_Preferences::Bool, PARAVIS_MODULE_NAME, "stop_trace");
1007 addPreference( tr( "PREF_NO_EXT_PVSERVER" ), aParaVisSettingsTab, LightApp_Preferences::Bool, PARAVIS_MODULE_NAME, "no_ext_pv_server");
1009 int aSaveType = addPreference(tr( "PREF_SAVE_TYPE_LBL" ), aParaVisSettingsTab,
1010 LightApp_Preferences::Selector,
1011 PARAVIS_MODULE_NAME, "savestate_type");
1012 QList<QVariant> aIndices;
1013 QStringList aStrings;
1015 aStrings<<tr("PREF_SAVE_TYPE_0");
1016 aStrings<<tr("PREF_SAVE_TYPE_1");
1017 aStrings<<tr("PREF_SAVE_TYPE_2");
1018 setPreferenceProperty(aSaveType, "strings", aStrings);
1019 setPreferenceProperty(aSaveType, "indexes", aIndices);
1023 \brief Creates ParaViS context menu popup
1025 void PVGUI_Module::contextMenuPopup(const QString& theClient, QMenu* theMenu, QString& theTitle)
1027 LightApp_Module::contextMenuPopup(theClient, theMenu, theTitle);
1029 // Check if we are in Object Browser
1030 SUIT_DataBrowser* ob = getApp()->objectBrowser();
1031 bool isOBClient = (ob && theClient == ob->popupClientType());
1036 // Get list of selected objects
1037 LightApp_SelectionMgr* aSelectionMgr = getApp()->selectionMgr();
1038 SALOME_ListIO aListIO;
1039 aSelectionMgr->selectedObjects(aListIO);
1040 if (aListIO.Extent() == 1 && aListIO.First()->hasEntry()) {
1041 QString entry = QString(aListIO.First()->getEntry());
1044 SalomeApp_Study* activeStudy =
1045 dynamic_cast<SalomeApp_Study*>(getApp()->activeStudy());
1050 // Get SALOMEDS client study
1051 _PTR(Study) studyDS = activeStudy->studyDS();
1056 QString paravisDataType(PARAVIS_MODULE_NAME);
1057 if(activeStudy && activeStudy->isComponent(entry) &&
1058 activeStudy->componentDataType(entry) == paravisDataType) {
1059 // ParaViS module object
1060 theMenu->addSeparator();
1061 theMenu->addAction(action(SaveStatePopupId));
1064 // Try to get state object
1065 _PTR(SObject) stateSObj =
1066 studyDS->FindObjectID(entry.toLatin1().constData());
1072 _PTR(GenericAttribute) anAttr;
1073 if (!stateSObj->FindAttribute(anAttr, "AttributeLocalID")) {
1077 _PTR(AttributeLocalID) anID(anAttr);
1079 if (anID->Value() == PVSTATEID) {
1080 // Paraview state object
1081 theMenu->addSeparator();
1082 theMenu->addAction(action(AddStatePopupId));
1083 theMenu->addAction(action(CleanAndAddStatePopupId));
1084 theMenu->addSeparator();
1085 theMenu->addAction(action(ParaVisRenameId));
1086 theMenu->addAction(action(ParaVisDeleteId));
1093 \brief. Show ParaView python trace.
1095 void PVGUI_Module::onShowTrace()
1097 if (!myTraceWindow) {
1098 myTraceWindow = new pqPythonScriptEditor(getApp()->desktop());
1100 myTraceWindow->setText(getTraceString());
1101 myTraceWindow->show();
1102 myTraceWindow->raise();
1103 myTraceWindow->activateWindow();
1108 \brief. Re-initialize ParaView python trace.
1110 void PVGUI_Module::onRestartTrace()
1117 \brief Save state under the module root object.
1119 void PVGUI_Module::onSaveMultiState()
1121 // Create state study object
1123 // Get SALOMEDS client study
1124 _PTR(Study) studyDS = PARAVIS::GetCStudy(this);
1129 _PTR(SComponent) paravisComp =
1130 studyDS->FindComponent(PARAVIS_MODULE_NAME);
1135 // Unlock the study if it is locked
1136 bool isLocked = studyDS->GetProperties()->IsLocked();
1138 studyDS->GetProperties()->SetLocked(false);
1141 QString stateName = tr("SAVED_PARAVIEW_STATE_NAME") +
1142 QString::number(myStateCounter + 1);
1144 _PTR(StudyBuilder) studyBuilder = studyDS->NewBuilder();
1145 _PTR(SObject) newSObj = studyBuilder->NewObject(paravisComp);
1148 _PTR(GenericAttribute) anAttr;
1149 anAttr = studyBuilder->FindOrCreateAttribute(newSObj, "AttributeName");
1150 _PTR(AttributeName) nameAttr(anAttr);
1152 nameAttr->SetValue(stateName.toLatin1().constData());
1155 anAttr = studyBuilder->FindOrCreateAttribute(newSObj, "AttributeLocalID");
1156 _PTR(AttributeLocalID) localIdAttr(anAttr);
1158 localIdAttr->SetValue(PVSTATEID);
1161 QString stateEntry = QString::fromStdString(newSObj->GetID());
1163 // File name for state saving
1164 QString tmpDir = QString::fromStdString(SALOMEDS_Tool::GetTmpDir());
1165 QString fileName = QString("%1_paravisstate:%2").arg(tmpDir, stateEntry);
1167 anAttr = studyBuilder->FindOrCreateAttribute(newSObj, "AttributeString");
1168 _PTR(AttributeString) stringAttr(anAttr);
1170 stringAttr->SetValue(fileName.toLatin1().constData());
1172 // Lock the study back if necessary
1174 studyDS->GetProperties()->SetLocked(true);
1178 saveParaviewState(fileName.toLatin1().constData());
1179 myTemporaryFiles.append(fileName);
1181 // Increment the counter
1188 \brief Restore the selected state by merging with the current one.
1190 void PVGUI_Module::onAddState()
1192 loadSelectedState(false);
1196 \brief Clean the current state and restore the selected one.
1198 void PVGUI_Module::onCleanAddState()
1200 loadSelectedState(true);
1204 \brief Rename the selected object.
1206 void PVGUI_Module::onRename()
1208 LightApp_SelectionMgr* aSelectionMgr = getApp()->selectionMgr();
1209 SALOME_ListIO aListIO;
1210 aSelectionMgr->selectedObjects(aListIO);
1212 if (aListIO.Extent() == 1 && aListIO.First()->hasEntry()) {
1213 std::string entry = aListIO.First()->getEntry();
1215 // Get SALOMEDS client study
1216 _PTR(Study) studyDS = PARAVIS::GetCStudy(this);
1221 // Unlock the study if it is locked
1222 bool isLocked = studyDS->GetProperties()->IsLocked();
1224 studyDS->GetProperties()->SetLocked(false);
1227 // Rename the selected state object
1228 _PTR(SObject) stateSObj = studyDS->FindObjectID(entry);
1233 _PTR(GenericAttribute) anAttr;
1234 if (stateSObj->FindAttribute(anAttr, "AttributeName")) {
1235 _PTR(AttributeName) nameAttr (anAttr);
1237 LightApp_NameDlg::getName(getApp()->desktop(), nameAttr->Value().c_str());
1238 if (!newName.isEmpty()) {
1239 nameAttr->SetValue(newName.toLatin1().constData());
1240 aListIO.First()->setName(newName.toLatin1().constData());
1244 // Lock the study back if necessary
1246 studyDS->GetProperties()->SetLocked(true);
1249 // Update object browser
1256 \brief Delete the selected objects.
1258 void PVGUI_Module::onDelete()
1260 LightApp_SelectionMgr* aSelectionMgr = getApp()->selectionMgr();
1261 SALOME_ListIO aListIO;
1262 aSelectionMgr->selectedObjects(aListIO);
1264 if (aListIO.Extent() == 1 && aListIO.First()->hasEntry()) {
1265 std::string entry = aListIO.First()->getEntry();
1267 // Get SALOMEDS client study
1268 _PTR(Study) studyDS = PARAVIS::GetCStudy(this);
1273 // Unlock the study if it is locked
1274 bool isLocked = studyDS->GetProperties()->IsLocked();
1276 studyDS->GetProperties()->SetLocked(false);
1279 // Remove the selected state from the study
1280 _PTR(StudyBuilder) studyBuilder = studyDS->NewBuilder();
1281 _PTR(SObject) stateSObj = studyDS->FindObjectID(entry);
1282 studyBuilder->RemoveObject(stateSObj);
1284 // Lock the study back if necessary
1286 studyDS->GetProperties()->SetLocked(true);
1289 // Update object browser
1294 void PVGUI_Module::onPushTraceTimer()
1296 //MESSAGE("onPushTraceTimer(): Pushing trace to engine...");
1297 GetEngine()->PutPythonTraceStringToEngine(getTraceString().toStdString().c_str());
1301 \brief Discover help project files from the resources.
1302 \return name of the help file.
1304 QString PVGUI_Module::getHelpFileName() {
1305 QString aPVHome(getenv("PVHOME"));
1306 if (aPVHome.isNull()) {
1307 qWarning("Wariable PVHOME is not defined");
1310 QChar aSep = QDir::separator();
1311 //PARAVIEW_VERSION from the vtkPVConfig.h file
1312 QString aFileName = aPVHome + aSep + "share" + aSep + "doc" + aSep + "paraview-"+ PARAVIEW_VERSION + aSep + "paraview.qch";
1318 \brief Load selected paraview state
1320 If toClear == true, the current state will be cleared
1322 void PVGUI_Module::loadSelectedState(bool toClear)
1326 LightApp_SelectionMgr* aSelectionMgr = getApp()->selectionMgr();
1327 SALOME_ListIO aListIO;
1328 aSelectionMgr->selectedObjects(aListIO);
1330 if (aListIO.Extent() == 1 && aListIO.First()->hasEntry()) {
1331 std::string entry = aListIO.First()->getEntry();
1333 // Get SALOMEDS client study
1334 _PTR(Study) studyDS = PARAVIS::GetCStudy(this);
1340 _PTR(SObject) stateSObj = studyDS->FindObjectID(entry);
1341 _PTR(GenericAttribute) anAttr;
1342 if (!stateSObj->FindAttribute(anAttr, "AttributeLocalID")) {
1345 _PTR(AttributeLocalID) anID(anAttr);
1346 if (!anID->Value() == PVSTATEID) {
1350 // Get state file name
1351 if (stateSObj->FindAttribute(anAttr, "AttributeString")) {
1352 _PTR(AttributeString) aStringAttr(anAttr);
1353 QString stringValue(aStringAttr->Value().c_str());
1355 if (QFile::exists(stringValue)) {
1356 fileName = stringValue;
1361 if (!fileName.isEmpty()) {
1363 clearParaviewState();
1366 loadParaviewState(fileName.toLatin1().constData());
1369 SUIT_MessageBox::critical(getApp()->desktop(),
1371 tr("ERR_STATE_CANNOT_BE_RESTORED"));
1376 \fn CAM_Module* createModule();
1377 \brief Export module instance (factory function).
1378 \return new created instance of the module
1382 #define PVGUI_EXPORT __declspec(dllexport)
1384 #define PVGUI_EXPORT
1390 PVGUI_EXPORT CAM_Module* createModule() {
1391 return new PVGUI_Module();
1394 PVGUI_EXPORT char* getModuleVersion() {
1395 return (char*)PARAVIS_VERSION_STR;