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"
44 #include <SUIT_DataBrowser.h>
45 #include <SUIT_Desktop.h>
46 #include <SUIT_MessageBox.h>
47 #include <SUIT_ResourceMgr.h>
48 #include <SUIT_Session.h>
49 #include <SUIT_OverrideCursor.h>
50 #include <SUIT_ExceptionHandler.h>
52 #include <SALOME_LifeCycleCORBA.hxx>
53 #include <SALOMEDS_SObject.hxx>
55 #include <LightApp_SelectionMgr.h>
56 #include <LightApp_NameDlg.h>
57 #include <SalomeApp_Application.h>
58 #include <SalomeApp_Study.h>
59 #include <SALOME_ListIO.hxx>
60 #include <SALOMEDS_Tool.hxx>
61 #include <Utils_ORB_INIT.hxx>
62 #include <Utils_SINGLETON.hxx>
64 #include <QtxActionMenuMgr.h>
65 #include <QtxActionToolMgr.h>
67 #include <PARAVIS_version.h>
73 #include <QApplication>
79 #include <QInputDialog>
83 #include <QStringList>
86 #include <QTextStream>
88 #include <QDockWidget>
89 #include <QHelpEngine>
92 #include <vtkPVConfig.h> // for symbol PARAVIEW_VERSION
93 #include <vtkProcessModule.h>
94 #include <vtkPVSession.h>
95 #include <vtkPVProgressHandler.h>
96 #include <vtkOutputWindow.h>
97 #include <vtkEventQtSlotConnect.h>
99 #include <vtkSMProxy.h>
100 #include <vtkSmartPointer.h>
101 #include <vtkSMSession.h>
102 #include <vtkSMTrace.h>
103 #include <vtkSMSessionProxyManager.h>
104 #include <vtkSMParaViewPipelineController.h>
106 #include <pqApplicationCore.h>
107 #include <pqPVApplicationCore.h>
108 #include <pqActiveView.h>
109 #include <pqObjectBuilder.h>
110 #include <pqOptions.h>
111 #include <pqSettings.h>
112 #include <pqServer.h>
113 #include <pqUndoStack.h>
114 #include <pqTabbedMultiViewWidget.h>
115 #include <pqActiveObjects.h>
116 #include <pqHelpReaction.h>
117 #include <pqPluginManager.h>
118 #include <pqPythonDialog.h>
119 #include <pqPythonManager.h>
120 #include <pqLoadDataReaction.h>
121 #include <pqPythonScriptEditor.h>
122 #include <pqDataRepresentation.h>
123 #include <pqDisplayColorWidget.h>
124 #include <pqColorToolbar.h>
125 #include <pqScalarBarVisibilityReaction.h>
126 #include <pqServerResource.h>
127 #include <pqServerConnectReaction.h>
129 //----------------------------------------------------------------------------
130 PVGUI_Module* ParavisModule = 0;
135 <h2>Building and installing PARAVIS</h2>
136 As any other SALOME module, PARAVIS requires PARAVIS_ROOT_DIR environment variable to be set to PARAVIS
137 installation directory.
138 Other variables needed for correct detection of ParaView location:
139 \li PVHOME - points at the ParaView installation directory tree
140 \li PVVERSION - number of ParaView version
142 It also requires common SALOME environment including GUI_ROOT_DIR and other prerequsites.
145 PARAVIS module can be launched using the following commands:
146 \li Full SALOME configuration
148 runSalome --modules="PARAVIS"
151 <h2>ParaView GUI integration</h2>
152 <h3>ParaView GUI integration overview</h3>
154 The main idea is to reuse ParaView GUI internal logic as much as possible, providing a layer
155 between it and SALOME GUI that hides the following SALOME GUI implementation details from ParaView:
157 \li SALOME GUI executable and Qt event loop
158 \li SALOME GUI desktop
159 \li Dock windows areas
160 \li SALOME menu and toolbar managers
162 Major part of the integration is implemented in PVGUI_Module class.
164 <h3>ParaView client initalization</h3>
166 ParaView client initalization is performed when an instance of PVGUI_Module class has been created
167 and \link PVGUI_Module::initialize() PVGUI_Module::initialize()\endlink method is called by SALOME GUI.
168 The actual client start-up is done in \link PVGUI_Module::pvInit() PVGUI_Module::pvInit()\endlink method.
171 <h3>Multi-view manager</h3>
173 SALOME GUI requires that each kind of view be implemnted with help of (at least) three classes. For ParaView multi-view manager
176 \li PVGUI_ViewManager - view manager class
177 \li PVGUI_Viewer - view model class
178 \li PVGUI_ViewWindow - view window class that acts as a parent for %pqViewManager
180 Single instances of PVGUI_ViewManager and PVGUI_ViewWindow classes are created by \link PVGUI_Module::showView()
181 PVGUI_Module::showView()\endlink method upon the first PARAVIS module activation. The same method hides the multi-view manager
182 when the module is deactivated (the user switches to another module or a study is closed).
183 A special trick is used to make PVGUI_ViewWindow the parent of %pqViewManager widget. It is created initally by %pqMainWindowCore
184 with the desktop as a parent, so when it is shown PVGUI_ViewWindow instance is passed to its setParent() method. In
185 \link PVGUI_ViewWindow::~PVGUI_ViewWindow() PVGUI_ViewWindow::~PVGUI_ViewWindow()\endlink the parent is nullified to avoid deletion
186 of %pqViewManager widget that would break %pqMainWindowCore class.
188 <h3>ParaView plugins</h3>
189 ParaView server and client plugins are managed by %pqMainWindowCore slots that has full access to PARAVIS menus and toolbars.
190 As a result they appears automatically in PARAVIS menus and toolbars if loaded successfully.
195 \brief Implementation
196 SALOME module wrapping ParaView GUI.
200 ClientFindOrCreateParavisComponent(_PTR(Study) theStudyDocument)
202 _PTR(SComponent) aSComponent = theStudyDocument->FindComponent("PARAVIS");
204 _PTR(StudyBuilder) aStudyBuilder = theStudyDocument->NewBuilder();
205 aStudyBuilder->NewCommand();
206 int aLocked = theStudyDocument->GetProperties()->IsLocked();
207 if (aLocked) theStudyDocument->GetProperties()->SetLocked(false);
208 aSComponent = aStudyBuilder->NewComponent("PARAVIS");
209 _PTR(GenericAttribute) anAttr =
210 aStudyBuilder->FindOrCreateAttribute(aSComponent, "AttributeName");
211 _PTR(AttributeName) aName (anAttr);
213 ORB_INIT& init = *SINGLETON_<ORB_INIT>::Instance();
214 CORBA::ORB_var anORB = init( qApp->argc(), qApp->argv() );
216 SALOME_NamingService *NamingService = new SALOME_NamingService( anORB );
217 CORBA::Object_var objVarN = NamingService->Resolve("/Kernel/ModulCatalog");
218 SALOME_ModuleCatalog::ModuleCatalog_var Catalogue =
219 SALOME_ModuleCatalog::ModuleCatalog::_narrow(objVarN);
220 SALOME_ModuleCatalog::Acomponent_var Comp = Catalogue->GetComponent( "PARAVIS" );
221 if (!Comp->_is_nil()) {
222 aName->SetValue(Comp->componentusername());
225 anAttr = aStudyBuilder->FindOrCreateAttribute(aSComponent, "AttributePixMap");
226 _PTR(AttributePixMap) aPixmap (anAttr);
227 aPixmap->SetPixMap( "pqAppIcon16.png" );
229 // Create Attribute parameters for future using
230 anAttr = aStudyBuilder->FindOrCreateAttribute(aSComponent, "AttributeParameter");
232 aStudyBuilder->DefineComponentInstance(aSComponent, PVGUI_Module::GetEngine()->GetIOR());
233 if (aLocked) theStudyDocument->GetProperties()->SetLocked(true);
234 aStudyBuilder->CommitCommand();
240 Clean up function; used to stop ParaView progress events when
241 exception is caught by global exception handler.
243 void paravisCleanUp()
245 if ( pqApplicationCore::instance() ) {
246 pqServer* s = pqApplicationCore::instance()->getActiveServer();
247 if ( s ) s->session()->GetProgressHandler()->CleanupPendingProgress();
252 \brief Constructor. Sets the default name for the module.
254 PVGUI_Module::PVGUI_Module()
255 : SalomeApp_Module( "PARAVIS" ),
256 mySelectionControlsTb( -1 ),
257 mySourcesMenuId( -1 ),
258 myFiltersMenuId( -1 ),
260 myToolbarsMenuId(-1),
269 Q_INIT_RESOURCE( PVGUI );
271 ParavisModule = this;
273 // Clear old copies of embedded macros files
274 QString aDestPath = QString( "%1/.config/%2/Macros" ).arg( QDir::homePath() ).arg( QApplication::applicationName() );
278 QDir aDestDir(aDestPath);
279 QStringList aDestFiles = aDestDir.entryList(aFilter, QDir::Files);
280 foreach (QString aMacrosPath, getEmbeddedMacrosList()) {
281 QString aMacrosName = QFileInfo(aMacrosPath).fileName();
282 if (aDestFiles.contains(aMacrosName)) {
283 aDestDir.remove(aMacrosName);
291 PVGUI_Module::~PVGUI_Module()
293 if (myPushTraceTimer)
294 delete myPushTraceTimer;
299 PARAVIS_ORB::PARAVIS_Gen_var PVGUI_Module::GetEngine()
301 return PVViewer_ViewManager::GetEngine();
304 pqPVApplicationCore * PVGUI_Module::GetPVApplication()
306 return PVViewer_ViewManager::GetPVApplication();
310 \brief Initialize module. Creates menus, prepares context menu, etc.
311 \param app SALOME GUI application instance
313 void PVGUI_Module::initialize( CAM_Application* app )
315 SalomeApp_Module::initialize( app );
317 // Create ParaViS actions
319 // Create ParaViS menus
322 // Uncomment to debug ParaView initialization
323 // "aa" used instead of "i" as GDB doesn't like "i" variables :)
331 SalomeApp_Application* anApp = getApp();
332 SUIT_Desktop* aDesktop = anApp->desktop();
334 // Initialize ParaView client and associated behaviors
335 // and connect to externally launched pvserver
336 PVViewer_ViewManager::ParaviewInitApp(aDesktop);
338 // Remember current state of desktop toolbars
339 QList<QToolBar*> foreignToolbars = aDesktop->findChildren<QToolBar*>();
343 // Behaviors and connection must be instanciated *after* widgets are in place
344 // In PARAVIS module we do not wait for PVViewer_ViewWindow to be instanciated to have this:
345 PVViewer_ViewManager::ParaviewInitBehaviors(true, aDesktop);
346 PVViewer_ViewManager::ConnectToExternalPVServer(aDesktop);
352 QList<QDockWidget*> activeDocks = aDesktop->findChildren<QDockWidget*>();
353 QList<QMenu*> activeMenus = aDesktop->findChildren<QMenu*>();
355 // Setup quick-launch shortcuts.
356 QShortcut *ctrlSpace = new QShortcut(Qt::CTRL + Qt::Key_Space, aDesktop);
357 QObject::connect(ctrlSpace, SIGNAL(activated()),
358 pqApplicationCore::instance(), SLOT(quickLaunch()));
360 // Find Plugin Dock Widgets
361 QList<QDockWidget*> currentDocks = aDesktop->findChildren<QDockWidget*>();
362 QList<QDockWidget*>::iterator i;
363 for (i = currentDocks.begin(); i != currentDocks.end(); ++i) {
364 if(!activeDocks.contains(*i)) {
365 myDockWidgets[*i] = false; // hidden by default
371 // [ABN] TODO: fix this - triggers a SEGFAULT at deactivation() time.
372 // QList<QMenu*> currentMenus = aDesktop->findChildren<QMenu*>();
373 // QList<QMenu*>::iterator im;
374 // for (im = currentMenus.begin(); im != currentMenus.end(); ++im) {
375 // if(!activeMenus.contains(*im)) {
376 // QString s = (*im)->title();
377 // std::cout << " MENU "<< s.toStdString() << std::endl;
378 // myMenus.append(*im);
382 PVViewer_ViewManager::ParaviewLoadConfigurations();
385 // Find created toolbars
386 QCoreApplication::processEvents();
388 QList<QToolBar*> allToolbars = aDesktop->findChildren<QToolBar*>();
389 foreach(QToolBar* aBar, allToolbars) {
390 if (!foreignToolbars.contains(aBar)) {
391 myToolbars[aBar] = true;
392 myToolbarBreaks[aBar] = false;
393 aBar->setVisible(false);
394 aBar->toggleViewAction()->setVisible(false);
400 SUIT_ResourceMgr* aResourceMgr = SUIT_Session::session()->resourceMgr();
401 bool isStop = aResourceMgr->booleanValue( "PARAVIS", "stop_trace", false );
404 // Start a timer to schedule asap:
405 // - the connection to the server
407 myInitTimer = new QTimer(aDesktop);
408 QObject::connect(myInitTimer, SIGNAL(timeout()), this, SLOT(onInitTimer()) );
409 myInitTimer->setSingleShot(true);
410 myInitTimer->start(0);
412 // Another timer to regularly push the trace onto the engine:
413 myPushTraceTimer = new QTimer(aDesktop);
414 QObject::connect(myPushTraceTimer, SIGNAL(timeout()), this, SLOT(onPushTraceTimer()) );
415 myPushTraceTimer->setSingleShot(false);
416 myPushTraceTimer->start(500);
419 this->VTKConnect = vtkEventQtSlotConnect::New();
421 vtkProcessModule* pm = vtkProcessModule::GetProcessModule();
423 vtkPVSession* pvs = dynamic_cast<vtkPVSession*>(pm->GetSession());
425 vtkPVProgressHandler* ph = pvs->GetProgressHandler();
427 this->VTKConnect->Connect(ph, vtkCommand::StartEvent,
428 this, SLOT(onStartProgress()));
429 this->VTKConnect->Connect(ph, vtkCommand::EndEvent,
430 this, SLOT(onEndProgress()));
436 void PVGUI_Module::onStartProgress()
438 QApplication::setOverrideCursor(Qt::WaitCursor);
441 void PVGUI_Module::onEndProgress()
443 QApplication::restoreOverrideCursor();
446 void PVGUI_Module::onDataRepresentationUpdated() {
447 SalomeApp_Study* activeStudy = dynamic_cast<SalomeApp_Study*>(application()->activeStudy());
448 if(!activeStudy) return;
450 activeStudy->Modified();
454 \brief Initialisation timer event - fired only once, after the GUI loop is ready.
455 See creation in initialize().
457 void PVGUI_Module::onInitTimer()
459 #ifndef PARAVIS_WITH_FULL_CORBA
460 // connectToExternalPVServer();
466 \brief Get list of embedded macros files
468 QStringList PVGUI_Module::getEmbeddedMacrosList()
470 QString aRootDir = getenv("PARAVIS_ROOT_DIR");
472 QString aSourcePath = aRootDir + "/bin/salome/Macro";
477 QDir aSourceDir(aSourcePath);
478 QStringList aSourceFiles = aSourceDir.entryList(aFilter, QDir::Files);
479 QStringList aFullPathSourceFiles;
480 foreach (QString aMacrosName, aSourceFiles) {
481 aFullPathSourceFiles << aSourceDir.absoluteFilePath(aMacrosName);
483 return aFullPathSourceFiles;
486 void PVGUI_Module::updateMacros()
488 pqPythonManager* aPythonManager = pqPVApplicationCore::instance()->pythonManager();
489 if(!aPythonManager) {
493 foreach (QString aStr, getEmbeddedMacrosList()) {
494 aPythonManager->addMacro(aStr);
500 \brief Get list of compliant dockable GUI elements
501 \param m map to be filled in ("type":"default_position")
503 void PVGUI_Module::windows( QMap<int, int>& m ) const
505 m.insert( LightApp_Application::WT_ObjectBrowser, Qt::LeftDockWidgetArea );
506 m.insert( LightApp_Application::WT_PyConsole, Qt::BottomDockWidgetArea );
507 // ParaView diagnostic output redirected here
508 m.insert( LightApp_Application::WT_LogWindow, Qt::BottomDockWidgetArea );
512 \brief Shows (toShow = true) or hides ParaView view window
514 void PVGUI_Module::showView( bool toShow )
516 SalomeApp_Application* anApp = getApp();
517 PVViewer_ViewManager* viewMgr =
518 dynamic_cast<PVViewer_ViewManager*>( anApp->getViewManager( PVViewer_Viewer::Type(), false ) );
520 viewMgr = new PVViewer_ViewManager( anApp->activeStudy(), anApp->desktop() );
521 anApp->addViewManager( viewMgr );
522 connect( viewMgr, SIGNAL( lastViewClosed( SUIT_ViewManager* ) ),
523 anApp, SLOT( onCloseView( SUIT_ViewManager* ) ) );
526 PVViewer_ViewWindow* pvWnd = dynamic_cast<PVViewer_ViewWindow*>( viewMgr->getActiveView() );
528 pvWnd = dynamic_cast<PVViewer_ViewWindow*>( viewMgr->createViewWindow() );
529 // this also connects to the pvserver and instantiates relevant PV behaviors
532 pvWnd->setShown( toShow );
533 if ( toShow ) pvWnd->setFocus();
537 \brief Slot to show help for proxy.
539 void PVGUI_Module::showHelpForProxy( const QString& groupname, const QString& proxyname )
541 pqHelpReaction::showProxyHelp(groupname, proxyname);
546 \brief Slot to show the waiting state.
548 void PVGUI_Module::onPreAccept()
550 getApp()->desktop()->statusBar()->showMessage(tr("STB_PREACCEPT"));
551 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
555 \brief Slot to show the ready state.
557 void PVGUI_Module::onPostAccept()
559 getApp()->desktop()->statusBar()->showMessage(tr("STB_POSTACCEPT"), 2000);
560 QTimer::singleShot(0, this, SLOT(endWaitCursor()));
564 \brief Slot to switch off wait cursor.
566 void PVGUI_Module::endWaitCursor()
568 QApplication::restoreOverrideCursor();
571 static void ParavisMessageOutput(QtMsgType type, const char *msg)
576 vtkOutputWindow::GetInstance()->DisplayText(msg);
579 vtkOutputWindow::GetInstance()->DisplayErrorText(msg);
582 vtkOutputWindow::GetInstance()->DisplayErrorText(msg);
585 vtkOutputWindow::GetInstance()->DisplayErrorText(msg);
591 \brief Activate module.
592 \param study current study
593 \return \c true if activaion is done successfully or 0 to prevent
596 bool PVGUI_Module::activateModule( SUIT_Study* study )
598 myOldMsgHandler = qInstallMsgHandler(ParavisMessageOutput);
600 SUIT_ExceptionHandler::addCleanUpRoutine( paravisCleanUp );
602 storeCommonWindowsState();
604 bool isDone = SalomeApp_Module::activateModule( study );
605 if ( !isDone ) return false;
607 showView( true ); // this will also trigger the connection to the server
608 // and the instanciation of the relevant PV behaviors
609 if ( mySourcesMenuId != -1 ) menuMgr()->show(mySourcesMenuId);
610 if ( myFiltersMenuId != -1 ) menuMgr()->show(myFiltersMenuId);
611 if ( myFiltersMenuId != -1 ) menuMgr()->show(myMacrosMenuId);
612 if ( myFiltersMenuId != -1 ) menuMgr()->show(myToolbarsMenuId);
613 setMenuShown( true );
614 setToolShown( true );
616 restoreDockWidgetsState();
618 QMenu* aMenu = menuMgr()->findMenu( myRecentMenuId );
620 QList<QAction*> anActns = aMenu->actions();
621 for (int i = 0; i < anActns.size(); ++i) {
622 QAction* a = anActns.at(i);
628 QList<QMenu*>::iterator it;
629 for (it = myMenus.begin(); it != myMenus.end(); ++it) {
630 QAction* a = (*it)->menuAction();
635 if ( myRecentMenuId != -1 ) menuMgr()->show(myRecentMenuId);
637 ClientFindOrCreateParavisComponent(PARAVIS::GetCStudy(this));
644 \brief Deactivate module.
645 \param study current study
646 \return \c true if deactivaion is done successfully or 0 to prevent
647 deactivation on error
649 bool PVGUI_Module::deactivateModule( SUIT_Study* study )
651 MESSAGE("PARAVIS deactivation ...")
653 QMenu* aMenu = menuMgr()->findMenu( myRecentMenuId );
655 QList<QAction*> anActns = aMenu->actions();
656 for (int i = 0; i < anActns.size(); ++i) {
657 QAction* a = anActns.at(i);
659 a->setVisible(false);
663 QList<QMenu*>::iterator it;
664 for (it = myMenus.begin(); it != myMenus.end(); ++it) {
665 QAction* a = (*it)->menuAction();
667 a->setVisible(false);
670 QList<QDockWidget*> aStreamingViews = application()->desktop()->findChildren<QDockWidget*>("pqStreamingControls");
671 foreach(QDockWidget* aView, aStreamingViews) {
672 if (!myDockWidgets.contains(aView))
673 myDockWidgets[aView] = aView->isVisible();
676 /*if (pqImplementation::helpWindow) {
677 pqImplementation::helpWindow->hide();
681 menuMgr()->hide(myRecentMenuId);
682 menuMgr()->hide(mySourcesMenuId);
683 menuMgr()->hide(myFiltersMenuId);
684 menuMgr()->hide(myMacrosMenuId);
685 menuMgr()->hide(myToolbarsMenuId);
686 setMenuShown( false );
687 setToolShown( false );
689 saveDockWidgetsState();
691 SUIT_ExceptionHandler::removeCleanUpRoutine( paravisCleanUp );
694 qInstallMsgHandler(myOldMsgHandler);
696 restoreCommonWindowsState();
698 return SalomeApp_Module::deactivateModule( study );
703 \brief Called when application is closed.
705 Process finalize application functionality from ParaView in order to save server settings
706 and nullify application pointer if the application is being closed.
708 \param theApp application
710 void PVGUI_Module::onApplicationClosed( SUIT_Application* theApp )
712 PVViewer_ViewManager::ParaviewCleanup();
714 int aAppsNb = SUIT_Session::session()->applications().size();
716 deleteTemporaryFiles();
718 CAM_Module::onApplicationClosed(theApp);
723 \brief Deletes temporary files created during import operation from VISU
725 void PVGUI_Module::deleteTemporaryFiles()
727 foreach(QString aFile, myTemporaryFiles) {
728 if (QFile::exists(aFile)) {
729 QFile::remove(aFile);
736 \brief Called when study is closed.
738 Removes data model from the \a study.
740 \param study study being closed
742 void PVGUI_Module::studyClosed(SUIT_Study* study)
744 clearParaviewState();
746 SalomeApp_Module::studyClosed(study);
750 \brief Called when study is opened.
752 void PVGUI_Module::onModelOpened()
754 _PTR(Study) studyDS = PARAVIS::GetCStudy(this);
759 _PTR(SComponent) paravisComp =
760 studyDS->FindComponent(GetEngine()->ComponentDataType());
765 _PTR(ChildIterator) anIter(studyDS->NewChildIterator(paravisComp));
766 for (; anIter->More(); anIter->Next()) {
767 _PTR(SObject) aSObj = anIter->Value();
768 _PTR(GenericAttribute) anAttr;
769 if (!aSObj->FindAttribute(anAttr, "AttributeLocalID")) {
772 _PTR(AttributeLocalID) anID(anAttr);
773 if (anID->Value() == PVSTATEID) {
780 \brief Returns IOR of current engine
782 QString PVGUI_Module::engineIOR() const
784 CORBA::String_var anIOR = GetEngine()->GetIOR();
785 return QString(anIOR.in());
789 \brief Open file of format supported by ParaView
791 void PVGUI_Module::openFile(const char* theName)
795 pqLoadDataReaction::loadData(aFiles);
799 * Start trace invoking the newly introduced C++ API (PV 4.2)
800 * (inspired from pqTraceReaction::start())
802 void PVGUI_Module::startTrace()
804 vtkSMSessionProxyManager* pxm = pqActiveObjects::instance().activeServer()->proxyManager();
806 vtkSmartPointer<vtkSMProxy> proxy;
807 proxy.TakeReference(pxm->NewProxy("pythontracing", "PythonTraceOptions"));
810 vtkNew<vtkSMParaViewPipelineController> controller;
811 controller->InitializeProxy(proxy);
813 vtkSMTrace* trace = vtkSMTrace::StartTrace();
816 // Set manually the properties entered via the dialog box poping-up when requiring
817 // a trace start in PV4.2 (trace options)
818 trace->SetPropertiesToTraceOnCreate(vtkSMTrace::RECORD_USER_MODIFIED_PROPERTIES);
819 trace->SetFullyTraceSupplementalProxies(false);
823 void PVGUI_Module::stopTrace()
825 vtkSMTrace::StopTrace();
828 void PVGUI_Module::executeScript(const char *script)
831 pqPythonManager* manager = qobject_cast<pqPythonManager*>(
832 pqApplicationCore::instance()->manager("PYTHON_MANAGER"));
834 pqPythonDialog* pyDiag = manager->pythonShellDialog();
836 pyDiag->runString(script);
843 // * Debug function printing out the given interpreter's execution context
845 //void printInterpContext(PyInterp_Interp * interp )
847 // // Extract __smtraceString from interpreter's context
848 // const PyObject* ctxt = interp->getExecutionContext();
850 // PyObject* lst = PyDict_Keys((PyObject *)ctxt);
851 // Py_ssize_t siz = PyList_GET_SIZE(lst);
852 // for (Py_ssize_t i = 0; i < siz; i++)
854 // PyObject * elem = PyList_GetItem(lst, i);
855 // if (PyString_Check(elem))
857 // std::cout << "At pos:" << i << ", " << PyString_AsString(elem) << std::endl;
860 // std::cout << "At pos:" << i << ", not a string!" << std::endl;
866 \brief Returns trace string
868 static const QString MYReplaceStr("paraview.simple");
869 static const QString MYReplaceImportStr("except: from pvsimple import *");
870 QString PVGUI_Module::getTraceString()
872 vtkSMTrace *tracer = vtkSMTrace::GetActiveTracer();
873 if (!tracer) // trace is not started
876 QString traceString(tracer->GetCurrentTrace());
878 // Replace import "paraview.simple" by "pvsimple"
879 if ((!traceString.isNull()) && traceString.length() != 0) {
880 int aPos = traceString.indexOf(MYReplaceStr);
882 traceString = traceString.replace(aPos, MYReplaceStr.length(), "pvsimple");
883 aPos = traceString.indexOf(MYReplaceStr, aPos);
885 int aImportPos = traceString.indexOf(MYReplaceImportStr);
888 traceString = traceString.replace(aImportPos, MYReplaceImportStr.length(), "except:\n import pvsimple\n from pvsimple import *");
896 \brief Saves trace string to disk file
898 void PVGUI_Module::saveTrace(const char* theName)
901 if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
902 MESSAGE( "Could not open file:" << theName );
905 QTextStream out(&file);
906 out << getTraceString();
911 \brief Saves ParaView state to a disk file
913 void PVGUI_Module::saveParaviewState(const char* theFileName)
915 pqApplicationCore::instance()->saveState(theFileName);
919 \brief Delete all objects for Paraview Pipeline Browser
921 void PVGUI_Module::clearParaviewState()
923 QAction* deleteAllAction = action(DeleteAllId);
924 if (deleteAllAction) {
925 deleteAllAction->activate(QAction::Trigger);
930 \brief Restores ParaView state from a disk file
932 If toClear == true, the current ojects will be deleted
934 void PVGUI_Module::loadParaviewState(const char* theFileName)
936 pqApplicationCore::instance()->loadState(theFileName, getActiveServer());
940 \brief Returns current active ParaView server
942 pqServer* PVGUI_Module::getActiveServer()
944 return pqApplicationCore::instance()->getActiveServer();
949 \brief Creates PARAVIS preference pane
951 void PVGUI_Module::createPreferences()
953 // Paraview settings tab
954 int aParaViewSettingsTab = addPreference( tr( "TIT_PVIEWSETTINGS" ) );
955 int aPanel = addPreference(QString(), aParaViewSettingsTab, LightApp_Preferences::UserDefined, "PARAVIS", "");
956 setPreferenceProperty(aPanel, "content", (qint64)(new PVGUI_ParaViewSettingsPane()));
958 // Paravis settings tab
959 int aParaVisSettingsTab = addPreference( tr( "TIT_PVISSETTINGS" ) );
960 addPreference( tr( "PREF_STOP_TRACE" ), aParaVisSettingsTab, LightApp_Preferences::Bool, "PARAVIS", "stop_trace");
962 int aSaveType = addPreference(tr( "PREF_SAVE_TYPE_LBL" ), aParaVisSettingsTab,
963 LightApp_Preferences::Selector,
964 "PARAVIS", "savestate_type");
965 QList<QVariant> aIndices;
966 QStringList aStrings;
968 aStrings<<tr("PREF_SAVE_TYPE_0");
969 aStrings<<tr("PREF_SAVE_TYPE_1");
970 aStrings<<tr("PREF_SAVE_TYPE_2");
971 setPreferenceProperty(aSaveType, "strings", aStrings);
972 setPreferenceProperty(aSaveType, "indexes", aIndices);
976 \brief Creates ParaViS context menu popup
978 void PVGUI_Module::contextMenuPopup(const QString& theClient, QMenu* theMenu, QString& theTitle)
980 SalomeApp_Module::contextMenuPopup(theClient, theMenu, theTitle);
982 // Check if we are in Object Browser
983 SUIT_DataBrowser* ob = getApp()->objectBrowser();
984 bool isOBClient = (ob && theClient == ob->popupClientType());
989 // Get list of selected objects
990 LightApp_SelectionMgr* aSelectionMgr = getApp()->selectionMgr();
991 SALOME_ListIO aListIO;
992 aSelectionMgr->selectedObjects(aListIO);
993 if (aListIO.Extent() == 1 && aListIO.First()->hasEntry()) {
994 QString entry = QString(aListIO.First()->getEntry());
997 SalomeApp_Study* activeStudy =
998 dynamic_cast<SalomeApp_Study*>(getApp()->activeStudy());
1003 // Get SALOMEDS client study
1004 _PTR(Study) studyDS = activeStudy->studyDS();
1009 QString paravisDataType(GetEngine()->ComponentDataType());
1010 if(activeStudy && activeStudy->isComponent(entry) &&
1011 activeStudy->componentDataType(entry) == paravisDataType) {
1012 // ParaViS module object
1013 theMenu->addSeparator();
1014 theMenu->addAction(action(SaveStatePopupId));
1017 // Try to get state object
1018 _PTR(SObject) stateSObj =
1019 studyDS->FindObjectID(entry.toLatin1().constData());
1025 _PTR(GenericAttribute) anAttr;
1026 if (!stateSObj->FindAttribute(anAttr, "AttributeLocalID")) {
1030 _PTR(AttributeLocalID) anID(anAttr);
1032 if (anID->Value() == PVSTATEID) {
1033 // Paraview state object
1034 theMenu->addSeparator();
1035 theMenu->addAction(action(AddStatePopupId));
1036 theMenu->addAction(action(CleanAndAddStatePopupId));
1037 theMenu->addSeparator();
1038 theMenu->addAction(action(ParaVisRenameId));
1039 theMenu->addAction(action(ParaVisDeleteId));
1046 \brief. Show ParaView python trace.
1048 void PVGUI_Module::onShowTrace()
1050 if (!myTraceWindow) {
1051 myTraceWindow = new pqPythonScriptEditor(getApp()->desktop());
1053 myTraceWindow->setText(getTraceString());
1054 myTraceWindow->show();
1055 myTraceWindow->raise();
1056 myTraceWindow->activateWindow();
1061 \brief. Re-initialize ParaView python trace.
1063 void PVGUI_Module::onRestartTrace()
1070 \brief Show ParaView view.
1072 void PVGUI_Module::onNewParaViewWindow()
1078 \brief Save state under the module root object.
1080 void PVGUI_Module::onSaveMultiState()
1082 // Create state study object
1084 // Get SALOMEDS client study
1085 _PTR(Study) studyDS = PARAVIS::GetCStudy(this);
1090 _PTR(SComponent) paravisComp =
1091 studyDS->FindComponent(GetEngine()->ComponentDataType());
1096 // Unlock the study if it is locked
1097 bool isLocked = studyDS->GetProperties()->IsLocked();
1099 studyDS->GetProperties()->SetLocked(false);
1102 QString stateName = tr("SAVED_PARAVIEW_STATE_NAME") +
1103 QString::number(myStateCounter + 1);
1105 _PTR(StudyBuilder) studyBuilder = studyDS->NewBuilder();
1106 _PTR(SObject) newSObj = studyBuilder->NewObject(paravisComp);
1109 _PTR(GenericAttribute) anAttr;
1110 anAttr = studyBuilder->FindOrCreateAttribute(newSObj, "AttributeName");
1111 _PTR(AttributeName) nameAttr(anAttr);
1113 nameAttr->SetValue(stateName.toLatin1().constData());
1116 anAttr = studyBuilder->FindOrCreateAttribute(newSObj, "AttributeLocalID");
1117 _PTR(AttributeLocalID) localIdAttr(anAttr);
1119 localIdAttr->SetValue(PVSTATEID);
1122 QString stateEntry = QString::fromStdString(newSObj->GetID());
1124 // File name for state saving
1125 QString tmpDir = QString::fromStdString(SALOMEDS_Tool::GetTmpDir());
1126 QString fileName = QString("%1_paravisstate:%2").arg(tmpDir, stateEntry);
1128 anAttr = studyBuilder->FindOrCreateAttribute(newSObj, "AttributeString");
1129 _PTR(AttributeString) stringAttr(anAttr);
1131 stringAttr->SetValue(fileName.toLatin1().constData());
1133 // Lock the study back if necessary
1135 studyDS->GetProperties()->SetLocked(true);
1139 saveParaviewState(fileName.toLatin1().constData());
1140 myTemporaryFiles.append(fileName);
1142 // Increment the counter
1149 \brief Restore the selected state by merging with the current one.
1151 void PVGUI_Module::onAddState()
1153 loadSelectedState(false);
1157 \brief Clean the current state and restore the selected one.
1159 void PVGUI_Module::onCleanAddState()
1161 loadSelectedState(true);
1165 \brief Rename the selected object.
1167 void PVGUI_Module::onRename()
1169 LightApp_SelectionMgr* aSelectionMgr = getApp()->selectionMgr();
1170 SALOME_ListIO aListIO;
1171 aSelectionMgr->selectedObjects(aListIO);
1173 if (aListIO.Extent() == 1 && aListIO.First()->hasEntry()) {
1174 std::string entry = aListIO.First()->getEntry();
1176 // Get SALOMEDS client study
1177 _PTR(Study) studyDS = PARAVIS::GetCStudy(this);
1182 // Unlock the study if it is locked
1183 bool isLocked = studyDS->GetProperties()->IsLocked();
1185 studyDS->GetProperties()->SetLocked(false);
1188 // Rename the selected state object
1189 _PTR(SObject) stateSObj = studyDS->FindObjectID(entry);
1194 _PTR(GenericAttribute) anAttr;
1195 if (stateSObj->FindAttribute(anAttr, "AttributeName")) {
1196 _PTR(AttributeName) nameAttr (anAttr);
1198 LightApp_NameDlg::getName(getApp()->desktop(), nameAttr->Value().c_str());
1199 if (!newName.isEmpty()) {
1200 nameAttr->SetValue(newName.toLatin1().constData());
1201 aListIO.First()->setName(newName.toLatin1().constData());
1205 // Lock the study back if necessary
1207 studyDS->GetProperties()->SetLocked(true);
1210 // Update object browser
1217 \brief Delete the selected objects.
1219 void PVGUI_Module::onDelete()
1221 LightApp_SelectionMgr* aSelectionMgr = getApp()->selectionMgr();
1222 SALOME_ListIO aListIO;
1223 aSelectionMgr->selectedObjects(aListIO);
1225 if (aListIO.Extent() == 1 && aListIO.First()->hasEntry()) {
1226 std::string entry = aListIO.First()->getEntry();
1228 // Get SALOMEDS client study
1229 _PTR(Study) studyDS = PARAVIS::GetCStudy(this);
1234 // Unlock the study if it is locked
1235 bool isLocked = studyDS->GetProperties()->IsLocked();
1237 studyDS->GetProperties()->SetLocked(false);
1240 // Remove the selected state from the study
1241 _PTR(StudyBuilder) studyBuilder = studyDS->NewBuilder();
1242 _PTR(SObject) stateSObj = studyDS->FindObjectID(entry);
1243 studyBuilder->RemoveObject(stateSObj);
1245 // Lock the study back if necessary
1247 studyDS->GetProperties()->SetLocked(true);
1250 // Update object browser
1255 void PVGUI_Module::onPushTraceTimer()
1257 // MESSAGE("onPushTraceTimer(): Pushing trace to engine...");
1258 GetEngine()->PutPythonTraceStringToEngine(getTraceString().toStdString().c_str());
1262 \brief Discover help project files from the resources.
1263 \return name of the help file.
1265 QString PVGUI_Module::getHelpFileName() {
1266 QString aPVHome(getenv("PVHOME"));
1267 if (aPVHome.isNull()) {
1268 qWarning("Wariable PVHOME is not defined");
1271 QChar aSep = QDir::separator();
1272 //PARAVIEW_VERSION from the vtkPVConfig.h file
1273 QString aFileName = aPVHome + aSep + "share" + aSep + "doc" + aSep + "paraview-"+ PARAVIEW_VERSION + aSep + "paraview.qch";
1279 \brief Load selected paraview state
1281 If toClear == true, the current state will be cleared
1283 void PVGUI_Module::loadSelectedState(bool toClear)
1287 LightApp_SelectionMgr* aSelectionMgr = getApp()->selectionMgr();
1288 SALOME_ListIO aListIO;
1289 aSelectionMgr->selectedObjects(aListIO);
1291 if (aListIO.Extent() == 1 && aListIO.First()->hasEntry()) {
1292 std::string entry = aListIO.First()->getEntry();
1294 // Get SALOMEDS client study
1295 _PTR(Study) studyDS = PARAVIS::GetCStudy(this);
1301 _PTR(SObject) stateSObj = studyDS->FindObjectID(entry);
1302 _PTR(GenericAttribute) anAttr;
1303 if (!stateSObj->FindAttribute(anAttr, "AttributeLocalID")) {
1306 _PTR(AttributeLocalID) anID(anAttr);
1307 if (!anID->Value() == PVSTATEID) {
1311 // Get state file name
1312 if (stateSObj->FindAttribute(anAttr, "AttributeString")) {
1313 _PTR(AttributeString) aStringAttr(anAttr);
1314 QString stringValue(aStringAttr->Value().c_str());
1316 if (QFile::exists(stringValue)) {
1317 fileName = stringValue;
1322 if (!fileName.isEmpty()) {
1324 clearParaviewState();
1327 loadParaviewState(fileName.toLatin1().constData());
1330 SUIT_MessageBox::critical(getApp()->desktop(),
1332 tr("ERR_STATE_CANNOT_BE_RESTORED"));
1337 \fn CAM_Module* createModule();
1338 \brief Export module instance (factory function).
1339 \return new created instance of the module
1343 #define PVGUI_EXPORT __declspec(dllexport)
1345 #define PVGUI_EXPORT
1351 PVGUI_EXPORT CAM_Module* createModule() {
1352 return new PVGUI_Module();
1355 PVGUI_EXPORT char* getModuleVersion() {
1356 return (char*)PARAVIS_VERSION_STR;