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>
130 #include <PyInterp_Interp.h>
133 //----------------------------------------------------------------------------
134 PVGUI_Module* ParavisModule = 0;
139 <h2>Building and installing PARAVIS</h2>
140 As any other SALOME module, PARAVIS requires PARAVIS_ROOT_DIR environment variable to be set to PARAVIS
141 installation directory.
142 Other variables needed for correct detection of ParaView location:
143 \li PVHOME - points at the ParaView installation directory tree
144 \li PVVERSION - number of ParaView version
146 It also requires common SALOME environment including GUI_ROOT_DIR and other prerequsites.
149 PARAVIS module can be launched using the following commands:
150 \li Full SALOME configuration
152 runSalome --modules="PARAVIS"
155 <h2>ParaView GUI integration</h2>
156 <h3>ParaView GUI integration overview</h3>
158 The main idea is to reuse ParaView GUI internal logic as much as possible, providing a layer
159 between it and SALOME GUI that hides the following SALOME GUI implementation details from ParaView:
161 \li SALOME GUI executable and Qt event loop
162 \li SALOME GUI desktop
163 \li Dock windows areas
164 \li SALOME menu and toolbar managers
166 Major part of the integration is implemented in PVGUI_Module class.
168 <h3>ParaView client initalization</h3>
170 ParaView client initalization is performed when an instance of PVGUI_Module class has been created
171 and \link PVGUI_Module::initialize() PVGUI_Module::initialize()\endlink method is called by SALOME GUI.
172 The actual client start-up is done in \link PVGUI_Module::pvInit() PVGUI_Module::pvInit()\endlink method.
175 <h3>Multi-view manager</h3>
177 SALOME GUI requires that each kind of view be implemnted with help of (at least) three classes. For ParaView multi-view manager
180 \li PVGUI_ViewManager - view manager class
181 \li PVGUI_Viewer - view model class
182 \li PVGUI_ViewWindow - view window class that acts as a parent for %pqViewManager
184 Single instances of PVGUI_ViewManager and PVGUI_ViewWindow classes are created by \link PVGUI_Module::showView()
185 PVGUI_Module::showView()\endlink method upon the first PARAVIS module activation. The same method hides the multi-view manager
186 when the module is deactivated (the user switches to another module or a study is closed).
187 A special trick is used to make PVGUI_ViewWindow the parent of %pqViewManager widget. It is created initally by %pqMainWindowCore
188 with the desktop as a parent, so when it is shown PVGUI_ViewWindow instance is passed to its setParent() method. In
189 \link PVGUI_ViewWindow::~PVGUI_ViewWindow() PVGUI_ViewWindow::~PVGUI_ViewWindow()\endlink the parent is nullified to avoid deletion
190 of %pqViewManager widget that would break %pqMainWindowCore class.
192 <h3>ParaView plugins</h3>
193 ParaView server and client plugins are managed by %pqMainWindowCore slots that has full access to PARAVIS menus and toolbars.
194 As a result they appears automatically in PARAVIS menus and toolbars if loaded successfully.
199 \brief Implementation
200 SALOME module wrapping ParaView GUI.
204 ClientFindOrCreateParavisComponent(_PTR(Study) theStudyDocument)
206 _PTR(SComponent) aSComponent = theStudyDocument->FindComponent("PARAVIS");
208 _PTR(StudyBuilder) aStudyBuilder = theStudyDocument->NewBuilder();
209 aStudyBuilder->NewCommand();
210 int aLocked = theStudyDocument->GetProperties()->IsLocked();
211 if (aLocked) theStudyDocument->GetProperties()->SetLocked(false);
212 aSComponent = aStudyBuilder->NewComponent("PARAVIS");
213 _PTR(GenericAttribute) anAttr =
214 aStudyBuilder->FindOrCreateAttribute(aSComponent, "AttributeName");
215 _PTR(AttributeName) aName (anAttr);
217 ORB_INIT& init = *SINGLETON_<ORB_INIT>::Instance();
218 CORBA::ORB_var anORB = init( qApp->argc(), qApp->argv() );
220 SALOME_NamingService *NamingService = new SALOME_NamingService( anORB );
221 CORBA::Object_var objVarN = NamingService->Resolve("/Kernel/ModulCatalog");
222 SALOME_ModuleCatalog::ModuleCatalog_var Catalogue =
223 SALOME_ModuleCatalog::ModuleCatalog::_narrow(objVarN);
224 SALOME_ModuleCatalog::Acomponent_var Comp = Catalogue->GetComponent( "PARAVIS" );
225 if (!Comp->_is_nil()) {
226 aName->SetValue(Comp->componentusername());
229 anAttr = aStudyBuilder->FindOrCreateAttribute(aSComponent, "AttributePixMap");
230 _PTR(AttributePixMap) aPixmap (anAttr);
231 aPixmap->SetPixMap( "pqAppIcon16.png" );
233 // Create Attribute parameters for future using
234 anAttr = aStudyBuilder->FindOrCreateAttribute(aSComponent, "AttributeParameter");
236 aStudyBuilder->DefineComponentInstance(aSComponent, PVGUI_Module::GetEngine()->GetIOR());
237 if (aLocked) theStudyDocument->GetProperties()->SetLocked(true);
238 aStudyBuilder->CommitCommand();
244 Clean up function; used to stop ParaView progress events when
245 exception is caught by global exception handler.
247 void paravisCleanUp()
249 if ( pqApplicationCore::instance() ) {
250 pqServer* s = pqApplicationCore::instance()->getActiveServer();
251 if ( s ) s->session()->GetProgressHandler()->CleanupPendingProgress();
256 \brief Constructor. Sets the default name for the module.
258 PVGUI_Module::PVGUI_Module()
259 : SalomeApp_Module( "PARAVIS" ),
260 mySelectionControlsTb( -1 ),
261 mySourcesMenuId( -1 ),
262 myFiltersMenuId( -1 ),
264 myToolbarsMenuId(-1),
273 Q_INIT_RESOURCE( PVGUI );
275 ParavisModule = this;
277 // Clear old copies of embedded macros files
278 QString aDestPath = QString( "%1/.config/%2/Macros" ).arg( QDir::homePath() ).arg( QApplication::applicationName() );
282 QDir aDestDir(aDestPath);
283 QStringList aDestFiles = aDestDir.entryList(aFilter, QDir::Files);
284 foreach (QString aMacrosPath, getEmbeddedMacrosList()) {
285 QString aMacrosName = QFileInfo(aMacrosPath).fileName();
286 if (aDestFiles.contains(aMacrosName)) {
287 aDestDir.remove(aMacrosName);
295 PVGUI_Module::~PVGUI_Module()
297 if (myPushTraceTimer)
298 delete myPushTraceTimer;
303 PARAVIS_ORB::PARAVIS_Gen_var PVGUI_Module::GetEngine()
305 return PVViewer_ViewManager::GetEngine();
308 pqPVApplicationCore * PVGUI_Module::GetPVApplication()
310 return PVViewer_ViewManager::GetPVApplication();
314 \brief Initialize module. Creates menus, prepares context menu, etc.
315 \param app SALOME GUI application instance
317 void PVGUI_Module::initialize( CAM_Application* app )
319 SalomeApp_Module::initialize( app );
321 // Create ParaViS actions
323 // Create ParaViS menus
326 // Uncomment to debug ParaView initialization
327 // "aa" used instead of "i" as GDB doesn't like "i" variables :)
335 SalomeApp_Application* anApp = getApp();
336 SUIT_Desktop* aDesktop = anApp->desktop();
338 // Initialize ParaView client and associated behaviors
339 // and connect to externally launched pvserver
340 PVViewer_ViewManager::ParaviewInitApp(aDesktop);
342 // Remember current state of desktop toolbars
343 QList<QToolBar*> foreignToolbars = aDesktop->findChildren<QToolBar*>();
347 // Behaviors and connection must be instanciated *after* widgets are in place
348 // In PARAVIS module we do not wait for PVViewer_ViewWindow to be instanciated to have this:
349 PVViewer_ViewManager::ParaviewInitBehaviors(true, aDesktop);
350 PVViewer_ViewManager::ConnectToExternalPVServer(aDesktop);
356 QList<QDockWidget*> activeDocks = aDesktop->findChildren<QDockWidget*>();
357 QList<QMenu*> activeMenus = aDesktop->findChildren<QMenu*>();
359 // Setup quick-launch shortcuts.
360 QShortcut *ctrlSpace = new QShortcut(Qt::CTRL + Qt::Key_Space, aDesktop);
361 QObject::connect(ctrlSpace, SIGNAL(activated()),
362 pqApplicationCore::instance(), SLOT(quickLaunch()));
364 // Find Plugin Dock Widgets
365 QList<QDockWidget*> currentDocks = aDesktop->findChildren<QDockWidget*>();
366 QList<QDockWidget*>::iterator i;
367 for (i = currentDocks.begin(); i != currentDocks.end(); ++i) {
368 if(!activeDocks.contains(*i)) {
369 myDockWidgets[*i] = false; // hidden by default
375 // [ABN] TODO: fix this - triggers a SEGFAULT at deactivation() time.
376 // QList<QMenu*> currentMenus = aDesktop->findChildren<QMenu*>();
377 // QList<QMenu*>::iterator im;
378 // for (im = currentMenus.begin(); im != currentMenus.end(); ++im) {
379 // if(!activeMenus.contains(*im)) {
380 // QString s = (*im)->title();
381 // std::cout << " MENU "<< s.toStdString() << std::endl;
382 // myMenus.append(*im);
386 PVViewer_ViewManager::ParaviewLoadConfigurations();
389 // Find created toolbars
390 QCoreApplication::processEvents();
392 QList<QToolBar*> allToolbars = aDesktop->findChildren<QToolBar*>();
393 foreach(QToolBar* aBar, allToolbars) {
394 if (!foreignToolbars.contains(aBar)) {
395 myToolbars[aBar] = true;
396 myToolbarBreaks[aBar] = false;
397 aBar->setVisible(false);
398 aBar->toggleViewAction()->setVisible(false);
404 SUIT_ResourceMgr* aResourceMgr = SUIT_Session::session()->resourceMgr();
405 bool isStop = aResourceMgr->booleanValue( "PARAVIS", "stop_trace", false );
408 // Start a timer to schedule asap:
410 myInitTimer = new QTimer(aDesktop);
411 QObject::connect(myInitTimer, SIGNAL(timeout()), this, SLOT(onInitTimer()) );
412 myInitTimer->setSingleShot(true);
413 myInitTimer->start(0);
415 // Another timer to regularly push the trace onto the engine:
416 myPushTraceTimer = new QTimer(aDesktop);
417 QObject::connect(myPushTraceTimer, SIGNAL(timeout()), this, SLOT(onPushTraceTimer()) );
418 myPushTraceTimer->setSingleShot(false);
419 myPushTraceTimer->start(500);
422 this->VTKConnect = vtkEventQtSlotConnect::New();
424 vtkProcessModule* pm = vtkProcessModule::GetProcessModule();
426 vtkPVSession* pvs = dynamic_cast<vtkPVSession*>(pm->GetSession());
428 vtkPVProgressHandler* ph = pvs->GetProgressHandler();
430 this->VTKConnect->Connect(ph, vtkCommand::StartEvent,
431 this, SLOT(onStartProgress()));
432 this->VTKConnect->Connect(ph, vtkCommand::EndEvent,
433 this, SLOT(onEndProgress()));
439 void PVGUI_Module::onStartProgress()
441 QApplication::setOverrideCursor(Qt::WaitCursor);
444 void PVGUI_Module::onEndProgress()
446 QApplication::restoreOverrideCursor();
449 void PVGUI_Module::onDataRepresentationUpdated() {
450 SalomeApp_Study* activeStudy = dynamic_cast<SalomeApp_Study*>(application()->activeStudy());
451 if(!activeStudy) return;
453 activeStudy->Modified();
457 \brief Initialisation timer event - trace start up
459 void PVGUI_Module::onInitTimer()
465 \brief Get list of embedded macros files
467 QStringList PVGUI_Module::getEmbeddedMacrosList()
469 QString aRootDir = getenv("PARAVIS_ROOT_DIR");
471 QString aSourcePath = aRootDir + "/bin/salome/Macro";
476 QDir aSourceDir(aSourcePath);
477 QStringList aSourceFiles = aSourceDir.entryList(aFilter, QDir::Files);
478 QStringList aFullPathSourceFiles;
479 foreach (QString aMacrosName, aSourceFiles) {
480 aFullPathSourceFiles << aSourceDir.absoluteFilePath(aMacrosName);
482 return aFullPathSourceFiles;
485 void PVGUI_Module::updateMacros()
487 pqPythonManager* aPythonManager = pqPVApplicationCore::instance()->pythonManager();
488 if(!aPythonManager) {
492 foreach (QString aStr, getEmbeddedMacrosList()) {
493 aPythonManager->addMacro(aStr);
499 \brief Get list of compliant dockable GUI elements
500 \param m map to be filled in ("type":"default_position")
502 void PVGUI_Module::windows( QMap<int, int>& m ) const
504 m.insert( LightApp_Application::WT_ObjectBrowser, Qt::LeftDockWidgetArea );
505 m.insert( LightApp_Application::WT_PyConsole, Qt::BottomDockWidgetArea );
506 // ParaView diagnostic output redirected here
507 m.insert( LightApp_Application::WT_LogWindow, Qt::BottomDockWidgetArea );
511 \brief Shows (toShow = true) or hides ParaView view window
513 void PVGUI_Module::showView( bool toShow )
515 SalomeApp_Application* anApp = getApp();
516 PVViewer_ViewManager* viewMgr =
517 dynamic_cast<PVViewer_ViewManager*>( anApp->getViewManager( PVViewer_Viewer::Type(), false ) );
519 viewMgr = new PVViewer_ViewManager( anApp->activeStudy(), anApp->desktop() );
520 anApp->addViewManager( viewMgr );
521 connect( viewMgr, SIGNAL( lastViewClosed( SUIT_ViewManager* ) ),
522 anApp, SLOT( onCloseView( SUIT_ViewManager* ) ) );
525 PVViewer_ViewWindow* pvWnd = dynamic_cast<PVViewer_ViewWindow*>( viewMgr->getActiveView() );
527 pvWnd = dynamic_cast<PVViewer_ViewWindow*>( viewMgr->createViewWindow() );
528 // this also connects to the pvserver and instantiates relevant PV behaviors
531 pvWnd->setShown( toShow );
532 if ( toShow ) pvWnd->setFocus();
536 \brief Slot to show help for proxy.
538 void PVGUI_Module::showHelpForProxy( const QString& groupname, const QString& proxyname )
540 pqHelpReaction::showProxyHelp(groupname, proxyname);
545 \brief Slot to show the waiting state.
547 void PVGUI_Module::onPreAccept()
549 getApp()->desktop()->statusBar()->showMessage(tr("STB_PREACCEPT"));
550 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
554 \brief Slot to show the ready state.
556 void PVGUI_Module::onPostAccept()
558 getApp()->desktop()->statusBar()->showMessage(tr("STB_POSTACCEPT"), 2000);
559 QTimer::singleShot(0, this, SLOT(endWaitCursor()));
563 \brief Slot to switch off wait cursor.
565 void PVGUI_Module::endWaitCursor()
567 QApplication::restoreOverrideCursor();
570 static void ParavisMessageOutput(QtMsgType type, const char *msg)
575 vtkOutputWindow::GetInstance()->DisplayText(msg);
578 vtkOutputWindow::GetInstance()->DisplayErrorText(msg);
581 vtkOutputWindow::GetInstance()->DisplayErrorText(msg);
584 vtkOutputWindow::GetInstance()->DisplayErrorText(msg);
590 \brief Activate module.
591 \param study current study
592 \return \c true if activaion is done successfully or 0 to prevent
595 bool PVGUI_Module::activateModule( SUIT_Study* study )
597 myOldMsgHandler = qInstallMsgHandler(ParavisMessageOutput);
599 SUIT_ExceptionHandler::addCleanUpRoutine( paravisCleanUp );
601 storeCommonWindowsState();
603 bool isDone = SalomeApp_Module::activateModule( study );
604 if ( !isDone ) return false;
606 showView( true ); // this will also trigger the connection to the server
607 // and the instanciation of the relevant PV behaviors
608 if ( mySourcesMenuId != -1 ) menuMgr()->show(mySourcesMenuId);
609 if ( myFiltersMenuId != -1 ) menuMgr()->show(myFiltersMenuId);
610 if ( myFiltersMenuId != -1 ) menuMgr()->show(myMacrosMenuId);
611 if ( myFiltersMenuId != -1 ) menuMgr()->show(myToolbarsMenuId);
612 setMenuShown( true );
613 setToolShown( true );
615 restoreDockWidgetsState();
617 QMenu* aMenu = menuMgr()->findMenu( myRecentMenuId );
619 QList<QAction*> anActns = aMenu->actions();
620 for (int i = 0; i < anActns.size(); ++i) {
621 QAction* a = anActns.at(i);
627 QList<QMenu*>::iterator it;
628 for (it = myMenus.begin(); it != myMenus.end(); ++it) {
629 QAction* a = (*it)->menuAction();
634 if ( myRecentMenuId != -1 ) menuMgr()->show(myRecentMenuId);
636 ClientFindOrCreateParavisComponent(PARAVIS::GetCStudy(this));
643 \brief Deactivate module.
644 \param study current study
645 \return \c true if deactivaion is done successfully or 0 to prevent
646 deactivation on error
648 bool PVGUI_Module::deactivateModule( SUIT_Study* study )
650 MESSAGE("PARAVIS deactivation ...")
652 QMenu* aMenu = menuMgr()->findMenu( myRecentMenuId );
654 QList<QAction*> anActns = aMenu->actions();
655 for (int i = 0; i < anActns.size(); ++i) {
656 QAction* a = anActns.at(i);
658 a->setVisible(false);
662 QList<QMenu*>::iterator it;
663 for (it = myMenus.begin(); it != myMenus.end(); ++it) {
664 QAction* a = (*it)->menuAction();
666 a->setVisible(false);
669 QList<QDockWidget*> aStreamingViews = application()->desktop()->findChildren<QDockWidget*>("pqStreamingControls");
670 foreach(QDockWidget* aView, aStreamingViews) {
671 if (!myDockWidgets.contains(aView))
672 myDockWidgets[aView] = aView->isVisible();
675 /*if (pqImplementation::helpWindow) {
676 pqImplementation::helpWindow->hide();
680 menuMgr()->hide(myRecentMenuId);
681 menuMgr()->hide(mySourcesMenuId);
682 menuMgr()->hide(myFiltersMenuId);
683 menuMgr()->hide(myMacrosMenuId);
684 menuMgr()->hide(myToolbarsMenuId);
685 setMenuShown( false );
686 setToolShown( false );
688 saveDockWidgetsState();
690 SUIT_ExceptionHandler::removeCleanUpRoutine( paravisCleanUp );
693 qInstallMsgHandler(myOldMsgHandler);
695 restoreCommonWindowsState();
697 return SalomeApp_Module::deactivateModule( study );
702 \brief Called when application is closed.
704 Process finalize application functionality from ParaView in order to save server settings
705 and nullify application pointer if the application is being closed.
707 \param theApp application
709 void PVGUI_Module::onApplicationClosed( SUIT_Application* theApp )
711 PVViewer_ViewManager::ParaviewCleanup();
713 int aAppsNb = SUIT_Session::session()->applications().size();
715 deleteTemporaryFiles();
717 CAM_Module::onApplicationClosed(theApp);
722 \brief Deletes temporary files created during import operation from VISU
724 void PVGUI_Module::deleteTemporaryFiles()
726 foreach(QString aFile, myTemporaryFiles) {
727 if (QFile::exists(aFile)) {
728 QFile::remove(aFile);
735 \brief Called when study is closed.
737 Removes data model from the \a study.
739 \param study study being closed
741 void PVGUI_Module::studyClosed(SUIT_Study* study)
743 clearParaviewState();
745 SalomeApp_Module::studyClosed(study);
749 \brief Called when study is opened.
751 void PVGUI_Module::onModelOpened()
753 _PTR(Study) studyDS = PARAVIS::GetCStudy(this);
758 _PTR(SComponent) paravisComp =
759 studyDS->FindComponent(GetEngine()->ComponentDataType());
764 _PTR(ChildIterator) anIter(studyDS->NewChildIterator(paravisComp));
765 for (; anIter->More(); anIter->Next()) {
766 _PTR(SObject) aSObj = anIter->Value();
767 _PTR(GenericAttribute) anAttr;
768 if (!aSObj->FindAttribute(anAttr, "AttributeLocalID")) {
771 _PTR(AttributeLocalID) anID(anAttr);
772 if (anID->Value() == PVSTATEID) {
779 \brief Returns IOR of current engine
781 QString PVGUI_Module::engineIOR() const
783 CORBA::String_var anIOR = GetEngine()->GetIOR();
784 return QString(anIOR.in());
788 \brief Open file of format supported by ParaView
790 void PVGUI_Module::openFile(const char* theName)
794 pqLoadDataReaction::loadData(aFiles);
798 * Start trace invoking the newly introduced C++ API (PV 4.2)
799 * (inspired from pqTraceReaction::start())
801 void PVGUI_Module::startTrace()
803 vtkSMSessionProxyManager* pxm = pqActiveObjects::instance().activeServer()->proxyManager();
805 vtkSmartPointer<vtkSMProxy> proxy;
806 proxy.TakeReference(pxm->NewProxy("pythontracing", "PythonTraceOptions"));
809 vtkNew<vtkSMParaViewPipelineController> controller;
810 controller->InitializeProxy(proxy);
812 vtkSMTrace* trace = vtkSMTrace::StartTrace();
815 // Set manually the properties entered via the dialog box poping-up when requiring
816 // a trace start in PV4.2 (trace options)
817 trace->SetPropertiesToTraceOnCreate(vtkSMTrace::RECORD_USER_MODIFIED_PROPERTIES);
818 trace->SetFullyTraceSupplementalProxies(false);
822 void PVGUI_Module::stopTrace()
824 vtkSMTrace::StopTrace();
827 void PVGUI_Module::executeScript(const char *script)
830 pqPythonManager* manager = qobject_cast<pqPythonManager*>(
831 pqApplicationCore::instance()->manager("PYTHON_MANAGER"));
833 pqPythonDialog* pyDiag = manager->pythonShellDialog();
835 pyDiag->runString(script);
842 // * Debug function printing out the given interpreter's execution context
844 //void printInterpContext(PyInterp_Interp * interp )
846 // // Extract __smtraceString from interpreter's context
847 // const PyObject* ctxt = interp->getExecutionContext();
849 // PyObject* lst = PyDict_Keys((PyObject *)ctxt);
850 // Py_ssize_t siz = PyList_GET_SIZE(lst);
851 // for (Py_ssize_t i = 0; i < siz; i++)
853 // PyObject * elem = PyList_GetItem(lst, i);
854 // if (PyString_Check(elem))
856 // std::cout << "At pos:" << i << ", " << PyString_AsString(elem) << std::endl;
859 // std::cout << "At pos:" << i << ", not a string!" << std::endl;
865 \brief Returns trace string
867 static const QString MYReplaceStr("paraview.simple");
868 static const QString MYReplaceImportStr("except: from pvsimple import *");
869 QString PVGUI_Module::getTraceString()
871 vtkSMTrace *tracer = vtkSMTrace::GetActiveTracer();
872 if (!tracer) // trace is not started
875 QString traceString(tracer->GetCurrentTrace());
877 // Replace import "paraview.simple" by "pvsimple"
878 if ((!traceString.isNull()) && traceString.length() != 0) {
879 int aPos = traceString.indexOf(MYReplaceStr);
881 traceString = traceString.replace(aPos, MYReplaceStr.length(), "pvsimple");
882 aPos = traceString.indexOf(MYReplaceStr, aPos);
884 int aImportPos = traceString.indexOf(MYReplaceImportStr);
887 traceString = traceString.replace(aImportPos, MYReplaceImportStr.length(), "except:\n import pvsimple\n from pvsimple import *");
895 \brief Saves trace string to disk file
897 void PVGUI_Module::saveTrace(const char* theName)
900 if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
901 MESSAGE( "Could not open file:" << theName );
904 QTextStream out(&file);
905 out << getTraceString();
910 \brief Saves ParaView state to a disk file
912 void PVGUI_Module::saveParaviewState(const char* theFileName)
914 pqApplicationCore::instance()->saveState(theFileName);
918 \brief Delete all objects for Paraview Pipeline Browser
920 void PVGUI_Module::clearParaviewState()
922 QAction* deleteAllAction = action(DeleteAllId);
923 if (deleteAllAction) {
924 deleteAllAction->activate(QAction::Trigger);
929 \brief Restores ParaView state from a disk file
931 If toClear == true, the current ojects will be deleted
933 void PVGUI_Module::loadParaviewState(const char* theFileName)
935 pqApplicationCore::instance()->loadState(theFileName, getActiveServer());
939 \brief Returns current active ParaView server
941 pqServer* PVGUI_Module::getActiveServer()
943 return pqApplicationCore::instance()->getActiveServer();
948 \brief Creates PARAVIS preference pane
950 void PVGUI_Module::createPreferences()
952 // Paraview settings tab
953 int aParaViewSettingsTab = addPreference( tr( "TIT_PVIEWSETTINGS" ) );
954 int aPanel = addPreference(QString(), aParaViewSettingsTab, LightApp_Preferences::UserDefined, "PARAVIS", "");
955 setPreferenceProperty(aPanel, "content", (qint64)(new PVGUI_ParaViewSettingsPane()));
957 // Paravis settings tab
958 int aParaVisSettingsTab = addPreference( tr( "TIT_PVISSETTINGS" ) );
959 addPreference( tr( "PREF_STOP_TRACE" ), aParaVisSettingsTab, LightApp_Preferences::Bool, "PARAVIS", "stop_trace");
961 addPreference( tr( "PREF_NO_EXT_PVSERVER" ), aParaVisSettingsTab, LightApp_Preferences::Bool, "PARAVIS", "no_ext_pv_server");
963 int aSaveType = addPreference(tr( "PREF_SAVE_TYPE_LBL" ), aParaVisSettingsTab,
964 LightApp_Preferences::Selector,
965 "PARAVIS", "savestate_type");
966 QList<QVariant> aIndices;
967 QStringList aStrings;
969 aStrings<<tr("PREF_SAVE_TYPE_0");
970 aStrings<<tr("PREF_SAVE_TYPE_1");
971 aStrings<<tr("PREF_SAVE_TYPE_2");
972 setPreferenceProperty(aSaveType, "strings", aStrings);
973 setPreferenceProperty(aSaveType, "indexes", aIndices);
977 \brief Creates ParaViS context menu popup
979 void PVGUI_Module::contextMenuPopup(const QString& theClient, QMenu* theMenu, QString& theTitle)
981 SalomeApp_Module::contextMenuPopup(theClient, theMenu, theTitle);
983 // Check if we are in Object Browser
984 SUIT_DataBrowser* ob = getApp()->objectBrowser();
985 bool isOBClient = (ob && theClient == ob->popupClientType());
990 // Get list of selected objects
991 LightApp_SelectionMgr* aSelectionMgr = getApp()->selectionMgr();
992 SALOME_ListIO aListIO;
993 aSelectionMgr->selectedObjects(aListIO);
994 if (aListIO.Extent() == 1 && aListIO.First()->hasEntry()) {
995 QString entry = QString(aListIO.First()->getEntry());
998 SalomeApp_Study* activeStudy =
999 dynamic_cast<SalomeApp_Study*>(getApp()->activeStudy());
1004 // Get SALOMEDS client study
1005 _PTR(Study) studyDS = activeStudy->studyDS();
1010 QString paravisDataType(GetEngine()->ComponentDataType());
1011 if(activeStudy && activeStudy->isComponent(entry) &&
1012 activeStudy->componentDataType(entry) == paravisDataType) {
1013 // ParaViS module object
1014 theMenu->addSeparator();
1015 theMenu->addAction(action(SaveStatePopupId));
1018 // Try to get state object
1019 _PTR(SObject) stateSObj =
1020 studyDS->FindObjectID(entry.toLatin1().constData());
1026 _PTR(GenericAttribute) anAttr;
1027 if (!stateSObj->FindAttribute(anAttr, "AttributeLocalID")) {
1031 _PTR(AttributeLocalID) anID(anAttr);
1033 if (anID->Value() == PVSTATEID) {
1034 // Paraview state object
1035 theMenu->addSeparator();
1036 theMenu->addAction(action(AddStatePopupId));
1037 theMenu->addAction(action(CleanAndAddStatePopupId));
1038 theMenu->addSeparator();
1039 theMenu->addAction(action(ParaVisRenameId));
1040 theMenu->addAction(action(ParaVisDeleteId));
1047 \brief. Show ParaView python trace.
1049 void PVGUI_Module::onShowTrace()
1051 if (!myTraceWindow) {
1052 myTraceWindow = new pqPythonScriptEditor(getApp()->desktop());
1054 myTraceWindow->setText(getTraceString());
1055 myTraceWindow->show();
1056 myTraceWindow->raise();
1057 myTraceWindow->activateWindow();
1062 \brief. Re-initialize ParaView python trace.
1064 void PVGUI_Module::onRestartTrace()
1071 \brief Show ParaView view.
1073 void PVGUI_Module::onNewParaViewWindow()
1079 \brief Save state under the module root object.
1081 void PVGUI_Module::onSaveMultiState()
1083 // Create state study object
1085 // Get SALOMEDS client study
1086 _PTR(Study) studyDS = PARAVIS::GetCStudy(this);
1091 _PTR(SComponent) paravisComp =
1092 studyDS->FindComponent(GetEngine()->ComponentDataType());
1097 // Unlock the study if it is locked
1098 bool isLocked = studyDS->GetProperties()->IsLocked();
1100 studyDS->GetProperties()->SetLocked(false);
1103 QString stateName = tr("SAVED_PARAVIEW_STATE_NAME") +
1104 QString::number(myStateCounter + 1);
1106 _PTR(StudyBuilder) studyBuilder = studyDS->NewBuilder();
1107 _PTR(SObject) newSObj = studyBuilder->NewObject(paravisComp);
1110 _PTR(GenericAttribute) anAttr;
1111 anAttr = studyBuilder->FindOrCreateAttribute(newSObj, "AttributeName");
1112 _PTR(AttributeName) nameAttr(anAttr);
1114 nameAttr->SetValue(stateName.toLatin1().constData());
1117 anAttr = studyBuilder->FindOrCreateAttribute(newSObj, "AttributeLocalID");
1118 _PTR(AttributeLocalID) localIdAttr(anAttr);
1120 localIdAttr->SetValue(PVSTATEID);
1123 QString stateEntry = QString::fromStdString(newSObj->GetID());
1125 // File name for state saving
1126 QString tmpDir = QString::fromStdString(SALOMEDS_Tool::GetTmpDir());
1127 QString fileName = QString("%1_paravisstate:%2").arg(tmpDir, stateEntry);
1129 anAttr = studyBuilder->FindOrCreateAttribute(newSObj, "AttributeString");
1130 _PTR(AttributeString) stringAttr(anAttr);
1132 stringAttr->SetValue(fileName.toLatin1().constData());
1134 // Lock the study back if necessary
1136 studyDS->GetProperties()->SetLocked(true);
1140 saveParaviewState(fileName.toLatin1().constData());
1141 myTemporaryFiles.append(fileName);
1143 // Increment the counter
1150 \brief Restore the selected state by merging with the current one.
1152 void PVGUI_Module::onAddState()
1154 loadSelectedState(false);
1158 \brief Clean the current state and restore the selected one.
1160 void PVGUI_Module::onCleanAddState()
1162 loadSelectedState(true);
1166 \brief Rename the selected object.
1168 void PVGUI_Module::onRename()
1170 LightApp_SelectionMgr* aSelectionMgr = getApp()->selectionMgr();
1171 SALOME_ListIO aListIO;
1172 aSelectionMgr->selectedObjects(aListIO);
1174 if (aListIO.Extent() == 1 && aListIO.First()->hasEntry()) {
1175 std::string entry = aListIO.First()->getEntry();
1177 // Get SALOMEDS client study
1178 _PTR(Study) studyDS = PARAVIS::GetCStudy(this);
1183 // Unlock the study if it is locked
1184 bool isLocked = studyDS->GetProperties()->IsLocked();
1186 studyDS->GetProperties()->SetLocked(false);
1189 // Rename the selected state object
1190 _PTR(SObject) stateSObj = studyDS->FindObjectID(entry);
1195 _PTR(GenericAttribute) anAttr;
1196 if (stateSObj->FindAttribute(anAttr, "AttributeName")) {
1197 _PTR(AttributeName) nameAttr (anAttr);
1199 LightApp_NameDlg::getName(getApp()->desktop(), nameAttr->Value().c_str());
1200 if (!newName.isEmpty()) {
1201 nameAttr->SetValue(newName.toLatin1().constData());
1202 aListIO.First()->setName(newName.toLatin1().constData());
1206 // Lock the study back if necessary
1208 studyDS->GetProperties()->SetLocked(true);
1211 // Update object browser
1218 \brief Delete the selected objects.
1220 void PVGUI_Module::onDelete()
1222 LightApp_SelectionMgr* aSelectionMgr = getApp()->selectionMgr();
1223 SALOME_ListIO aListIO;
1224 aSelectionMgr->selectedObjects(aListIO);
1226 if (aListIO.Extent() == 1 && aListIO.First()->hasEntry()) {
1227 std::string entry = aListIO.First()->getEntry();
1229 // Get SALOMEDS client study
1230 _PTR(Study) studyDS = PARAVIS::GetCStudy(this);
1235 // Unlock the study if it is locked
1236 bool isLocked = studyDS->GetProperties()->IsLocked();
1238 studyDS->GetProperties()->SetLocked(false);
1241 // Remove the selected state from the study
1242 _PTR(StudyBuilder) studyBuilder = studyDS->NewBuilder();
1243 _PTR(SObject) stateSObj = studyDS->FindObjectID(entry);
1244 studyBuilder->RemoveObject(stateSObj);
1246 // Lock the study back if necessary
1248 studyDS->GetProperties()->SetLocked(true);
1251 // Update object browser
1256 void PVGUI_Module::onPushTraceTimer()
1258 // MESSAGE("onPushTraceTimer(): Pushing trace to engine...");
1259 GetEngine()->PutPythonTraceStringToEngine(getTraceString().toStdString().c_str());
1263 \brief Discover help project files from the resources.
1264 \return name of the help file.
1266 QString PVGUI_Module::getHelpFileName() {
1267 QString aPVHome(getenv("PVHOME"));
1268 if (aPVHome.isNull()) {
1269 qWarning("Wariable PVHOME is not defined");
1272 QChar aSep = QDir::separator();
1273 //PARAVIEW_VERSION from the vtkPVConfig.h file
1274 QString aFileName = aPVHome + aSep + "share" + aSep + "doc" + aSep + "paraview-"+ PARAVIEW_VERSION + aSep + "paraview.qch";
1280 \brief Load selected paraview state
1282 If toClear == true, the current state will be cleared
1284 void PVGUI_Module::loadSelectedState(bool toClear)
1288 LightApp_SelectionMgr* aSelectionMgr = getApp()->selectionMgr();
1289 SALOME_ListIO aListIO;
1290 aSelectionMgr->selectedObjects(aListIO);
1292 if (aListIO.Extent() == 1 && aListIO.First()->hasEntry()) {
1293 std::string entry = aListIO.First()->getEntry();
1295 // Get SALOMEDS client study
1296 _PTR(Study) studyDS = PARAVIS::GetCStudy(this);
1302 _PTR(SObject) stateSObj = studyDS->FindObjectID(entry);
1303 _PTR(GenericAttribute) anAttr;
1304 if (!stateSObj->FindAttribute(anAttr, "AttributeLocalID")) {
1307 _PTR(AttributeLocalID) anID(anAttr);
1308 if (!anID->Value() == PVSTATEID) {
1312 // Get state file name
1313 if (stateSObj->FindAttribute(anAttr, "AttributeString")) {
1314 _PTR(AttributeString) aStringAttr(anAttr);
1315 QString stringValue(aStringAttr->Value().c_str());
1317 if (QFile::exists(stringValue)) {
1318 fileName = stringValue;
1323 if (!fileName.isEmpty()) {
1325 clearParaviewState();
1328 loadParaviewState(fileName.toLatin1().constData());
1331 SUIT_MessageBox::critical(getApp()->desktop(),
1333 tr("ERR_STATE_CANNOT_BE_RESTORED"));
1338 \fn CAM_Module* createModule();
1339 \brief Export module instance (factory function).
1340 \return new created instance of the module
1344 #define PVGUI_EXPORT __declspec(dllexport)
1346 #define PVGUI_EXPORT
1352 PVGUI_EXPORT CAM_Module* createModule() {
1353 return new PVGUI_Module();
1356 PVGUI_EXPORT char* getModuleVersion() {
1357 return (char*)PARAVIS_VERSION_STR;