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 #include <Standard_math.hxx> // E.A. must be included before Python.h to fix compilation on windows
25 #undef HAVE_FINITE // VSR: avoid compilation warning on Linux : "HAVE_FINITE" redefined
27 #include <vtkPython.h> // Python first
28 #include "PVGUI_Module.h"
30 #ifdef PARAVIS_WITH_FULL_CORBA
31 # include "PARAVIS_Gen_i.hh"
34 #include CORBA_SERVER_HEADER(SALOME_ModuleCatalog)
35 #include CORBA_SERVER_HEADER(SALOMEDS)
37 #include "PVViewer_ViewManager.h"
38 #include "PVViewer_ViewWindow.h"
39 #include "PVViewer_ViewModel.h"
40 #include "PVGUI_Tools.h"
41 #include "PVGUI_ParaViewSettingsPane.h"
42 #include "PVViewer_GUIElements.h"
43 #include "PVViewer_EngineWrapper.h"
46 #include <SUIT_DataBrowser.h>
47 #include <SUIT_Desktop.h>
48 #include <SUIT_MessageBox.h>
49 #include <SUIT_ResourceMgr.h>
50 #include <SUIT_Session.h>
51 #include <SUIT_OverrideCursor.h>
52 #include <SUIT_ExceptionHandler.h>
54 #include <SALOME_LifeCycleCORBA.hxx>
55 #include <SALOMEDS_SObject.hxx>
57 #include <LightApp_SelectionMgr.h>
58 #include <LightApp_NameDlg.h>
59 #include <SalomeApp_Application.h>
60 #include <SalomeApp_Study.h>
61 #include <SALOME_ListIO.hxx>
62 #include <SALOMEDS_Tool.hxx>
63 #include <Utils_ORB_INIT.hxx>
64 #include <Utils_SINGLETON.hxx>
66 #include <QtxActionMenuMgr.h>
67 #include <QtxActionToolMgr.h>
69 #include <PARAVIS_version.h>
75 #include <QApplication>
81 #include <QInputDialog>
85 #include <QStringList>
88 #include <QTextStream>
90 #include <QDockWidget>
91 #include <QHelpEngine>
94 #include <vtkPVConfig.h> // for symbol PARAVIEW_VERSION
95 #include <vtkProcessModule.h>
96 #include <vtkPVSession.h>
97 #include <vtkPVProgressHandler.h>
98 #include <vtkOutputWindow.h>
99 #include <vtkEventQtSlotConnect.h>
101 #include <vtkSMProxy.h>
102 #include <vtkSmartPointer.h>
103 #include <vtkSMSession.h>
104 #include <vtkSMTrace.h>
105 #include <vtkSMSessionProxyManager.h>
106 #include <vtkSMParaViewPipelineController.h>
108 #include <pqApplicationCore.h>
109 #include <pqPVApplicationCore.h>
110 #include <pqActiveView.h>
111 #include <pqObjectBuilder.h>
112 #include <pqOptions.h>
113 #include <pqSettings.h>
114 #include <pqServer.h>
115 #include <pqUndoStack.h>
116 #include <pqTabbedMultiViewWidget.h>
117 #include <pqActiveObjects.h>
118 #include <pqHelpReaction.h>
119 #include <pqPluginManager.h>
120 #include <pqPythonDialog.h>
121 #include <pqPythonManager.h>
122 #include <pqLoadDataReaction.h>
123 #include <pqPythonScriptEditor.h>
124 #include <pqDataRepresentation.h>
125 #include <pqDisplayColorWidget.h>
126 #include <pqColorToolbar.h>
127 #include <pqScalarBarVisibilityReaction.h>
128 #include <pqServerResource.h>
129 #include <pqServerConnectReaction.h>
132 #include <PyInterp_Interp.h>
135 //----------------------------------------------------------------------------
136 PVGUI_Module* ParavisModule = 0;
137 PARAVIS_ORB::PARAVIS_Gen_var PVGUI_Module::MyEngine;
142 <h2>Building and installing PARAVIS</h2>
143 As any other SALOME module, PARAVIS requires PARAVIS_ROOT_DIR environment variable to be set to PARAVIS
144 installation directory.
145 Other variables needed for correct detection of ParaView location:
146 \li PVHOME - points at the ParaView installation directory tree
147 \li PVVERSION - number of ParaView version
149 It also requires common SALOME environment including GUI_ROOT_DIR and other prerequsites.
152 PARAVIS module can be launched using the following commands:
153 \li Full SALOME configuration
155 runSalome --modules="PARAVIS"
158 <h2>ParaView GUI integration</h2>
159 <h3>ParaView GUI integration overview</h3>
161 The main idea is to reuse ParaView GUI internal logic as much as possible, providing a layer
162 between it and SALOME GUI that hides the following SALOME GUI implementation details from ParaView:
164 \li SALOME GUI executable and Qt event loop
165 \li SALOME GUI desktop
166 \li Dock windows areas
167 \li SALOME menu and toolbar managers
169 Major part of the integration is implemented in PVGUI_Module class.
171 <h3>ParaView client initalization</h3>
173 ParaView client initalization is performed when an instance of PVGUI_Module class has been created
174 and \link PVGUI_Module::initialize() PVGUI_Module::initialize()\endlink method is called by SALOME GUI.
175 The actual client start-up is done in \link PVGUI_Module::pvInit() PVGUI_Module::pvInit()\endlink method.
178 <h3>Multi-view manager</h3>
180 SALOME GUI requires that each kind of view be implemnted with help of (at least) three classes. For ParaView multi-view manager
183 \li PVGUI_ViewManager - view manager class
184 \li PVGUI_Viewer - view model class
185 \li PVGUI_ViewWindow - view window class that acts as a parent for %pqViewManager
187 Single instances of PVGUI_ViewManager and PVGUI_ViewWindow classes are created by \link PVGUI_Module::showView()
188 PVGUI_Module::showView()\endlink method upon the first PARAVIS module activation. The same method hides the multi-view manager
189 when the module is deactivated (the user switches to another module or a study is closed).
190 A special trick is used to make PVGUI_ViewWindow the parent of %pqViewManager widget. It is created initally by %pqMainWindowCore
191 with the desktop as a parent, so when it is shown PVGUI_ViewWindow instance is passed to its setParent() method. In
192 \link PVGUI_ViewWindow::~PVGUI_ViewWindow() PVGUI_ViewWindow::~PVGUI_ViewWindow()\endlink the parent is nullified to avoid deletion
193 of %pqViewManager widget that would break %pqMainWindowCore class.
195 <h3>ParaView plugins</h3>
196 ParaView server and client plugins are managed by %pqMainWindowCore slots that has full access to PARAVIS menus and toolbars.
197 As a result they appears automatically in PARAVIS menus and toolbars if loaded successfully.
202 \brief Implementation
203 SALOME module wrapping ParaView GUI.
207 ClientFindOrCreateParavisComponent(_PTR(Study) theStudyDocument)
209 _PTR(SComponent) aSComponent = theStudyDocument->FindComponent("PARAVIS");
211 _PTR(StudyBuilder) aStudyBuilder = theStudyDocument->NewBuilder();
212 aStudyBuilder->NewCommand();
213 int aLocked = theStudyDocument->GetProperties()->IsLocked();
214 if (aLocked) theStudyDocument->GetProperties()->SetLocked(false);
215 aSComponent = aStudyBuilder->NewComponent("PARAVIS");
216 _PTR(GenericAttribute) anAttr =
217 aStudyBuilder->FindOrCreateAttribute(aSComponent, "AttributeName");
218 _PTR(AttributeName) aName (anAttr);
220 ORB_INIT& init = *SINGLETON_<ORB_INIT>::Instance();
221 CORBA::ORB_var anORB = init( qApp->argc(), qApp->argv() );
223 SALOME_NamingService *NamingService = new SALOME_NamingService( anORB );
224 CORBA::Object_var objVarN = NamingService->Resolve("/Kernel/ModulCatalog");
225 SALOME_ModuleCatalog::ModuleCatalog_var Catalogue =
226 SALOME_ModuleCatalog::ModuleCatalog::_narrow(objVarN);
227 SALOME_ModuleCatalog::Acomponent_var Comp = Catalogue->GetComponent( "PARAVIS" );
228 if (!Comp->_is_nil()) {
229 aName->SetValue(Comp->componentusername());
232 anAttr = aStudyBuilder->FindOrCreateAttribute(aSComponent, "AttributePixMap");
233 _PTR(AttributePixMap) aPixmap (anAttr);
234 aPixmap->SetPixMap( "pqAppIcon16.png" );
236 // Create Attribute parameters for future using
237 anAttr = aStudyBuilder->FindOrCreateAttribute(aSComponent, "AttributeParameter");
239 aStudyBuilder->DefineComponentInstance(aSComponent, PVGUI_Module::GetCPPEngine()->GetIOR());
240 if (aLocked) theStudyDocument->GetProperties()->SetLocked(true);
241 aStudyBuilder->CommitCommand();
247 Clean up function; used to stop ParaView progress events when
248 exception is caught by global exception handler.
250 void paravisCleanUp()
252 if ( pqApplicationCore::instance() ) {
253 pqServer* s = pqApplicationCore::instance()->getActiveServer();
254 if ( s ) s->session()->GetProgressHandler()->CleanupPendingProgress();
259 \brief Constructor. Sets the default name for the module.
261 PVGUI_Module::PVGUI_Module()
262 : SalomeApp_Module( "PARAVIS" ),
263 mySelectionControlsTb( -1 ),
264 mySourcesMenuId( -1 ),
265 myFiltersMenuId( -1 ),
267 myToolbarsMenuId(-1),
277 Q_INIT_RESOURCE( PVGUI );
279 ParavisModule = this;
281 // Clear old copies of embedded macros files
282 QString aDestPath = QString( "%1/.config/%2/Macros" ).arg( QDir::homePath() ).arg( QApplication::applicationName() );
286 QDir aDestDir(aDestPath);
287 QStringList aDestFiles = aDestDir.entryList(aFilter, QDir::Files);
288 foreach (QString aMacrosPath, getEmbeddedMacrosList()) {
289 QString aMacrosName = QFileInfo(aMacrosPath).fileName();
290 if (aDestFiles.contains(aMacrosName)) {
291 aDestDir.remove(aMacrosName);
299 PVGUI_Module::~PVGUI_Module()
301 if (myPushTraceTimer)
302 delete myPushTraceTimer;
307 PARAVIS_ORB::PARAVIS_Gen_var PVGUI_Module::GetCPPEngine()
309 // initialize PARAVIS module engine (load, if necessary)
310 if ( CORBA::is_nil( MyEngine ) ) {
311 Engines::EngineComponent_var comp =
312 SalomeApp_Application::lcc()->FindOrLoad_Component( "FactoryServer", "PARAVIS" );
313 MyEngine = PARAVIS_ORB::PARAVIS_Gen::_narrow( comp );
319 pqPVApplicationCore * PVGUI_Module::GetPVApplication()
321 return PVViewer_ViewManager::GetPVApplication();
325 \brief Initialize module. Creates menus, prepares context menu, etc.
326 \param app SALOME GUI application instance
328 void PVGUI_Module::initialize( CAM_Application* app )
330 SalomeApp_Module::initialize( app );
332 // Create ParaViS actions
334 // Create ParaViS menus
337 // Uncomment to debug ParaView initialization
338 // "aa" used instead of "i" as GDB doesn't like "i" variables :)
346 SalomeApp_Application* anApp = getApp();
347 SUIT_Desktop* aDesktop = anApp->desktop();
349 // Initialize ParaView client and associated behaviors
350 // and connect to externally launched pvserver
351 PVViewer_ViewManager::ParaviewInitApp(aDesktop);
352 myGuiElements = PVViewer_GUIElements::GetInstance(aDesktop);
354 // Remember current state of desktop toolbars
355 QList<QToolBar*> foreignToolbars = aDesktop->findChildren<QToolBar*>();
359 // Behaviors and connection must be instanciated *after* widgets are in place
360 // In PARAVIS module we do not wait for PVViewer_ViewWindow to be instanciated to have this:
361 PVViewer_ViewManager::ParaviewInitBehaviors(true, aDesktop);
362 PVViewer_ViewManager::ConnectToExternalPVServer(aDesktop);
368 QList<QDockWidget*> activeDocks = aDesktop->findChildren<QDockWidget*>();
369 QList<QMenu*> activeMenus = aDesktop->findChildren<QMenu*>();
371 // Setup quick-launch shortcuts.
372 QShortcut *ctrlSpace = new QShortcut(Qt::CTRL + Qt::Key_Space, aDesktop);
373 QObject::connect(ctrlSpace, SIGNAL(activated()),
374 pqApplicationCore::instance(), SLOT(quickLaunch()));
376 // Find Plugin Dock Widgets
377 QList<QDockWidget*> currentDocks = aDesktop->findChildren<QDockWidget*>();
378 QList<QDockWidget*>::iterator i;
379 for (i = currentDocks.begin(); i != currentDocks.end(); ++i) {
380 if(!activeDocks.contains(*i)) {
381 myDockWidgets[*i] = false; // hidden by default
387 // [ABN] TODO: fix this - triggers a SEGFAULT at deactivation() time.
388 // QList<QMenu*> currentMenus = aDesktop->findChildren<QMenu*>();
389 // QList<QMenu*>::iterator im;
390 // for (im = currentMenus.begin(); im != currentMenus.end(); ++im) {
391 // if(!activeMenus.contains(*im)) {
392 // QString s = (*im)->title();
393 // std::cout << " MENU "<< s.toStdString() << std::endl;
394 // myMenus.append(*im);
398 PVViewer_ViewManager::ParaviewLoadConfigurations();
401 // Find created toolbars
402 QCoreApplication::processEvents();
404 QList<QToolBar*> allToolbars = aDesktop->findChildren<QToolBar*>();
405 foreach(QToolBar* aBar, allToolbars) {
406 if (!foreignToolbars.contains(aBar)) {
407 myToolbars[aBar] = true;
408 myToolbarBreaks[aBar] = false;
409 aBar->setVisible(false);
410 aBar->toggleViewAction()->setVisible(false);
416 SUIT_ResourceMgr* aResourceMgr = SUIT_Session::session()->resourceMgr();
417 bool isStop = aResourceMgr->booleanValue( "PARAVIS", "stop_trace", false );
420 // Start a timer to schedule asap:
422 myInitTimer = new QTimer(aDesktop);
423 QObject::connect(myInitTimer, SIGNAL(timeout()), this, SLOT(onInitTimer()) );
424 myInitTimer->setSingleShot(true);
425 myInitTimer->start(0);
427 // Another timer to regularly push the trace onto the engine:
428 myPushTraceTimer = new QTimer(aDesktop);
429 QObject::connect(myPushTraceTimer, SIGNAL(timeout()), this, SLOT(onPushTraceTimer()) );
430 myPushTraceTimer->setSingleShot(false);
431 myPushTraceTimer->start(500);
434 this->VTKConnect = vtkEventQtSlotConnect::New();
436 vtkProcessModule* pm = vtkProcessModule::GetProcessModule();
438 vtkPVSession* pvs = dynamic_cast<vtkPVSession*>(pm->GetSession());
440 vtkPVProgressHandler* ph = pvs->GetProgressHandler();
442 this->VTKConnect->Connect(ph, vtkCommand::StartEvent,
443 this, SLOT(onStartProgress()));
444 this->VTKConnect->Connect(ph, vtkCommand::EndEvent,
445 this, SLOT(onEndProgress()));
451 void PVGUI_Module::onStartProgress()
453 QApplication::setOverrideCursor(Qt::WaitCursor);
456 void PVGUI_Module::onEndProgress()
458 QApplication::restoreOverrideCursor();
461 void PVGUI_Module::onDataRepresentationUpdated() {
462 SalomeApp_Study* activeStudy = dynamic_cast<SalomeApp_Study*>(application()->activeStudy());
463 if(!activeStudy) return;
465 activeStudy->Modified();
469 \brief Initialisation timer event - trace start up
471 void PVGUI_Module::onInitTimer()
477 \brief Get list of embedded macros files
479 QStringList PVGUI_Module::getEmbeddedMacrosList()
481 QString aRootDir = getenv("PARAVIS_ROOT_DIR");
483 QString aSourcePath = aRootDir + "/bin/salome/Macro";
488 QDir aSourceDir(aSourcePath);
489 QStringList aSourceFiles = aSourceDir.entryList(aFilter, QDir::Files);
490 QStringList aFullPathSourceFiles;
491 foreach (QString aMacrosName, aSourceFiles) {
492 aFullPathSourceFiles << aSourceDir.absoluteFilePath(aMacrosName);
494 return aFullPathSourceFiles;
497 void PVGUI_Module::updateMacros()
499 pqPythonManager* aPythonManager = pqPVApplicationCore::instance()->pythonManager();
500 if(!aPythonManager) {
504 foreach (QString aStr, getEmbeddedMacrosList()) {
505 aPythonManager->addMacro(aStr);
511 \brief Get list of compliant dockable GUI elements
512 \param m map to be filled in ("type":"default_position")
514 void PVGUI_Module::windows( QMap<int, int>& m ) const
516 m.insert( LightApp_Application::WT_ObjectBrowser, Qt::LeftDockWidgetArea );
517 m.insert( LightApp_Application::WT_PyConsole, Qt::BottomDockWidgetArea );
518 // ParaView diagnostic output redirected here
519 m.insert( LightApp_Application::WT_LogWindow, Qt::BottomDockWidgetArea );
523 \brief Shows (toShow = true) or hides ParaView view window
525 void PVGUI_Module::showView( bool toShow )
527 SalomeApp_Application* anApp = getApp();
528 PVViewer_ViewManager* viewMgr =
529 dynamic_cast<PVViewer_ViewManager*>( anApp->getViewManager( PVViewer_Viewer::Type(), false ) );
531 viewMgr = new PVViewer_ViewManager( anApp->activeStudy(), anApp->desktop() );
532 anApp->addViewManager( viewMgr );
533 connect( viewMgr, SIGNAL( lastViewClosed( SUIT_ViewManager* ) ),
534 anApp, SLOT( onCloseView( SUIT_ViewManager* ) ) );
537 PVViewer_ViewWindow* pvWnd = dynamic_cast<PVViewer_ViewWindow*>( viewMgr->getActiveView() );
539 pvWnd = dynamic_cast<PVViewer_ViewWindow*>( viewMgr->createViewWindow() );
540 // this also connects to the pvserver and instantiates relevant PV behaviors
543 pvWnd->setShown( toShow );
544 if ( toShow ) pvWnd->setFocus();
548 \brief Slot to show help for proxy.
550 void PVGUI_Module::showHelpForProxy( const QString& groupname, const QString& proxyname )
552 pqHelpReaction::showProxyHelp(groupname, proxyname);
557 \brief Slot to show the waiting state.
559 void PVGUI_Module::onPreAccept()
561 getApp()->desktop()->statusBar()->showMessage(tr("STB_PREACCEPT"));
562 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
566 \brief Slot to show the ready state.
568 void PVGUI_Module::onPostAccept()
570 getApp()->desktop()->statusBar()->showMessage(tr("STB_POSTACCEPT"), 2000);
571 QTimer::singleShot(0, this, SLOT(endWaitCursor()));
575 \brief Slot to switch off wait cursor.
577 void PVGUI_Module::endWaitCursor()
579 QApplication::restoreOverrideCursor();
582 static void ParavisMessageOutput(QtMsgType type, const char *msg)
587 vtkOutputWindow::GetInstance()->DisplayText(msg);
590 vtkOutputWindow::GetInstance()->DisplayErrorText(msg);
593 vtkOutputWindow::GetInstance()->DisplayErrorText(msg);
596 vtkOutputWindow::GetInstance()->DisplayErrorText(msg);
602 \brief Activate module.
603 \param study current study
604 \return \c true if activaion is done successfully or 0 to prevent
607 bool PVGUI_Module::activateModule( SUIT_Study* study )
609 myOldMsgHandler = qInstallMsgHandler(ParavisMessageOutput);
611 SUIT_ExceptionHandler::addCleanUpRoutine( paravisCleanUp );
613 storeCommonWindowsState();
615 bool isDone = SalomeApp_Module::activateModule( study );
616 if ( !isDone ) return false;
619 if ( mySourcesMenuId != -1 ) menuMgr()->show(mySourcesMenuId);
620 if ( myFiltersMenuId != -1 ) menuMgr()->show(myFiltersMenuId);
621 if ( myMacrosMenuId != -1 ) menuMgr()->show(myMacrosMenuId);
622 if ( myToolbarsMenuId != -1 ) menuMgr()->show(myToolbarsMenuId);
624 // Update the various menus with the content pre-loaded in myGuiElements
625 QMenu* srcMenu = menuMgr()->findMenu( mySourcesMenuId );
626 myGuiElements->updateSourcesMenu(srcMenu);
627 QMenu* filtMenu = menuMgr()->findMenu( myFiltersMenuId );
628 myGuiElements->updateFiltersMenu(filtMenu);
629 QMenu* macMenu = menuMgr()->findMenu( myMacrosMenuId );
630 myGuiElements->updateMacrosMenu(macMenu);
632 setMenuShown( true );
633 setToolShown( true );
635 restoreDockWidgetsState();
637 QMenu* aMenu = menuMgr()->findMenu( myRecentMenuId );
639 QList<QAction*> anActns = aMenu->actions();
640 for (int i = 0; i < anActns.size(); ++i) {
641 QAction* a = anActns.at(i);
647 QList<QMenu*>::iterator it;
648 for (it = myMenus.begin(); it != myMenus.end(); ++it) {
649 QAction* a = (*it)->menuAction();
654 if ( myRecentMenuId != -1 ) menuMgr()->show(myRecentMenuId);
656 ClientFindOrCreateParavisComponent(PARAVIS::GetCStudy(this));
663 \brief Deactivate module.
664 \param study current study
665 \return \c true if deactivaion is done successfully or 0 to prevent
666 deactivation on error
668 bool PVGUI_Module::deactivateModule( SUIT_Study* study )
670 MESSAGE("PARAVIS deactivation ...")
672 QMenu* aMenu = menuMgr()->findMenu( myRecentMenuId );
674 QList<QAction*> anActns = aMenu->actions();
675 for (int i = 0; i < anActns.size(); ++i) {
676 QAction* a = anActns.at(i);
678 a->setVisible(false);
682 QList<QMenu*>::iterator it;
683 for (it = myMenus.begin(); it != myMenus.end(); ++it) {
684 QAction* a = (*it)->menuAction();
686 a->setVisible(false);
689 QList<QDockWidget*> aStreamingViews = application()->desktop()->findChildren<QDockWidget*>("pqStreamingControls");
690 foreach(QDockWidget* aView, aStreamingViews) {
691 if (!myDockWidgets.contains(aView))
692 myDockWidgets[aView] = aView->isVisible();
695 /*if (pqImplementation::helpWindow) {
696 pqImplementation::helpWindow->hide();
700 menuMgr()->hide(myRecentMenuId);
701 menuMgr()->hide(mySourcesMenuId);
702 menuMgr()->hide(myFiltersMenuId);
703 menuMgr()->hide(myMacrosMenuId);
704 menuMgr()->hide(myToolbarsMenuId);
705 setMenuShown( false );
706 setToolShown( false );
708 saveDockWidgetsState();
710 SUIT_ExceptionHandler::removeCleanUpRoutine( paravisCleanUp );
713 qInstallMsgHandler(myOldMsgHandler);
715 restoreCommonWindowsState();
717 return SalomeApp_Module::deactivateModule( study );
722 \brief Called when application is closed.
724 Process finalize application functionality from ParaView in order to save server settings
725 and nullify application pointer if the application is being closed.
727 \param theApp application
729 void PVGUI_Module::onApplicationClosed( SUIT_Application* theApp )
731 PVViewer_ViewManager::ParaviewCleanup();
733 int aAppsNb = SUIT_Session::session()->applications().size();
735 deleteTemporaryFiles();
737 CAM_Module::onApplicationClosed(theApp);
742 \brief Deletes temporary files created during import operation from VISU
744 void PVGUI_Module::deleteTemporaryFiles()
746 foreach(QString aFile, myTemporaryFiles) {
747 if (QFile::exists(aFile)) {
748 QFile::remove(aFile);
755 \brief Called when study is closed.
757 Removes data model from the \a study.
759 \param study study being closed
761 void PVGUI_Module::studyClosed(SUIT_Study* study)
763 clearParaviewState();
765 SalomeApp_Module::studyClosed(study);
769 \brief Called when study is opened.
771 void PVGUI_Module::onModelOpened()
773 _PTR(Study) studyDS = PARAVIS::GetCStudy(this);
778 _PTR(SComponent) paravisComp =
779 studyDS->FindComponent(GetCPPEngine()->ComponentDataType());
784 _PTR(ChildIterator) anIter(studyDS->NewChildIterator(paravisComp));
785 for (; anIter->More(); anIter->Next()) {
786 _PTR(SObject) aSObj = anIter->Value();
787 _PTR(GenericAttribute) anAttr;
788 if (!aSObj->FindAttribute(anAttr, "AttributeLocalID")) {
791 _PTR(AttributeLocalID) anID(anAttr);
792 if (anID->Value() == PVSTATEID) {
799 \brief Returns IOR of current engine
801 QString PVGUI_Module::engineIOR() const
803 CORBA::String_var anIOR = GetCPPEngine()->GetIOR();
804 return QString(anIOR.in());
808 \brief Open file of format supported by ParaView
810 void PVGUI_Module::openFile(const char* theName)
814 pqLoadDataReaction::loadData(aFiles);
818 * Start trace invoking the newly introduced C++ API (PV 4.2)
819 * (inspired from pqTraceReaction::start())
821 void PVGUI_Module::startTrace()
823 vtkSMSessionProxyManager* pxm = pqActiveObjects::instance().activeServer()->proxyManager();
825 vtkSmartPointer<vtkSMProxy> proxy;
826 proxy.TakeReference(pxm->NewProxy("pythontracing", "PythonTraceOptions"));
829 vtkNew<vtkSMParaViewPipelineController> controller;
830 controller->InitializeProxy(proxy);
832 vtkSMTrace* trace = vtkSMTrace::StartTrace();
835 // Set manually the properties entered via the dialog box poping-up when requiring
836 // a trace start in PV4.2 (trace options)
837 trace->SetPropertiesToTraceOnCreate(vtkSMTrace::RECORD_USER_MODIFIED_PROPERTIES);
838 trace->SetFullyTraceSupplementalProxies(false);
842 void PVGUI_Module::stopTrace()
844 vtkSMTrace::StopTrace();
847 void PVGUI_Module::executeScript(const char *script)
850 pqPythonManager* manager = qobject_cast<pqPythonManager*>(
851 pqApplicationCore::instance()->manager("PYTHON_MANAGER"));
853 pqPythonDialog* pyDiag = manager->pythonShellDialog();
855 pyDiag->runString(script);
862 // * Debug function printing out the given interpreter's execution context
864 //void printInterpContext(PyInterp_Interp * interp )
866 // // Extract __smtraceString from interpreter's context
867 // const PyObject* ctxt = interp->getExecutionContext();
869 // PyObject* lst = PyDict_Keys((PyObject *)ctxt);
870 // Py_ssize_t siz = PyList_GET_SIZE(lst);
871 // for (Py_ssize_t i = 0; i < siz; i++)
873 // PyObject * elem = PyList_GetItem(lst, i);
874 // if (PyString_Check(elem))
876 // std::cout << "At pos:" << i << ", " << PyString_AsString(elem) << std::endl;
879 // std::cout << "At pos:" << i << ", not a string!" << std::endl;
885 \brief Returns trace string
887 static const QString MYReplaceStr("paraview.simple");
888 QString PVGUI_Module::getTraceString()
890 vtkSMTrace *tracer = vtkSMTrace::GetActiveTracer();
891 if (!tracer) // trace is not started
894 QString traceString(tracer->GetCurrentTrace());
895 std::stringstream nl; nl << std::endl; // surely there is some Qt trick to do that in a portable way??
896 QString end_line(nl.str().c_str());
897 // 'import pvsimple' is necessary to fix the first call to DisableFirstRenderCamera in the paraview trace
898 // 'ShowParaviewView()' ensure there is an opened viewing window (otherwise SEGFAULT!)
899 traceString = "import pvsimple" + end_line +
900 "pvsimple.ShowParaviewView()" + end_line + traceString;
902 // Replace import "paraview.simple" by "pvsimple"
903 if ((!traceString.isNull()) && traceString.length() != 0) {
904 int aPos = traceString.indexOf(MYReplaceStr);
906 traceString = traceString.replace(aPos, MYReplaceStr.length(), "pvsimple");
907 aPos = traceString.indexOf(MYReplaceStr, aPos);
915 \brief Saves trace string to disk file
917 void PVGUI_Module::saveTrace(const char* theName)
920 if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
921 MESSAGE( "Could not open file:" << theName );
924 QTextStream out(&file);
925 out << getTraceString();
930 \brief Saves ParaView state to a disk file
932 void PVGUI_Module::saveParaviewState(const char* theFileName)
934 pqApplicationCore::instance()->saveState(theFileName);
938 \brief Delete all objects for Paraview Pipeline Browser
940 void PVGUI_Module::clearParaviewState()
942 QAction* deleteAllAction = action(DeleteAllId);
943 if (deleteAllAction) {
944 deleteAllAction->activate(QAction::Trigger);
949 \brief Restores ParaView state from a disk file
951 If toClear == true, the current ojects will be deleted
953 void PVGUI_Module::loadParaviewState(const char* theFileName)
955 pqApplicationCore::instance()->loadState(theFileName, getActiveServer());
959 \brief Returns current active ParaView server
961 pqServer* PVGUI_Module::getActiveServer()
963 return pqApplicationCore::instance()->getActiveServer();
968 \brief Creates PARAVIS preference pane
970 void PVGUI_Module::createPreferences()
972 // Paraview settings tab
973 int aParaViewSettingsTab = addPreference( tr( "TIT_PVIEWSETTINGS" ) );
974 int aPanel = addPreference(QString(), aParaViewSettingsTab, LightApp_Preferences::UserDefined, "PARAVIS", "");
975 setPreferenceProperty(aPanel, "content", (qint64)(new PVGUI_ParaViewSettingsPane()));
977 // Paravis settings tab
978 int aParaVisSettingsTab = addPreference( tr( "TIT_PVISSETTINGS" ) );
979 addPreference( tr( "PREF_STOP_TRACE" ), aParaVisSettingsTab, LightApp_Preferences::Bool, "PARAVIS", "stop_trace");
981 addPreference( tr( "PREF_NO_EXT_PVSERVER" ), aParaVisSettingsTab, LightApp_Preferences::Bool, "PARAVIS", "no_ext_pv_server");
983 int aSaveType = addPreference(tr( "PREF_SAVE_TYPE_LBL" ), aParaVisSettingsTab,
984 LightApp_Preferences::Selector,
985 "PARAVIS", "savestate_type");
986 QList<QVariant> aIndices;
987 QStringList aStrings;
989 aStrings<<tr("PREF_SAVE_TYPE_0");
990 aStrings<<tr("PREF_SAVE_TYPE_1");
991 aStrings<<tr("PREF_SAVE_TYPE_2");
992 setPreferenceProperty(aSaveType, "strings", aStrings);
993 setPreferenceProperty(aSaveType, "indexes", aIndices);
997 \brief Creates ParaViS context menu popup
999 void PVGUI_Module::contextMenuPopup(const QString& theClient, QMenu* theMenu, QString& theTitle)
1001 SalomeApp_Module::contextMenuPopup(theClient, theMenu, theTitle);
1003 // Check if we are in Object Browser
1004 SUIT_DataBrowser* ob = getApp()->objectBrowser();
1005 bool isOBClient = (ob && theClient == ob->popupClientType());
1010 // Get list of selected objects
1011 LightApp_SelectionMgr* aSelectionMgr = getApp()->selectionMgr();
1012 SALOME_ListIO aListIO;
1013 aSelectionMgr->selectedObjects(aListIO);
1014 if (aListIO.Extent() == 1 && aListIO.First()->hasEntry()) {
1015 QString entry = QString(aListIO.First()->getEntry());
1018 SalomeApp_Study* activeStudy =
1019 dynamic_cast<SalomeApp_Study*>(getApp()->activeStudy());
1024 // Get SALOMEDS client study
1025 _PTR(Study) studyDS = activeStudy->studyDS();
1030 QString paravisDataType(GetCPPEngine()->ComponentDataType());
1031 if(activeStudy && activeStudy->isComponent(entry) &&
1032 activeStudy->componentDataType(entry) == paravisDataType) {
1033 // ParaViS module object
1034 theMenu->addSeparator();
1035 theMenu->addAction(action(SaveStatePopupId));
1038 // Try to get state object
1039 _PTR(SObject) stateSObj =
1040 studyDS->FindObjectID(entry.toLatin1().constData());
1046 _PTR(GenericAttribute) anAttr;
1047 if (!stateSObj->FindAttribute(anAttr, "AttributeLocalID")) {
1051 _PTR(AttributeLocalID) anID(anAttr);
1053 if (anID->Value() == PVSTATEID) {
1054 // Paraview state object
1055 theMenu->addSeparator();
1056 theMenu->addAction(action(AddStatePopupId));
1057 theMenu->addAction(action(CleanAndAddStatePopupId));
1058 theMenu->addSeparator();
1059 theMenu->addAction(action(ParaVisRenameId));
1060 theMenu->addAction(action(ParaVisDeleteId));
1067 \brief. Show ParaView python trace.
1069 void PVGUI_Module::onShowTrace()
1071 if (!myTraceWindow) {
1072 myTraceWindow = new pqPythonScriptEditor(getApp()->desktop());
1074 myTraceWindow->setText(getTraceString());
1075 myTraceWindow->show();
1076 myTraceWindow->raise();
1077 myTraceWindow->activateWindow();
1082 \brief. Re-initialize ParaView python trace.
1084 void PVGUI_Module::onRestartTrace()
1091 \brief Save state under the module root object.
1093 void PVGUI_Module::onSaveMultiState()
1095 // Create state study object
1097 // Get SALOMEDS client study
1098 _PTR(Study) studyDS = PARAVIS::GetCStudy(this);
1103 _PTR(SComponent) paravisComp =
1104 studyDS->FindComponent(GetCPPEngine()->ComponentDataType());
1109 // Unlock the study if it is locked
1110 bool isLocked = studyDS->GetProperties()->IsLocked();
1112 studyDS->GetProperties()->SetLocked(false);
1115 QString stateName = tr("SAVED_PARAVIEW_STATE_NAME") +
1116 QString::number(myStateCounter + 1);
1118 _PTR(StudyBuilder) studyBuilder = studyDS->NewBuilder();
1119 _PTR(SObject) newSObj = studyBuilder->NewObject(paravisComp);
1122 _PTR(GenericAttribute) anAttr;
1123 anAttr = studyBuilder->FindOrCreateAttribute(newSObj, "AttributeName");
1124 _PTR(AttributeName) nameAttr(anAttr);
1126 nameAttr->SetValue(stateName.toLatin1().constData());
1129 anAttr = studyBuilder->FindOrCreateAttribute(newSObj, "AttributeLocalID");
1130 _PTR(AttributeLocalID) localIdAttr(anAttr);
1132 localIdAttr->SetValue(PVSTATEID);
1135 QString stateEntry = QString::fromStdString(newSObj->GetID());
1137 // File name for state saving
1138 QString tmpDir = QString::fromStdString(SALOMEDS_Tool::GetTmpDir());
1139 QString fileName = QString("%1_paravisstate:%2").arg(tmpDir, stateEntry);
1141 anAttr = studyBuilder->FindOrCreateAttribute(newSObj, "AttributeString");
1142 _PTR(AttributeString) stringAttr(anAttr);
1144 stringAttr->SetValue(fileName.toLatin1().constData());
1146 // Lock the study back if necessary
1148 studyDS->GetProperties()->SetLocked(true);
1152 saveParaviewState(fileName.toLatin1().constData());
1153 myTemporaryFiles.append(fileName);
1155 // Increment the counter
1162 \brief Restore the selected state by merging with the current one.
1164 void PVGUI_Module::onAddState()
1166 loadSelectedState(false);
1170 \brief Clean the current state and restore the selected one.
1172 void PVGUI_Module::onCleanAddState()
1174 loadSelectedState(true);
1178 \brief Rename the selected object.
1180 void PVGUI_Module::onRename()
1182 LightApp_SelectionMgr* aSelectionMgr = getApp()->selectionMgr();
1183 SALOME_ListIO aListIO;
1184 aSelectionMgr->selectedObjects(aListIO);
1186 if (aListIO.Extent() == 1 && aListIO.First()->hasEntry()) {
1187 std::string entry = aListIO.First()->getEntry();
1189 // Get SALOMEDS client study
1190 _PTR(Study) studyDS = PARAVIS::GetCStudy(this);
1195 // Unlock the study if it is locked
1196 bool isLocked = studyDS->GetProperties()->IsLocked();
1198 studyDS->GetProperties()->SetLocked(false);
1201 // Rename the selected state object
1202 _PTR(SObject) stateSObj = studyDS->FindObjectID(entry);
1207 _PTR(GenericAttribute) anAttr;
1208 if (stateSObj->FindAttribute(anAttr, "AttributeName")) {
1209 _PTR(AttributeName) nameAttr (anAttr);
1211 LightApp_NameDlg::getName(getApp()->desktop(), nameAttr->Value().c_str());
1212 if (!newName.isEmpty()) {
1213 nameAttr->SetValue(newName.toLatin1().constData());
1214 aListIO.First()->setName(newName.toLatin1().constData());
1218 // Lock the study back if necessary
1220 studyDS->GetProperties()->SetLocked(true);
1223 // Update object browser
1230 \brief Delete the selected objects.
1232 void PVGUI_Module::onDelete()
1234 LightApp_SelectionMgr* aSelectionMgr = getApp()->selectionMgr();
1235 SALOME_ListIO aListIO;
1236 aSelectionMgr->selectedObjects(aListIO);
1238 if (aListIO.Extent() == 1 && aListIO.First()->hasEntry()) {
1239 std::string entry = aListIO.First()->getEntry();
1241 // Get SALOMEDS client study
1242 _PTR(Study) studyDS = PARAVIS::GetCStudy(this);
1247 // Unlock the study if it is locked
1248 bool isLocked = studyDS->GetProperties()->IsLocked();
1250 studyDS->GetProperties()->SetLocked(false);
1253 // Remove the selected state from the study
1254 _PTR(StudyBuilder) studyBuilder = studyDS->NewBuilder();
1255 _PTR(SObject) stateSObj = studyDS->FindObjectID(entry);
1256 studyBuilder->RemoveObject(stateSObj);
1258 // Lock the study back if necessary
1260 studyDS->GetProperties()->SetLocked(true);
1263 // Update object browser
1268 void PVGUI_Module::onPushTraceTimer()
1270 // MESSAGE("onPushTraceTimer(): Pushing trace to engine...");
1271 GetCPPEngine()->PutPythonTraceStringToEngine(getTraceString().toStdString().c_str());
1275 \brief Discover help project files from the resources.
1276 \return name of the help file.
1278 QString PVGUI_Module::getHelpFileName() {
1279 QString aPVHome(getenv("PVHOME"));
1280 if (aPVHome.isNull()) {
1281 qWarning("Wariable PVHOME is not defined");
1284 QChar aSep = QDir::separator();
1285 //PARAVIEW_VERSION from the vtkPVConfig.h file
1286 QString aFileName = aPVHome + aSep + "share" + aSep + "doc" + aSep + "paraview-"+ PARAVIEW_VERSION + aSep + "paraview.qch";
1292 \brief Load selected paraview state
1294 If toClear == true, the current state will be cleared
1296 void PVGUI_Module::loadSelectedState(bool toClear)
1300 LightApp_SelectionMgr* aSelectionMgr = getApp()->selectionMgr();
1301 SALOME_ListIO aListIO;
1302 aSelectionMgr->selectedObjects(aListIO);
1304 if (aListIO.Extent() == 1 && aListIO.First()->hasEntry()) {
1305 std::string entry = aListIO.First()->getEntry();
1307 // Get SALOMEDS client study
1308 _PTR(Study) studyDS = PARAVIS::GetCStudy(this);
1314 _PTR(SObject) stateSObj = studyDS->FindObjectID(entry);
1315 _PTR(GenericAttribute) anAttr;
1316 if (!stateSObj->FindAttribute(anAttr, "AttributeLocalID")) {
1319 _PTR(AttributeLocalID) anID(anAttr);
1320 if (!anID->Value() == PVSTATEID) {
1324 // Get state file name
1325 if (stateSObj->FindAttribute(anAttr, "AttributeString")) {
1326 _PTR(AttributeString) aStringAttr(anAttr);
1327 QString stringValue(aStringAttr->Value().c_str());
1329 if (QFile::exists(stringValue)) {
1330 fileName = stringValue;
1335 if (!fileName.isEmpty()) {
1337 clearParaviewState();
1340 loadParaviewState(fileName.toLatin1().constData());
1343 SUIT_MessageBox::critical(getApp()->desktop(),
1345 tr("ERR_STATE_CANNOT_BE_RESTORED"));
1350 \fn CAM_Module* createModule();
1351 \brief Export module instance (factory function).
1352 \return new created instance of the module
1356 #define PVGUI_EXPORT __declspec(dllexport)
1358 #define PVGUI_EXPORT
1364 PVGUI_EXPORT CAM_Module* createModule() {
1365 return new PVGUI_Module();
1368 PVGUI_EXPORT char* getModuleVersion() {
1369 return (char*)PARAVIS_VERSION_STR;