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"
45 #include <SUIT_DataBrowser.h>
46 #include <SUIT_Desktop.h>
47 #include <SUIT_MessageBox.h>
48 #include <SUIT_ResourceMgr.h>
49 #include <SUIT_Session.h>
50 #include <SUIT_OverrideCursor.h>
51 #include <SUIT_ExceptionHandler.h>
53 #include <SALOME_LifeCycleCORBA.hxx>
54 #include <SALOMEDS_SObject.hxx>
56 #include <LightApp_SelectionMgr.h>
57 #include <LightApp_NameDlg.h>
58 #include <SalomeApp_Application.h>
59 #include <SalomeApp_Study.h>
60 #include <SALOME_ListIO.hxx>
61 #include <SALOMEDS_Tool.hxx>
62 #include <Utils_ORB_INIT.hxx>
63 #include <Utils_SINGLETON.hxx>
65 #include <QtxActionMenuMgr.h>
66 #include <QtxActionToolMgr.h>
68 #include <PARAVIS_version.h>
74 #include <QApplication>
80 #include <QInputDialog>
84 #include <QStringList>
87 #include <QTextStream>
89 #include <QDockWidget>
90 #include <QHelpEngine>
93 #include <vtkPVConfig.h> // for symbol PARAVIEW_VERSION
94 #include <vtkProcessModule.h>
95 #include <vtkPVSession.h>
96 #include <vtkPVProgressHandler.h>
97 #include <vtkOutputWindow.h>
98 #include <vtkEventQtSlotConnect.h>
100 #include <vtkSMProxy.h>
101 #include <vtkSmartPointer.h>
102 #include <vtkSMSession.h>
103 #include <vtkSMTrace.h>
104 #include <vtkSMSessionProxyManager.h>
105 #include <vtkSMParaViewPipelineController.h>
107 #include <pqApplicationCore.h>
108 #include <pqPVApplicationCore.h>
109 #include <pqActiveView.h>
110 #include <pqObjectBuilder.h>
111 #include <pqOptions.h>
112 #include <pqSettings.h>
113 #include <pqServer.h>
114 #include <pqUndoStack.h>
115 #include <pqTabbedMultiViewWidget.h>
116 #include <pqActiveObjects.h>
117 #include <pqHelpReaction.h>
118 #include <pqPluginManager.h>
119 #include <pqPythonDialog.h>
120 #include <pqPythonManager.h>
121 #include <pqLoadDataReaction.h>
122 #include <pqPythonScriptEditor.h>
123 #include <pqDataRepresentation.h>
124 #include <pqDisplayColorWidget.h>
125 #include <pqColorToolbar.h>
126 #include <pqScalarBarVisibilityReaction.h>
127 #include <pqServerResource.h>
128 #include <pqServerConnectReaction.h>
131 #include <PyInterp_Interp.h>
134 //----------------------------------------------------------------------------
135 PVGUI_Module* ParavisModule = 0;
140 <h2>Building and installing PARAVIS</h2>
141 As any other SALOME module, PARAVIS requires PARAVIS_ROOT_DIR environment variable to be set to PARAVIS
142 installation directory.
143 Other variables needed for correct detection of ParaView location:
144 \li PVHOME - points at the ParaView installation directory tree
145 \li PVVERSION - number of ParaView version
147 It also requires common SALOME environment including GUI_ROOT_DIR and other prerequsites.
150 PARAVIS module can be launched using the following commands:
151 \li Full SALOME configuration
153 runSalome --modules="PARAVIS"
156 <h2>ParaView GUI integration</h2>
157 <h3>ParaView GUI integration overview</h3>
159 The main idea is to reuse ParaView GUI internal logic as much as possible, providing a layer
160 between it and SALOME GUI that hides the following SALOME GUI implementation details from ParaView:
162 \li SALOME GUI executable and Qt event loop
163 \li SALOME GUI desktop
164 \li Dock windows areas
165 \li SALOME menu and toolbar managers
167 Major part of the integration is implemented in PVGUI_Module class.
169 <h3>ParaView client initalization</h3>
171 ParaView client initalization is performed when an instance of PVGUI_Module class has been created
172 and \link PVGUI_Module::initialize() PVGUI_Module::initialize()\endlink method is called by SALOME GUI.
173 The actual client start-up is done in \link PVGUI_Module::pvInit() PVGUI_Module::pvInit()\endlink method.
176 <h3>Multi-view manager</h3>
178 SALOME GUI requires that each kind of view be implemnted with help of (at least) three classes. For ParaView multi-view manager
181 \li PVGUI_ViewManager - view manager class
182 \li PVGUI_Viewer - view model class
183 \li PVGUI_ViewWindow - view window class that acts as a parent for %pqViewManager
185 Single instances of PVGUI_ViewManager and PVGUI_ViewWindow classes are created by \link PVGUI_Module::showView()
186 PVGUI_Module::showView()\endlink method upon the first PARAVIS module activation. The same method hides the multi-view manager
187 when the module is deactivated (the user switches to another module or a study is closed).
188 A special trick is used to make PVGUI_ViewWindow the parent of %pqViewManager widget. It is created initally by %pqMainWindowCore
189 with the desktop as a parent, so when it is shown PVGUI_ViewWindow instance is passed to its setParent() method. In
190 \link PVGUI_ViewWindow::~PVGUI_ViewWindow() PVGUI_ViewWindow::~PVGUI_ViewWindow()\endlink the parent is nullified to avoid deletion
191 of %pqViewManager widget that would break %pqMainWindowCore class.
193 <h3>ParaView plugins</h3>
194 ParaView server and client plugins are managed by %pqMainWindowCore slots that has full access to PARAVIS menus and toolbars.
195 As a result they appears automatically in PARAVIS menus and toolbars if loaded successfully.
200 \brief Implementation
201 SALOME module wrapping ParaView GUI.
205 ClientFindOrCreateParavisComponent(_PTR(Study) theStudyDocument)
207 _PTR(SComponent) aSComponent = theStudyDocument->FindComponent("PARAVIS");
209 _PTR(StudyBuilder) aStudyBuilder = theStudyDocument->NewBuilder();
210 aStudyBuilder->NewCommand();
211 int aLocked = theStudyDocument->GetProperties()->IsLocked();
212 if (aLocked) theStudyDocument->GetProperties()->SetLocked(false);
213 aSComponent = aStudyBuilder->NewComponent("PARAVIS");
214 _PTR(GenericAttribute) anAttr =
215 aStudyBuilder->FindOrCreateAttribute(aSComponent, "AttributeName");
216 _PTR(AttributeName) aName (anAttr);
218 ORB_INIT& init = *SINGLETON_<ORB_INIT>::Instance();
219 CORBA::ORB_var anORB = init( qApp->argc(), qApp->argv() );
221 SALOME_NamingService *NamingService = new SALOME_NamingService( anORB );
222 CORBA::Object_var objVarN = NamingService->Resolve("/Kernel/ModulCatalog");
223 SALOME_ModuleCatalog::ModuleCatalog_var Catalogue =
224 SALOME_ModuleCatalog::ModuleCatalog::_narrow(objVarN);
225 SALOME_ModuleCatalog::Acomponent_var Comp = Catalogue->GetComponent( "PARAVIS" );
226 if (!Comp->_is_nil()) {
227 aName->SetValue(Comp->componentusername());
230 anAttr = aStudyBuilder->FindOrCreateAttribute(aSComponent, "AttributePixMap");
231 _PTR(AttributePixMap) aPixmap (anAttr);
232 aPixmap->SetPixMap( "pqAppIcon16.png" );
234 // Create Attribute parameters for future using
235 anAttr = aStudyBuilder->FindOrCreateAttribute(aSComponent, "AttributeParameter");
237 aStudyBuilder->DefineComponentInstance(aSComponent, PVGUI_Module::GetEngine()->GetIOR());
238 if (aLocked) theStudyDocument->GetProperties()->SetLocked(true);
239 aStudyBuilder->CommitCommand();
245 Clean up function; used to stop ParaView progress events when
246 exception is caught by global exception handler.
248 void paravisCleanUp()
250 if ( pqApplicationCore::instance() ) {
251 pqServer* s = pqApplicationCore::instance()->getActiveServer();
252 if ( s ) s->session()->GetProgressHandler()->CleanupPendingProgress();
257 \brief Constructor. Sets the default name for the module.
259 PVGUI_Module::PVGUI_Module()
260 : SalomeApp_Module( "PARAVIS" ),
261 mySelectionControlsTb( -1 ),
262 mySourcesMenuId( -1 ),
263 myFiltersMenuId( -1 ),
265 myToolbarsMenuId(-1),
275 Q_INIT_RESOURCE( PVGUI );
277 ParavisModule = this;
279 // Clear old copies of embedded macros files
280 QString aDestPath = QString( "%1/.config/%2/Macros" ).arg( QDir::homePath() ).arg( QApplication::applicationName() );
284 QDir aDestDir(aDestPath);
285 QStringList aDestFiles = aDestDir.entryList(aFilter, QDir::Files);
286 foreach (QString aMacrosPath, getEmbeddedMacrosList()) {
287 QString aMacrosName = QFileInfo(aMacrosPath).fileName();
288 if (aDestFiles.contains(aMacrosName)) {
289 aDestDir.remove(aMacrosName);
297 PVGUI_Module::~PVGUI_Module()
299 if (myPushTraceTimer)
300 delete myPushTraceTimer;
305 PARAVIS_ORB::PARAVIS_Gen_var PVGUI_Module::GetEngine()
307 return PVViewer_ViewManager::GetEngine();
310 pqPVApplicationCore * PVGUI_Module::GetPVApplication()
312 return PVViewer_ViewManager::GetPVApplication();
316 \brief Initialize module. Creates menus, prepares context menu, etc.
317 \param app SALOME GUI application instance
319 void PVGUI_Module::initialize( CAM_Application* app )
321 SalomeApp_Module::initialize( app );
323 // Create ParaViS actions
325 // Create ParaViS menus
328 // Uncomment to debug ParaView initialization
329 // "aa" used instead of "i" as GDB doesn't like "i" variables :)
337 SalomeApp_Application* anApp = getApp();
338 SUIT_Desktop* aDesktop = anApp->desktop();
340 // Initialize ParaView client and associated behaviors
341 // and connect to externally launched pvserver
342 PVViewer_ViewManager::ParaviewInitApp(aDesktop);
343 myGuiElements = PVViewer_GUIElements::GetInstance(aDesktop);
345 // Remember current state of desktop toolbars
346 QList<QToolBar*> foreignToolbars = aDesktop->findChildren<QToolBar*>();
350 // Behaviors and connection must be instanciated *after* widgets are in place
351 // In PARAVIS module we do not wait for PVViewer_ViewWindow to be instanciated to have this:
352 PVViewer_ViewManager::ParaviewInitBehaviors(true, aDesktop);
353 PVViewer_ViewManager::ConnectToExternalPVServer(aDesktop);
359 QList<QDockWidget*> activeDocks = aDesktop->findChildren<QDockWidget*>();
360 QList<QMenu*> activeMenus = aDesktop->findChildren<QMenu*>();
362 // Setup quick-launch shortcuts.
363 QShortcut *ctrlSpace = new QShortcut(Qt::CTRL + Qt::Key_Space, aDesktop);
364 QObject::connect(ctrlSpace, SIGNAL(activated()),
365 pqApplicationCore::instance(), SLOT(quickLaunch()));
367 // Find Plugin Dock Widgets
368 QList<QDockWidget*> currentDocks = aDesktop->findChildren<QDockWidget*>();
369 QList<QDockWidget*>::iterator i;
370 for (i = currentDocks.begin(); i != currentDocks.end(); ++i) {
371 if(!activeDocks.contains(*i)) {
372 myDockWidgets[*i] = false; // hidden by default
378 // [ABN] TODO: fix this - triggers a SEGFAULT at deactivation() time.
379 // QList<QMenu*> currentMenus = aDesktop->findChildren<QMenu*>();
380 // QList<QMenu*>::iterator im;
381 // for (im = currentMenus.begin(); im != currentMenus.end(); ++im) {
382 // if(!activeMenus.contains(*im)) {
383 // QString s = (*im)->title();
384 // std::cout << " MENU "<< s.toStdString() << std::endl;
385 // myMenus.append(*im);
389 PVViewer_ViewManager::ParaviewLoadConfigurations();
392 // Find created toolbars
393 QCoreApplication::processEvents();
395 QList<QToolBar*> allToolbars = aDesktop->findChildren<QToolBar*>();
396 foreach(QToolBar* aBar, allToolbars) {
397 if (!foreignToolbars.contains(aBar)) {
398 myToolbars[aBar] = true;
399 myToolbarBreaks[aBar] = false;
400 aBar->setVisible(false);
401 aBar->toggleViewAction()->setVisible(false);
407 SUIT_ResourceMgr* aResourceMgr = SUIT_Session::session()->resourceMgr();
408 bool isStop = aResourceMgr->booleanValue( "PARAVIS", "stop_trace", false );
411 // Start a timer to schedule asap:
413 myInitTimer = new QTimer(aDesktop);
414 QObject::connect(myInitTimer, SIGNAL(timeout()), this, SLOT(onInitTimer()) );
415 myInitTimer->setSingleShot(true);
416 myInitTimer->start(0);
418 // Another timer to regularly push the trace onto the engine:
419 myPushTraceTimer = new QTimer(aDesktop);
420 QObject::connect(myPushTraceTimer, SIGNAL(timeout()), this, SLOT(onPushTraceTimer()) );
421 myPushTraceTimer->setSingleShot(false);
422 myPushTraceTimer->start(500);
425 this->VTKConnect = vtkEventQtSlotConnect::New();
427 vtkProcessModule* pm = vtkProcessModule::GetProcessModule();
429 vtkPVSession* pvs = dynamic_cast<vtkPVSession*>(pm->GetSession());
431 vtkPVProgressHandler* ph = pvs->GetProgressHandler();
433 this->VTKConnect->Connect(ph, vtkCommand::StartEvent,
434 this, SLOT(onStartProgress()));
435 this->VTKConnect->Connect(ph, vtkCommand::EndEvent,
436 this, SLOT(onEndProgress()));
442 void PVGUI_Module::onStartProgress()
444 QApplication::setOverrideCursor(Qt::WaitCursor);
447 void PVGUI_Module::onEndProgress()
449 QApplication::restoreOverrideCursor();
452 void PVGUI_Module::onDataRepresentationUpdated() {
453 SalomeApp_Study* activeStudy = dynamic_cast<SalomeApp_Study*>(application()->activeStudy());
454 if(!activeStudy) return;
456 activeStudy->Modified();
460 \brief Initialisation timer event - trace start up
462 void PVGUI_Module::onInitTimer()
468 \brief Get list of embedded macros files
470 QStringList PVGUI_Module::getEmbeddedMacrosList()
472 QString aRootDir = getenv("PARAVIS_ROOT_DIR");
474 QString aSourcePath = aRootDir + "/bin/salome/Macro";
479 QDir aSourceDir(aSourcePath);
480 QStringList aSourceFiles = aSourceDir.entryList(aFilter, QDir::Files);
481 QStringList aFullPathSourceFiles;
482 foreach (QString aMacrosName, aSourceFiles) {
483 aFullPathSourceFiles << aSourceDir.absoluteFilePath(aMacrosName);
485 return aFullPathSourceFiles;
488 void PVGUI_Module::updateMacros()
490 pqPythonManager* aPythonManager = pqPVApplicationCore::instance()->pythonManager();
491 if(!aPythonManager) {
495 foreach (QString aStr, getEmbeddedMacrosList()) {
496 aPythonManager->addMacro(aStr);
502 \brief Get list of compliant dockable GUI elements
503 \param m map to be filled in ("type":"default_position")
505 void PVGUI_Module::windows( QMap<int, int>& m ) const
507 m.insert( LightApp_Application::WT_ObjectBrowser, Qt::LeftDockWidgetArea );
508 m.insert( LightApp_Application::WT_PyConsole, Qt::BottomDockWidgetArea );
509 // ParaView diagnostic output redirected here
510 m.insert( LightApp_Application::WT_LogWindow, Qt::BottomDockWidgetArea );
514 \brief Shows (toShow = true) or hides ParaView view window
516 void PVGUI_Module::showView( bool toShow )
518 SalomeApp_Application* anApp = getApp();
519 PVViewer_ViewManager* viewMgr =
520 dynamic_cast<PVViewer_ViewManager*>( anApp->getViewManager( PVViewer_Viewer::Type(), false ) );
522 viewMgr = new PVViewer_ViewManager( anApp->activeStudy(), anApp->desktop() );
523 anApp->addViewManager( viewMgr );
524 connect( viewMgr, SIGNAL( lastViewClosed( SUIT_ViewManager* ) ),
525 anApp, SLOT( onCloseView( SUIT_ViewManager* ) ) );
528 PVViewer_ViewWindow* pvWnd = dynamic_cast<PVViewer_ViewWindow*>( viewMgr->getActiveView() );
530 pvWnd = dynamic_cast<PVViewer_ViewWindow*>( viewMgr->createViewWindow() );
531 // this also connects to the pvserver and instantiates relevant PV behaviors
534 pvWnd->setShown( toShow );
535 if ( toShow ) pvWnd->setFocus();
539 \brief Slot to show help for proxy.
541 void PVGUI_Module::showHelpForProxy( const QString& groupname, const QString& proxyname )
543 pqHelpReaction::showProxyHelp(groupname, proxyname);
548 \brief Slot to show the waiting state.
550 void PVGUI_Module::onPreAccept()
552 getApp()->desktop()->statusBar()->showMessage(tr("STB_PREACCEPT"));
553 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
557 \brief Slot to show the ready state.
559 void PVGUI_Module::onPostAccept()
561 getApp()->desktop()->statusBar()->showMessage(tr("STB_POSTACCEPT"), 2000);
562 QTimer::singleShot(0, this, SLOT(endWaitCursor()));
566 \brief Slot to switch off wait cursor.
568 void PVGUI_Module::endWaitCursor()
570 QApplication::restoreOverrideCursor();
573 static void ParavisMessageOutput(QtMsgType type, const char *msg)
578 vtkOutputWindow::GetInstance()->DisplayText(msg);
581 vtkOutputWindow::GetInstance()->DisplayErrorText(msg);
584 vtkOutputWindow::GetInstance()->DisplayErrorText(msg);
587 vtkOutputWindow::GetInstance()->DisplayErrorText(msg);
593 \brief Activate module.
594 \param study current study
595 \return \c true if activaion is done successfully or 0 to prevent
598 bool PVGUI_Module::activateModule( SUIT_Study* study )
600 myOldMsgHandler = qInstallMsgHandler(ParavisMessageOutput);
602 SUIT_ExceptionHandler::addCleanUpRoutine( paravisCleanUp );
604 storeCommonWindowsState();
606 bool isDone = SalomeApp_Module::activateModule( study );
607 if ( !isDone ) return false;
610 if ( mySourcesMenuId != -1 ) menuMgr()->show(mySourcesMenuId);
611 if ( myFiltersMenuId != -1 ) menuMgr()->show(myFiltersMenuId);
612 if ( myMacrosMenuId != -1 ) menuMgr()->show(myMacrosMenuId);
613 if ( myToolbarsMenuId != -1 ) menuMgr()->show(myToolbarsMenuId);
615 // Update the various menus with the content pre-loaded in myGuiElements
616 QMenu* srcMenu = menuMgr()->findMenu( mySourcesMenuId );
617 myGuiElements->updateSourcesMenu(srcMenu);
618 QMenu* filtMenu = menuMgr()->findMenu( myFiltersMenuId );
619 myGuiElements->updateFiltersMenu(filtMenu);
620 QMenu* macMenu = menuMgr()->findMenu( myMacrosMenuId );
621 myGuiElements->updateMacrosMenu(macMenu);
623 setMenuShown( true );
624 setToolShown( true );
626 restoreDockWidgetsState();
628 QMenu* aMenu = menuMgr()->findMenu( myRecentMenuId );
630 QList<QAction*> anActns = aMenu->actions();
631 for (int i = 0; i < anActns.size(); ++i) {
632 QAction* a = anActns.at(i);
638 QList<QMenu*>::iterator it;
639 for (it = myMenus.begin(); it != myMenus.end(); ++it) {
640 QAction* a = (*it)->menuAction();
645 if ( myRecentMenuId != -1 ) menuMgr()->show(myRecentMenuId);
647 ClientFindOrCreateParavisComponent(PARAVIS::GetCStudy(this));
654 \brief Deactivate module.
655 \param study current study
656 \return \c true if deactivaion is done successfully or 0 to prevent
657 deactivation on error
659 bool PVGUI_Module::deactivateModule( SUIT_Study* study )
661 MESSAGE("PARAVIS deactivation ...")
663 QMenu* aMenu = menuMgr()->findMenu( myRecentMenuId );
665 QList<QAction*> anActns = aMenu->actions();
666 for (int i = 0; i < anActns.size(); ++i) {
667 QAction* a = anActns.at(i);
669 a->setVisible(false);
673 QList<QMenu*>::iterator it;
674 for (it = myMenus.begin(); it != myMenus.end(); ++it) {
675 QAction* a = (*it)->menuAction();
677 a->setVisible(false);
680 QList<QDockWidget*> aStreamingViews = application()->desktop()->findChildren<QDockWidget*>("pqStreamingControls");
681 foreach(QDockWidget* aView, aStreamingViews) {
682 if (!myDockWidgets.contains(aView))
683 myDockWidgets[aView] = aView->isVisible();
686 /*if (pqImplementation::helpWindow) {
687 pqImplementation::helpWindow->hide();
691 menuMgr()->hide(myRecentMenuId);
692 menuMgr()->hide(mySourcesMenuId);
693 menuMgr()->hide(myFiltersMenuId);
694 menuMgr()->hide(myMacrosMenuId);
695 menuMgr()->hide(myToolbarsMenuId);
696 setMenuShown( false );
697 setToolShown( false );
699 saveDockWidgetsState();
701 SUIT_ExceptionHandler::removeCleanUpRoutine( paravisCleanUp );
704 qInstallMsgHandler(myOldMsgHandler);
706 restoreCommonWindowsState();
708 return SalomeApp_Module::deactivateModule( study );
713 \brief Called when application is closed.
715 Process finalize application functionality from ParaView in order to save server settings
716 and nullify application pointer if the application is being closed.
718 \param theApp application
720 void PVGUI_Module::onApplicationClosed( SUIT_Application* theApp )
722 PVViewer_ViewManager::ParaviewCleanup();
724 int aAppsNb = SUIT_Session::session()->applications().size();
726 deleteTemporaryFiles();
728 CAM_Module::onApplicationClosed(theApp);
733 \brief Deletes temporary files created during import operation from VISU
735 void PVGUI_Module::deleteTemporaryFiles()
737 foreach(QString aFile, myTemporaryFiles) {
738 if (QFile::exists(aFile)) {
739 QFile::remove(aFile);
746 \brief Called when study is closed.
748 Removes data model from the \a study.
750 \param study study being closed
752 void PVGUI_Module::studyClosed(SUIT_Study* study)
754 clearParaviewState();
756 SalomeApp_Module::studyClosed(study);
760 \brief Called when study is opened.
762 void PVGUI_Module::onModelOpened()
764 _PTR(Study) studyDS = PARAVIS::GetCStudy(this);
769 _PTR(SComponent) paravisComp =
770 studyDS->FindComponent(GetEngine()->ComponentDataType());
775 _PTR(ChildIterator) anIter(studyDS->NewChildIterator(paravisComp));
776 for (; anIter->More(); anIter->Next()) {
777 _PTR(SObject) aSObj = anIter->Value();
778 _PTR(GenericAttribute) anAttr;
779 if (!aSObj->FindAttribute(anAttr, "AttributeLocalID")) {
782 _PTR(AttributeLocalID) anID(anAttr);
783 if (anID->Value() == PVSTATEID) {
790 \brief Returns IOR of current engine
792 QString PVGUI_Module::engineIOR() const
794 CORBA::String_var anIOR = GetEngine()->GetIOR();
795 return QString(anIOR.in());
799 \brief Open file of format supported by ParaView
801 void PVGUI_Module::openFile(const char* theName)
805 pqLoadDataReaction::loadData(aFiles);
809 * Start trace invoking the newly introduced C++ API (PV 4.2)
810 * (inspired from pqTraceReaction::start())
812 void PVGUI_Module::startTrace()
814 vtkSMSessionProxyManager* pxm = pqActiveObjects::instance().activeServer()->proxyManager();
816 vtkSmartPointer<vtkSMProxy> proxy;
817 proxy.TakeReference(pxm->NewProxy("pythontracing", "PythonTraceOptions"));
820 vtkNew<vtkSMParaViewPipelineController> controller;
821 controller->InitializeProxy(proxy);
823 vtkSMTrace* trace = vtkSMTrace::StartTrace();
826 // Set manually the properties entered via the dialog box poping-up when requiring
827 // a trace start in PV4.2 (trace options)
828 trace->SetPropertiesToTraceOnCreate(vtkSMTrace::RECORD_USER_MODIFIED_PROPERTIES);
829 trace->SetFullyTraceSupplementalProxies(false);
833 void PVGUI_Module::stopTrace()
835 vtkSMTrace::StopTrace();
838 void PVGUI_Module::executeScript(const char *script)
841 pqPythonManager* manager = qobject_cast<pqPythonManager*>(
842 pqApplicationCore::instance()->manager("PYTHON_MANAGER"));
844 pqPythonDialog* pyDiag = manager->pythonShellDialog();
846 pyDiag->runString(script);
853 // * Debug function printing out the given interpreter's execution context
855 //void printInterpContext(PyInterp_Interp * interp )
857 // // Extract __smtraceString from interpreter's context
858 // const PyObject* ctxt = interp->getExecutionContext();
860 // PyObject* lst = PyDict_Keys((PyObject *)ctxt);
861 // Py_ssize_t siz = PyList_GET_SIZE(lst);
862 // for (Py_ssize_t i = 0; i < siz; i++)
864 // PyObject * elem = PyList_GetItem(lst, i);
865 // if (PyString_Check(elem))
867 // std::cout << "At pos:" << i << ", " << PyString_AsString(elem) << std::endl;
870 // std::cout << "At pos:" << i << ", not a string!" << std::endl;
876 \brief Returns trace string
878 static const QString MYReplaceStr("paraview.simple");
879 QString PVGUI_Module::getTraceString()
881 vtkSMTrace *tracer = vtkSMTrace::GetActiveTracer();
882 if (!tracer) // trace is not started
885 QString traceString(tracer->GetCurrentTrace());
886 std::stringstream nl; nl << std::endl; // surely there is some Qt trick to do that in a portable way??
887 traceString = "import pvsimple" + QString(nl.str().c_str()) + traceString;
889 // Replace import "paraview.simple" by "pvsimple"
890 if ((!traceString.isNull()) && traceString.length() != 0) {
891 int aPos = traceString.indexOf(MYReplaceStr);
893 traceString = traceString.replace(aPos, MYReplaceStr.length(), "pvsimple");
894 aPos = traceString.indexOf(MYReplaceStr, aPos);
902 \brief Saves trace string to disk file
904 void PVGUI_Module::saveTrace(const char* theName)
907 if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
908 MESSAGE( "Could not open file:" << theName );
911 QTextStream out(&file);
912 out << getTraceString();
917 \brief Saves ParaView state to a disk file
919 void PVGUI_Module::saveParaviewState(const char* theFileName)
921 pqApplicationCore::instance()->saveState(theFileName);
925 \brief Delete all objects for Paraview Pipeline Browser
927 void PVGUI_Module::clearParaviewState()
929 QAction* deleteAllAction = action(DeleteAllId);
930 if (deleteAllAction) {
931 deleteAllAction->activate(QAction::Trigger);
936 \brief Restores ParaView state from a disk file
938 If toClear == true, the current ojects will be deleted
940 void PVGUI_Module::loadParaviewState(const char* theFileName)
942 pqApplicationCore::instance()->loadState(theFileName, getActiveServer());
946 \brief Returns current active ParaView server
948 pqServer* PVGUI_Module::getActiveServer()
950 return pqApplicationCore::instance()->getActiveServer();
955 \brief Creates PARAVIS preference pane
957 void PVGUI_Module::createPreferences()
959 // Paraview settings tab
960 int aParaViewSettingsTab = addPreference( tr( "TIT_PVIEWSETTINGS" ) );
961 int aPanel = addPreference(QString(), aParaViewSettingsTab, LightApp_Preferences::UserDefined, "PARAVIS", "");
962 setPreferenceProperty(aPanel, "content", (qint64)(new PVGUI_ParaViewSettingsPane()));
964 // Paravis settings tab
965 int aParaVisSettingsTab = addPreference( tr( "TIT_PVISSETTINGS" ) );
966 addPreference( tr( "PREF_STOP_TRACE" ), aParaVisSettingsTab, LightApp_Preferences::Bool, "PARAVIS", "stop_trace");
968 addPreference( tr( "PREF_NO_EXT_PVSERVER" ), aParaVisSettingsTab, LightApp_Preferences::Bool, "PARAVIS", "no_ext_pv_server");
970 int aSaveType = addPreference(tr( "PREF_SAVE_TYPE_LBL" ), aParaVisSettingsTab,
971 LightApp_Preferences::Selector,
972 "PARAVIS", "savestate_type");
973 QList<QVariant> aIndices;
974 QStringList aStrings;
976 aStrings<<tr("PREF_SAVE_TYPE_0");
977 aStrings<<tr("PREF_SAVE_TYPE_1");
978 aStrings<<tr("PREF_SAVE_TYPE_2");
979 setPreferenceProperty(aSaveType, "strings", aStrings);
980 setPreferenceProperty(aSaveType, "indexes", aIndices);
984 \brief Creates ParaViS context menu popup
986 void PVGUI_Module::contextMenuPopup(const QString& theClient, QMenu* theMenu, QString& theTitle)
988 SalomeApp_Module::contextMenuPopup(theClient, theMenu, theTitle);
990 // Check if we are in Object Browser
991 SUIT_DataBrowser* ob = getApp()->objectBrowser();
992 bool isOBClient = (ob && theClient == ob->popupClientType());
997 // Get list of selected objects
998 LightApp_SelectionMgr* aSelectionMgr = getApp()->selectionMgr();
999 SALOME_ListIO aListIO;
1000 aSelectionMgr->selectedObjects(aListIO);
1001 if (aListIO.Extent() == 1 && aListIO.First()->hasEntry()) {
1002 QString entry = QString(aListIO.First()->getEntry());
1005 SalomeApp_Study* activeStudy =
1006 dynamic_cast<SalomeApp_Study*>(getApp()->activeStudy());
1011 // Get SALOMEDS client study
1012 _PTR(Study) studyDS = activeStudy->studyDS();
1017 QString paravisDataType(GetEngine()->ComponentDataType());
1018 if(activeStudy && activeStudy->isComponent(entry) &&
1019 activeStudy->componentDataType(entry) == paravisDataType) {
1020 // ParaViS module object
1021 theMenu->addSeparator();
1022 theMenu->addAction(action(SaveStatePopupId));
1025 // Try to get state object
1026 _PTR(SObject) stateSObj =
1027 studyDS->FindObjectID(entry.toLatin1().constData());
1033 _PTR(GenericAttribute) anAttr;
1034 if (!stateSObj->FindAttribute(anAttr, "AttributeLocalID")) {
1038 _PTR(AttributeLocalID) anID(anAttr);
1040 if (anID->Value() == PVSTATEID) {
1041 // Paraview state object
1042 theMenu->addSeparator();
1043 theMenu->addAction(action(AddStatePopupId));
1044 theMenu->addAction(action(CleanAndAddStatePopupId));
1045 theMenu->addSeparator();
1046 theMenu->addAction(action(ParaVisRenameId));
1047 theMenu->addAction(action(ParaVisDeleteId));
1054 \brief. Show ParaView python trace.
1056 void PVGUI_Module::onShowTrace()
1058 if (!myTraceWindow) {
1059 myTraceWindow = new pqPythonScriptEditor(getApp()->desktop());
1061 myTraceWindow->setText(getTraceString());
1062 myTraceWindow->show();
1063 myTraceWindow->raise();
1064 myTraceWindow->activateWindow();
1069 \brief. Re-initialize ParaView python trace.
1071 void PVGUI_Module::onRestartTrace()
1078 \brief Show ParaView view.
1080 void PVGUI_Module::onNewParaViewWindow()
1086 \brief Save state under the module root object.
1088 void PVGUI_Module::onSaveMultiState()
1090 // Create state study object
1092 // Get SALOMEDS client study
1093 _PTR(Study) studyDS = PARAVIS::GetCStudy(this);
1098 _PTR(SComponent) paravisComp =
1099 studyDS->FindComponent(GetEngine()->ComponentDataType());
1104 // Unlock the study if it is locked
1105 bool isLocked = studyDS->GetProperties()->IsLocked();
1107 studyDS->GetProperties()->SetLocked(false);
1110 QString stateName = tr("SAVED_PARAVIEW_STATE_NAME") +
1111 QString::number(myStateCounter + 1);
1113 _PTR(StudyBuilder) studyBuilder = studyDS->NewBuilder();
1114 _PTR(SObject) newSObj = studyBuilder->NewObject(paravisComp);
1117 _PTR(GenericAttribute) anAttr;
1118 anAttr = studyBuilder->FindOrCreateAttribute(newSObj, "AttributeName");
1119 _PTR(AttributeName) nameAttr(anAttr);
1121 nameAttr->SetValue(stateName.toLatin1().constData());
1124 anAttr = studyBuilder->FindOrCreateAttribute(newSObj, "AttributeLocalID");
1125 _PTR(AttributeLocalID) localIdAttr(anAttr);
1127 localIdAttr->SetValue(PVSTATEID);
1130 QString stateEntry = QString::fromStdString(newSObj->GetID());
1132 // File name for state saving
1133 QString tmpDir = QString::fromStdString(SALOMEDS_Tool::GetTmpDir());
1134 QString fileName = QString("%1_paravisstate:%2").arg(tmpDir, stateEntry);
1136 anAttr = studyBuilder->FindOrCreateAttribute(newSObj, "AttributeString");
1137 _PTR(AttributeString) stringAttr(anAttr);
1139 stringAttr->SetValue(fileName.toLatin1().constData());
1141 // Lock the study back if necessary
1143 studyDS->GetProperties()->SetLocked(true);
1147 saveParaviewState(fileName.toLatin1().constData());
1148 myTemporaryFiles.append(fileName);
1150 // Increment the counter
1157 \brief Restore the selected state by merging with the current one.
1159 void PVGUI_Module::onAddState()
1161 loadSelectedState(false);
1165 \brief Clean the current state and restore the selected one.
1167 void PVGUI_Module::onCleanAddState()
1169 loadSelectedState(true);
1173 \brief Rename the selected object.
1175 void PVGUI_Module::onRename()
1177 LightApp_SelectionMgr* aSelectionMgr = getApp()->selectionMgr();
1178 SALOME_ListIO aListIO;
1179 aSelectionMgr->selectedObjects(aListIO);
1181 if (aListIO.Extent() == 1 && aListIO.First()->hasEntry()) {
1182 std::string entry = aListIO.First()->getEntry();
1184 // Get SALOMEDS client study
1185 _PTR(Study) studyDS = PARAVIS::GetCStudy(this);
1190 // Unlock the study if it is locked
1191 bool isLocked = studyDS->GetProperties()->IsLocked();
1193 studyDS->GetProperties()->SetLocked(false);
1196 // Rename the selected state object
1197 _PTR(SObject) stateSObj = studyDS->FindObjectID(entry);
1202 _PTR(GenericAttribute) anAttr;
1203 if (stateSObj->FindAttribute(anAttr, "AttributeName")) {
1204 _PTR(AttributeName) nameAttr (anAttr);
1206 LightApp_NameDlg::getName(getApp()->desktop(), nameAttr->Value().c_str());
1207 if (!newName.isEmpty()) {
1208 nameAttr->SetValue(newName.toLatin1().constData());
1209 aListIO.First()->setName(newName.toLatin1().constData());
1213 // Lock the study back if necessary
1215 studyDS->GetProperties()->SetLocked(true);
1218 // Update object browser
1225 \brief Delete the selected objects.
1227 void PVGUI_Module::onDelete()
1229 LightApp_SelectionMgr* aSelectionMgr = getApp()->selectionMgr();
1230 SALOME_ListIO aListIO;
1231 aSelectionMgr->selectedObjects(aListIO);
1233 if (aListIO.Extent() == 1 && aListIO.First()->hasEntry()) {
1234 std::string entry = aListIO.First()->getEntry();
1236 // Get SALOMEDS client study
1237 _PTR(Study) studyDS = PARAVIS::GetCStudy(this);
1242 // Unlock the study if it is locked
1243 bool isLocked = studyDS->GetProperties()->IsLocked();
1245 studyDS->GetProperties()->SetLocked(false);
1248 // Remove the selected state from the study
1249 _PTR(StudyBuilder) studyBuilder = studyDS->NewBuilder();
1250 _PTR(SObject) stateSObj = studyDS->FindObjectID(entry);
1251 studyBuilder->RemoveObject(stateSObj);
1253 // Lock the study back if necessary
1255 studyDS->GetProperties()->SetLocked(true);
1258 // Update object browser
1263 void PVGUI_Module::onPushTraceTimer()
1265 // MESSAGE("onPushTraceTimer(): Pushing trace to engine...");
1266 GetEngine()->PutPythonTraceStringToEngine(getTraceString().toStdString().c_str());
1270 \brief Discover help project files from the resources.
1271 \return name of the help file.
1273 QString PVGUI_Module::getHelpFileName() {
1274 QString aPVHome(getenv("PVHOME"));
1275 if (aPVHome.isNull()) {
1276 qWarning("Wariable PVHOME is not defined");
1279 QChar aSep = QDir::separator();
1280 //PARAVIEW_VERSION from the vtkPVConfig.h file
1281 QString aFileName = aPVHome + aSep + "share" + aSep + "doc" + aSep + "paraview-"+ PARAVIEW_VERSION + aSep + "paraview.qch";
1287 \brief Load selected paraview state
1289 If toClear == true, the current state will be cleared
1291 void PVGUI_Module::loadSelectedState(bool toClear)
1295 LightApp_SelectionMgr* aSelectionMgr = getApp()->selectionMgr();
1296 SALOME_ListIO aListIO;
1297 aSelectionMgr->selectedObjects(aListIO);
1299 if (aListIO.Extent() == 1 && aListIO.First()->hasEntry()) {
1300 std::string entry = aListIO.First()->getEntry();
1302 // Get SALOMEDS client study
1303 _PTR(Study) studyDS = PARAVIS::GetCStudy(this);
1309 _PTR(SObject) stateSObj = studyDS->FindObjectID(entry);
1310 _PTR(GenericAttribute) anAttr;
1311 if (!stateSObj->FindAttribute(anAttr, "AttributeLocalID")) {
1314 _PTR(AttributeLocalID) anID(anAttr);
1315 if (!anID->Value() == PVSTATEID) {
1319 // Get state file name
1320 if (stateSObj->FindAttribute(anAttr, "AttributeString")) {
1321 _PTR(AttributeString) aStringAttr(anAttr);
1322 QString stringValue(aStringAttr->Value().c_str());
1324 if (QFile::exists(stringValue)) {
1325 fileName = stringValue;
1330 if (!fileName.isEmpty()) {
1332 clearParaviewState();
1335 loadParaviewState(fileName.toLatin1().constData());
1338 SUIT_MessageBox::critical(getApp()->desktop(),
1340 tr("ERR_STATE_CANNOT_BE_RESTORED"));
1345 \fn CAM_Module* createModule();
1346 \brief Export module instance (factory function).
1347 \return new created instance of the module
1351 #define PVGUI_EXPORT __declspec(dllexport)
1353 #define PVGUI_EXPORT
1359 PVGUI_EXPORT CAM_Module* createModule() {
1360 return new PVGUI_Module();
1363 PVGUI_EXPORT char* getModuleVersion() {
1364 return (char*)PARAVIS_VERSION_STR;