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
22 // Author : Julia DOROVSKIKH
24 #include <Standard_math.hxx> // E.A. must be included before Python.h to fix compilation on windows
26 #undef HAVE_FINITE // VSR: avoid compilation warning on Linux : "HAVE_FINITE" redefined
28 #include <vtkPython.h> // Python first
29 #include "PVGUI_Module.h"
31 #ifdef PARAVIS_WITH_FULL_CORBA
32 # include "PARAVIS_Gen_i.hh"
35 //#include "PV_Tools.h"
37 #include "PVGUI_ViewModel.h"
38 #include "PVGUI_ViewManager.h"
39 #include "PVGUI_ViewWindow.h"
40 #include "PVGUI_Tools.h"
41 #include "PVGUI_ParaViewSettingsPane.h"
42 #include "PVGUI_OutputWindowAdapter.h"
43 #include "PVGUI_Behaviors.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>
54 #include "SALOME_LifeCycleCORBA.hxx"
55 #include "SALOMEDS_SObject.hxx"
57 #include "LightApp_SelectionMgr.h"
58 #include "LightApp_NameDlg.h"
60 #include <SalomeApp_Application.h>
61 #include <SalomeApp_Study.h>
62 #include <SALOME_ListIO.hxx>
63 #include <SALOMEDS_Tool.hxx>
64 #include <PyInterp_Interp.h>
65 #include <PyInterp_Dispatcher.h>
66 #include <PyConsole_Console.h>
67 #include <PyConsole_Interp.h>
71 #include <QtxActionMenuMgr.h>
72 #include <QtxActionToolMgr.h>
75 #include <QApplication>
81 #include <QInputDialog>
85 #include <QStringList>
88 #include <QTextStream>
90 #include <QDockWidget>
91 #include <QHelpEngine>
93 #include <pqApplicationCore.h>
94 //#include <pqPVApplicationCore.h>
95 #include <pqActiveView.h>
96 #include <pqObjectBuilder.h>
97 #include <pqOptions.h>
98 #include <pqRenderView.h>
100 #include <pqUndoStack.h>
101 #include <pqVCRController.h>
102 #include <pqTabbedMultiViewWidget.h>
103 #include <pqPipelineSource.h>
104 #include <pqActiveObjects.h>
105 #include <vtkProcessModule.h>
106 #include <vtkSMSession.h>
107 #include <vtkPVSession.h>
108 #include <vtkPVProgressHandler.h>
109 #include <pqParaViewBehaviors.h>
110 #include <pqHelpReaction.h>
111 #include <vtkOutputWindow.h>
112 #include <pqPluginManager.h>
113 #include <pqSettings.h>
114 #include <pqPythonDialog.h>
115 #include <pqPythonManager.h>
116 #include <pqPythonShell.h>
117 #include <pqLoadDataReaction.h>
118 #include <vtkEventQtSlotConnect.h>
119 #include <pqPythonScriptEditor.h>
120 #include <pqDataRepresentation.h>
121 #include <pqPipelineRepresentation.h>
122 #include <pqLookupTableManager.h>
123 #include <pqDisplayColorWidget.h>
124 #include <pqColorToolbar.h>
125 #include <pqScalarBarVisibilityReaction.h>
127 #include <pqServerResource.h>
128 #include <pqServerConnectReaction.h>
129 #include <pqServerDisconnectReaction.h>
131 #include <pqServerManagerObserver.h>
132 #include <vtkClientServerInterpreterInitializer.h>
133 #include <vtkPVConfig.h>
135 #include <PARAVIS_version.h>
137 #include CORBA_SERVER_HEADER(SALOME_ModuleCatalog)
139 //----------------------------------------------------------------------------
140 PVGUI_Module* ParavisModule = 0;
145 <h2>Building and installing PARAVIS</h2>
146 As any other SALOME module, PARAVIS requires PARAVIS_ROOT_DIR environment variable to be set to PARAVIS
147 installation directory.
148 Other variables needed for correct detection of ParaView location:
149 \li PVHOME - points at the ParaView installation directory tree
150 \li PVVERSION - number of ParaView version
152 It also requires common SALOME environment including GUI_ROOT_DIR and other prerequsites.
155 PARAVIS module can be launched using the following commands:
156 \li Full SALOME configuration
158 runSalome --modules="PARAVIS"
161 <h2>ParaView GUI integration</h2>
162 <h3>ParaView GUI integration overview</h3>
164 The main idea is to reuse ParaView GUI internal logic as much as possible, providing a layer
165 between it and SALOME GUI that hides the following SALOME GUI implementation details from ParaView:
167 \li SALOME GUI executable and Qt event loop
168 \li SALOME GUI desktop
169 \li Dock windows areas
170 \li SALOME menu and toolbar managers
172 Major part of the integration is implemented in PVGUI_Module class.
174 <h3>ParaView client initalization</h3>
176 ParaView client initalization is performed when an instance of PVGUI_Module class has been created
177 and \link PVGUI_Module::initialize() PVGUI_Module::initialize()\endlink method is called by SALOME GUI.
178 The actual client start-up is done in \link PVGUI_Module::pvInit() PVGUI_Module::pvInit()\endlink method.
181 <h3>Multi-view manager</h3>
183 SALOME GUI requires that each kind of view be implemnted with help of (at least) three classes. For ParaView multi-view manager
186 \li PVGUI_ViewManager - view manager class
187 \li PVGUI_Viewer - view model class
188 \li PVGUI_ViewWindow - view window class that acts as a parent for %pqViewManager
190 Single instances of PVGUI_ViewManager and PVGUI_ViewWindow classes are created by \link PVGUI_Module::showView()
191 PVGUI_Module::showView()\endlink method upon the first PARAVIS module activation. The same method hides the multi-view manager
192 when the module is deactivated (the user switches to another module or a study is closed).
193 A special trick is used to make PVGUI_ViewWindow the parent of %pqViewManager widget. It is created initally by %pqMainWindowCore
194 with the desktop as a parent, so when it is shown PVGUI_ViewWindow instance is passed to its setParent() method. In
195 \link PVGUI_ViewWindow::~PVGUI_ViewWindow() PVGUI_ViewWindow::~PVGUI_ViewWindow()\endlink the parent is nullified to avoid deletion
196 of %pqViewManager widget that would break %pqMainWindowCore class.
198 <h3>ParaView plugins</h3>
199 ParaView server and client plugins are managed by %pqMainWindowCore slots that has full access to PARAVIS menus and toolbars.
200 As a result they appears automatically in PARAVIS menus and toolbars if loaded successfully.
205 \brief Implementation
206 SALOME module wrapping ParaView GUI.
211 Fix for the issue 21730: [CEA 596] Slice of polyhedron in PARAVIS returns no cell.
212 Wrap vtkEDFCutter filter.
215 extern "C" void vtkEDFCutterCS_Initialize(vtkClientServerInterpreter*);
216 static void vtkEDFHelperInit();
218 void vtkEDFHelperInit(vtkClientServerInterpreter* interp){
219 vtkEDFCutterCS_Initialize(interp);
222 void vtkEDFHelperInit() {
223 vtkClientServerInterpreterInitializer::GetInitializer()->
224 RegisterCallback(&vtkEDFHelperInit);
229 ClientFindOrCreateParavisComponent(_PTR(Study) theStudyDocument)
231 _PTR(SComponent) aSComponent = theStudyDocument->FindComponent("PARAVIS");
233 _PTR(StudyBuilder) aStudyBuilder = theStudyDocument->NewBuilder();
234 aStudyBuilder->NewCommand();
235 int aLocked = theStudyDocument->GetProperties()->IsLocked();
236 if (aLocked) theStudyDocument->GetProperties()->SetLocked(false);
237 aSComponent = aStudyBuilder->NewComponent("PARAVIS");
238 _PTR(GenericAttribute) anAttr =
239 aStudyBuilder->FindOrCreateAttribute(aSComponent, "AttributeName");
240 _PTR(AttributeName) aName (anAttr);
242 //CORBA::ORB_var anORB = PARAVIS::PARAVIS_Gen_i::GetORB();
244 CORBA::ORB_var anORB = CORBA::ORB_init(dnu, 0); // suppose ORB was already initialized
245 SALOME_NamingService *NamingService = new SALOME_NamingService( anORB );
246 CORBA::Object_var objVarN = NamingService->Resolve("/Kernel/ModulCatalog");
247 SALOME_ModuleCatalog::ModuleCatalog_var Catalogue =
248 SALOME_ModuleCatalog::ModuleCatalog::_narrow(objVarN);
249 SALOME_ModuleCatalog::Acomponent_var Comp = Catalogue->GetComponent( "PARAVIS" );
250 if (!Comp->_is_nil()) {
251 aName->SetValue(Comp->componentusername());
254 anAttr = aStudyBuilder->FindOrCreateAttribute(aSComponent, "AttributePixMap");
255 _PTR(AttributePixMap) aPixmap (anAttr);
256 aPixmap->SetPixMap( "pqAppIcon16.png" );
258 // Create Attribute parameters for future using
259 anAttr = aStudyBuilder->FindOrCreateAttribute(aSComponent, "AttributeParameter");
261 aStudyBuilder->DefineComponentInstance(aSComponent, PVGUI_Module::GetEngine()->GetIOR());
262 if (aLocked) theStudyDocument->GetProperties()->SetLocked(true);
263 aStudyBuilder->CommitCommand();
269 Clean up function; used to stop ParaView progress events when
270 exception is caught by global exception handler.
272 void paravisCleanUp()
274 if ( pqApplicationCore::instance() ) {
275 pqServer* s = pqApplicationCore::instance()->getActiveServer();
276 if ( s ) s->session()->GetProgressHandler()->CleanupPendingProgress();
281 \brief Constructor. Sets the default name for the module.
283 PVGUI_Module::PVGUI_Module()
284 : SalomeApp_Module( "PARAVIS" ),
285 mySelectionControlsTb( -1 ),
286 mySourcesMenuId( -1 ),
287 myFiltersMenuId( -1 ),
289 myToolbarsMenuId(-1),
298 Q_INIT_RESOURCE( PVGUI );
300 ParavisModule = this;
302 // Clear old copies of embedded macros files
303 QString aDestPath = QString( "%1/.config/%2/Macros" ).arg( QDir::homePath() ).arg( QApplication::applicationName() );
307 QDir aDestDir(aDestPath);
308 QStringList aDestFiles = aDestDir.entryList(aFilter, QDir::Files);
309 foreach (QString aMacrosPath, getEmbeddedMacrosList()) {
310 QString aMacrosName = QFileInfo(aMacrosPath).fileName();
311 if (aDestFiles.contains(aMacrosName)) {
312 aDestDir.remove(aMacrosName);
320 PVGUI_Module::~PVGUI_Module()
322 if (myPushTraceTimer)
323 delete myPushTraceTimer;
326 // Disconnect from server
327 pqServer* server = pqActiveObjects::instance().activeServer();
328 if (server && server->isRemote())
330 MESSAGE("~PVGUI_Module(): Disconnecting from remote server ...");
331 pqServerDisconnectReaction::disconnectFromServer();
335 PARAVIS_ORB::PARAVIS_Gen_var PVGUI_Module::GetEngine()
337 return PVGUI_ViewerModel::GetEngine();
341 \brief Initialize module. Creates menus, prepares context menu, etc.
342 \param app SALOME GUI application instance
344 void PVGUI_Module::initialize( CAM_Application* app )
346 SalomeApp_Module::initialize( app );
348 // Create ParaViS actions
350 // Create ParaViS menus
353 // Uncomment to debug ParaView initialization
354 // "aa" used instead of "i" as GDB doesn't like "i" variables :)
362 // Initialize ParaView client
365 // Create GUI elements (menus, toolbars, dock widgets)
366 SalomeApp_Application* anApp = getApp();
367 SUIT_Desktop* aDesktop = anApp->desktop();
369 // Remember current state of desktop toolbars
370 QList<QToolBar*> foreignToolbars = aDesktop->findChildren<QToolBar*>();
378 QList<QDockWidget*> activeDocks = aDesktop->findChildren<QDockWidget*>();
379 QList<QMenu*> activeMenus = aDesktop->findChildren<QMenu*>();
381 PVGUI_Behaviors * behav = new PVGUI_Behaviors(this);
382 behav->instanciateAllBehaviors(aDesktop);
384 // Setup quick-launch shortcuts.
385 QShortcut *ctrlSpace = new QShortcut(Qt::CTRL + Qt::Key_Space, aDesktop);
386 QObject::connect(ctrlSpace, SIGNAL(activated()),
387 pqApplicationCore::instance(), SLOT(quickLaunch()));
389 // Find Plugin Dock Widgets
390 QList<QDockWidget*> currentDocks = aDesktop->findChildren<QDockWidget*>();
391 QList<QDockWidget*>::iterator i;
392 for (i = currentDocks.begin(); i != currentDocks.end(); ++i) {
393 if(!activeDocks.contains(*i)) {
394 myDockWidgets[*i] = false; // hidden by default
400 QList<QMenu*> currentMenus = aDesktop->findChildren<QMenu*>();
401 QList<QMenu*>::iterator im;
402 for (im = currentMenus.begin(); im != currentMenus.end(); ++im) {
403 if(!activeMenus.contains(*im)) {
408 SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr();
409 QString aPath = resMgr->stringValue("resources", "PARAVIS", QString());
410 if (!aPath.isNull()) {
411 MyCoreApp->loadConfiguration(aPath + QDir::separator() + "ParaViewFilters.xml");
412 MyCoreApp->loadConfiguration(aPath + QDir::separator() + "ParaViewReaders.xml");
413 MyCoreApp->loadConfiguration(aPath + QDir::separator() + "ParaViewSources.xml");
414 MyCoreApp->loadConfiguration(aPath + QDir::separator() + "ParaViewWriters.xml");
417 // Force creation of the PARAVIS engine
421 // Find created toolbars
422 QCoreApplication::processEvents();
424 QList<QToolBar*> allToolbars = aDesktop->findChildren<QToolBar*>();
425 foreach(QToolBar* aBar, allToolbars) {
426 if (!foreignToolbars.contains(aBar)) {
427 myToolbars[aBar] = true;
428 myToolbarBreaks[aBar] = false;
429 aBar->setVisible(false);
430 aBar->toggleViewAction()->setVisible(false);
436 // we need to start trace after connection is done
437 connect(pqApplicationCore::instance()->getObjectBuilder(), SIGNAL(finishedAddingServer(pqServer*)),
438 this, SLOT(onFinishedAddingServer(pqServer*)));
440 connect(pqApplicationCore::instance()->getObjectBuilder(), SIGNAL(dataRepresentationCreated(pqDataRepresentation*)),
441 this, SLOT(onDataRepresentationCreated(pqDataRepresentation*)));
443 SUIT_ResourceMgr* aResourceMgr = SUIT_Session::session()->resourceMgr();
444 bool isStop = aResourceMgr->booleanValue( "PARAVIS", "stop_trace", false );
447 // Start a timer to schedule asap:
448 // - the connection to the server
450 myInitTimer = new QTimer(aDesktop);
451 QObject::connect(myInitTimer, SIGNAL(timeout()), this, SLOT(onInitTimer()) );
452 myInitTimer->setSingleShot(true);
453 myInitTimer->start(0);
455 // Another timer to regularly push the trace onto the engine:
456 myPushTraceTimer = new QTimer(aDesktop);
457 QObject::connect(myPushTraceTimer, SIGNAL(timeout()), this, SLOT(onPushTraceTimer()) );
458 myPushTraceTimer->setSingleShot(false);
459 myPushTraceTimer->start(500);
462 this->VTKConnect = vtkEventQtSlotConnect::New();
464 vtkProcessModule* pm = vtkProcessModule::GetProcessModule();
466 vtkPVSession* pvs = dynamic_cast<vtkPVSession*>(pm->GetSession());
468 vtkPVProgressHandler* ph = pvs->GetProgressHandler();
470 this->VTKConnect->Connect(ph, vtkCommand::StartEvent,
471 this, SLOT(onStartProgress()));
472 this->VTKConnect->Connect(ph, vtkCommand::EndEvent,
473 this, SLOT(onEndProgress()));
478 connect(&pqActiveObjects::instance(),
479 SIGNAL(representationChanged(pqRepresentation*)),
480 this, SLOT(onRepresentationChanged(pqRepresentation*)));
483 void PVGUI_Module::onStartProgress()
485 QApplication::setOverrideCursor(Qt::WaitCursor);
488 void PVGUI_Module::onEndProgress()
490 QApplication::restoreOverrideCursor();
493 void PVGUI_Module::onFinishedAddingServer(pqServer* /*server*/)
495 SUIT_ResourceMgr* aResourceMgr = SUIT_Session::session()->resourceMgr();
496 bool isStop = aResourceMgr->booleanValue( "PARAVIS", "stop_trace", false );
501 void PVGUI_Module::onDataRepresentationCreated(pqDataRepresentation* data) {
505 if(!data->getLookupTable())
508 SUIT_ResourceMgr* aResourceMgr = SUIT_Session::session()->resourceMgr();
512 bool visible = aResourceMgr->booleanValue( "PARAVIS", "show_color_legend", false );
513 pqLookupTableManager* lut_mgr = pqApplicationCore::instance()->getLookupTableManager();
516 lut_mgr->setScalarBarVisibility(data,visible);
519 connect(data, SIGNAL(dataUpdated()), this, SLOT(onDataRepresentationUpdated()));
522 void PVGUI_Module::onDataRepresentationUpdated() {
523 SalomeApp_Study* activeStudy = dynamic_cast<SalomeApp_Study*>(application()->activeStudy());
524 if(!activeStudy) return;
526 activeStudy->Modified();
529 void PVGUI_Module::onVariableChanged(pqVariableType t, const QString) {
531 pqDisplayColorWidget* colorWidget = qobject_cast<pqDisplayColorWidget*>(sender());
535 if( t == VARIABLE_TYPE_NONE )
538 SUIT_ResourceMgr* aResourceMgr = SUIT_Session::session()->resourceMgr();
543 bool visible = aResourceMgr->booleanValue( "PARAVIS", "show_color_legend", false );
548 /*//VTN: getRepresentation is protected
549 pqDataRepresentation* data = colorWidget->getRepresentation();
551 if( !data->getLookupTable() )
554 pqLookupTableManager* lut_mgr = pqApplicationCore::instance()->getLookupTableManager();
557 lut_mgr->setScalarBarVisibility(data,visible);
560 pqColorToolbar* colorTooBar = qobject_cast<pqColorToolbar*>(colorWidget->parent());
564 pqScalarBarVisibilityReaction* scalarBarVisibility = colorTooBar->findChild<pqScalarBarVisibilityReaction *>();
565 if(scalarBarVisibility) {
566 scalarBarVisibility->setScalarBarVisibility(visible);
570 void PVGUI_Module::execPythonCommand(const QString& cmd, bool inSalomeConsole)
572 if ( inSalomeConsole ) {
573 if ( PyInterp_Dispatcher::Get()->IsBusy() ) return;
574 SalomeApp_Application* app =
575 dynamic_cast< SalomeApp_Application* >(SUIT_Session::session()->activeApplication());
576 PyConsole_Console* pyConsole = app->pythonConsole();
578 pyConsole->exec(cmd);
582 SalomeApp_Application* app =
583 dynamic_cast< SalomeApp_Application* >(SUIT_Session::session()->activeApplication());
584 PyConsole_Interp* pyInterp = app->pythonConsole()->getInterp();
586 pyInterp->run(cmd.toStdString().c_str());
587 // pqPythonManager* manager = qobject_cast<pqPythonManager*>
588 // ( pqApplicationCore::instance()->manager( "PYTHON_MANAGER" ) );
591 // pqPythonDialog* pyDiag = manager->pythonShellDialog();
594 // pqPythonShell* shell = pyDiag->shell();
596 // shell->executeScript(cmd);
604 \brief Initialisation timer event - fired only once, after the GUI loop is ready.
605 See creation in initialize().
607 void PVGUI_Module::onInitTimer()
609 #ifndef PARAVIS_WITH_FULL_CORBA
610 connectToExternalPVServer();
614 // if ( PyInterp_Dispatcher::Get()->IsBusy() )
616 // // Reschedule for later
617 // MESSAGE("interpreter busy -> rescheduling trace start.");
622 MESSAGE("timerEvent(): About to start trace....");
623 execPythonCommand("from paraview import smtrace;smtrace.start_trace()", false);
624 MESSAGE("timerEvent(): Trace STARTED....");
628 MESSAGE("initialize(): Initializing PARAVIS's Python context ...");
629 execPythonCommand("import paraview.servermanager as sm; sm.fromGUI=True", false);
630 MESSAGE("initialize(): Initialized.");
634 \brief Get list of embedded macros files
636 QStringList PVGUI_Module::getEmbeddedMacrosList()
638 QString aRootDir = getenv("PARAVIS_ROOT_DIR");
640 QString aSourcePath = aRootDir + "/bin/salome/Macro";
645 QDir aSourceDir(aSourcePath);
646 QStringList aSourceFiles = aSourceDir.entryList(aFilter, QDir::Files);
647 QStringList aFullPathSourceFiles;
648 foreach (QString aMacrosName, aSourceFiles) {
649 aFullPathSourceFiles << aSourceDir.absoluteFilePath(aMacrosName);
651 return aFullPathSourceFiles;
654 void PVGUI_Module::updateMacros()
656 pqPythonManager* aPythonManager = pqPVApplicationCore::instance()->pythonManager();
657 if(!aPythonManager) {
661 foreach (QString aStr, getEmbeddedMacrosList()) {
662 aPythonManager->addMacro(aStr);
668 \brief Get list of compliant dockable GUI elements
669 \param m map to be filled in ("type":"default_position")
671 void PVGUI_Module::windows( QMap<int, int>& m ) const
673 m.insert( LightApp_Application::WT_ObjectBrowser, Qt::LeftDockWidgetArea );
674 m.insert( LightApp_Application::WT_PyConsole, Qt::BottomDockWidgetArea );
675 // ParaView diagnostic output redirected here
676 m.insert( LightApp_Application::WT_LogWindow, Qt::BottomDockWidgetArea );
680 \brief Shows (toShow = true) or hides ParaView view window
682 void PVGUI_Module::showView( bool toShow )
685 SalomeApp_Application* anApp = getApp();
686 PVGUI_ViewManager* viewMgr =
687 dynamic_cast<PVGUI_ViewManager*>( anApp->getViewManager( PVGUI_Viewer::Type(), false ) );
689 viewMgr = new PVGUI_ViewManager( anApp->activeStudy(), anApp->desktop() );
690 anApp->addViewManager( viewMgr );
691 connect( viewMgr, SIGNAL( lastViewClosed( SUIT_ViewManager* ) ),
692 anApp, SLOT( onCloseView( SUIT_ViewManager* ) ) );
695 PVGUI_ViewWindow* pvWnd = dynamic_cast<PVGUI_ViewWindow*>( viewMgr->getActiveView() );
697 pvWnd = dynamic_cast<PVGUI_ViewWindow*>( viewMgr->createViewWindow() );
700 pvWnd->setShown( toShow );
701 if ( toShow ) pvWnd->setFocus();
705 \brief Slot to show help for proxy.
707 void PVGUI_Module::showHelpForProxy( const QString& groupname, const QString& proxyname )
709 pqHelpReaction::showProxyHelp(groupname, proxyname);
714 \brief Slot to show the waiting state.
716 void PVGUI_Module::onPreAccept()
718 getApp()->desktop()->statusBar()->showMessage(tr("STB_PREACCEPT"));
719 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
723 \brief Slot to show the ready state.
725 void PVGUI_Module::onPostAccept()
727 getApp()->desktop()->statusBar()->showMessage(tr("STB_POSTACCEPT"), 2000);
728 QTimer::singleShot(0, this, SLOT(endWaitCursor()));
732 \brief Slot to switch off wait cursor.
734 void PVGUI_Module::endWaitCursor()
736 QApplication::restoreOverrideCursor();
739 static void ParavisMessageOutput(QtMsgType type, const char *msg)
744 vtkOutputWindow::GetInstance()->DisplayText(msg);
747 vtkOutputWindow::GetInstance()->DisplayErrorText(msg);
750 vtkOutputWindow::GetInstance()->DisplayErrorText(msg);
753 vtkOutputWindow::GetInstance()->DisplayErrorText(msg);
759 \brief Activate module.
760 \param study current study
761 \return \c true if activaion is done successfully or 0 to prevent
764 bool PVGUI_Module::activateModule( SUIT_Study* study )
766 myOldMsgHandler = qInstallMsgHandler(ParavisMessageOutput);
768 SUIT_ExceptionHandler::addCleanUpRoutine( paravisCleanUp );
770 storeCommonWindowsState();
772 bool isDone = SalomeApp_Module::activateModule( study );
773 if ( !isDone ) return false;
776 if ( mySourcesMenuId != -1 ) menuMgr()->show(mySourcesMenuId);
777 if ( myFiltersMenuId != -1 ) menuMgr()->show(myFiltersMenuId);
778 if ( myFiltersMenuId != -1 ) menuMgr()->show(myMacrosMenuId);
779 if ( myFiltersMenuId != -1 ) menuMgr()->show(myToolbarsMenuId);
780 setMenuShown( true );
781 setToolShown( true );
783 restoreDockWidgetsState();
785 QMenu* aMenu = menuMgr()->findMenu( myRecentMenuId );
787 QList<QAction*> anActns = aMenu->actions();
788 for (int i = 0; i < anActns.size(); ++i) {
789 QAction* a = anActns.at(i);
795 QList<QMenu*>::iterator it;
796 for (it = myMenus.begin(); it != myMenus.end(); ++it) {
797 QAction* a = (*it)->menuAction();
802 if ( myRecentMenuId != -1 ) menuMgr()->show(myRecentMenuId);
804 ClientFindOrCreateParavisComponent(PARAVIS::GetCStudy(this));
811 \brief Deactivate module.
812 \param study current study
813 \return \c true if deactivaion is done successfully or 0 to prevent
814 deactivation on error
816 bool PVGUI_Module::deactivateModule( SUIT_Study* study )
818 MESSAGE("PARAVIS deactivation ...")
820 QMenu* aMenu = menuMgr()->findMenu( myRecentMenuId );
822 QList<QAction*> anActns = aMenu->actions();
823 for (int i = 0; i < anActns.size(); ++i) {
824 QAction* a = anActns.at(i);
826 a->setVisible(false);
830 QList<QMenu*>::iterator it;
831 for (it = myMenus.begin(); it != myMenus.end(); ++it) {
832 QAction* a = (*it)->menuAction();
834 a->setVisible(false);
837 QList<QDockWidget*> aStreamingViews = application()->desktop()->findChildren<QDockWidget*>("pqStreamingControls");
838 foreach(QDockWidget* aView, aStreamingViews) {
839 if (!myDockWidgets.contains(aView))
840 myDockWidgets[aView] = aView->isVisible();
843 /*if (pqImplementation::helpWindow) {
844 pqImplementation::helpWindow->hide();
848 menuMgr()->hide(myRecentMenuId);
849 menuMgr()->hide(mySourcesMenuId);
850 menuMgr()->hide(myFiltersMenuId);
851 menuMgr()->hide(myMacrosMenuId);
852 menuMgr()->hide(myToolbarsMenuId);
853 setMenuShown( false );
854 setToolShown( false );
856 saveDockWidgetsState();
858 SUIT_ExceptionHandler::removeCleanUpRoutine( paravisCleanUp );
861 qInstallMsgHandler(myOldMsgHandler);
863 restoreCommonWindowsState();
865 return SalomeApp_Module::deactivateModule( study );
870 \brief Called when application is closed.
872 Process finalize application functionality from ParaView in order to save server settings
873 and nullify application pointer if the application is being closed.
875 \param theApp application
877 void PVGUI_Module::onApplicationClosed( SUIT_Application* theApp )
879 pqApplicationCore::instance()->settings()->sync();
880 int aAppsNb = SUIT_Session::session()->applications().size();
882 deleteTemporaryFiles();
883 MyCoreApp->deleteLater();
885 CAM_Module::onApplicationClosed(theApp);
890 \brief Deletes temporary files created during import operation from VISU
892 void PVGUI_Module::deleteTemporaryFiles()
894 foreach(QString aFile, myTemporaryFiles) {
895 if (QFile::exists(aFile)) {
896 QFile::remove(aFile);
903 \brief Called when study is closed.
905 Removes data model from the \a study.
907 \param study study being closed
909 void PVGUI_Module::studyClosed(SUIT_Study* study)
911 clearParaviewState();
913 SalomeApp_Module::studyClosed(study);
917 \brief Called when study is opened.
919 void PVGUI_Module::onModelOpened()
921 _PTR(Study) studyDS = PARAVIS::GetCStudy(this);
926 _PTR(SComponent) paravisComp =
927 studyDS->FindComponent(GetEngine()->ComponentDataType());
932 _PTR(ChildIterator) anIter(studyDS->NewChildIterator(paravisComp));
933 for (; anIter->More(); anIter->Next()) {
934 _PTR(SObject) aSObj = anIter->Value();
935 _PTR(GenericAttribute) anAttr;
936 if (!aSObj->FindAttribute(anAttr, "AttributeLocalID")) {
939 _PTR(AttributeLocalID) anID(anAttr);
940 if (anID->Value() == PVSTATEID) {
947 // \brief Returns IOR of current engine
949 //QString PVGUI_Module::engineIOR() const
951 // CORBA::String_var anIOR = GetEngine()->GetIOR();
952 // return QString(anIOR.in());
957 \brief Open file of format supported by ParaView
959 void PVGUI_Module::openFile(const char* theName)
963 pqLoadDataReaction::loadData(aFiles);
966 void PVGUI_Module::executeScript(const char *script)
969 pqPythonManager* manager = qobject_cast<pqPythonManager*>(
970 pqApplicationCore::instance()->manager("PYTHON_MANAGER"));
972 pqPythonDialog* pyDiag = manager->pythonShellDialog();
974 pyDiag->runString(script);
981 // * Debug function printing out the given interpreter's execution context
983 //void printInterpContext(PyInterp_Interp * interp )
985 // // Extract __smtraceString from interpreter's context
986 // const PyObject* ctxt = interp->getExecutionContext();
988 // PyObject* lst = PyDict_Keys((PyObject *)ctxt);
989 // Py_ssize_t siz = PyList_GET_SIZE(lst);
990 // for (Py_ssize_t i = 0; i < siz; i++)
992 // PyObject * elem = PyList_GetItem(lst, i);
993 // if (PyString_Check(elem))
995 // std::cout << "At pos:" << i << ", " << PyString_AsString(elem) << std::endl;
998 // std::cout << "At pos:" << i << ", not a string!" << std::endl;
1004 \brief Returns trace string
1006 static const QString MYReplaceStr("paraview.simple");
1007 static const QString MYReplaceImportStr("except: from pvsimple import *");
1008 QString PVGUI_Module::getTraceString()
1010 QString traceString;
1013 PyLockWrapper lck; // Acquire GIL
1015 const char * code = "from paraview import smtrace;"
1016 "__smtraceString = smtrace.get_trace_string()";
1017 PyRun_SimpleString(code);
1018 // Now get the value of __smtraceString
1019 PyObject* main_module = PyImport_AddModule((char*)"__main__");
1020 PyObject* global_dict = PyModule_GetDict(main_module);
1021 PyObject* string_object = PyDict_GetItemString(global_dict, "__smtraceString");
1022 char* string_ptr = string_object ? PyString_AsString(string_object) : 0;
1024 traceString = string_ptr;
1028 if ((!traceString.isNull()) && traceString.length() != 0) {
1029 int aPos = traceString.indexOf(MYReplaceStr);
1030 while (aPos != -1) {
1031 traceString = traceString.replace(aPos, MYReplaceStr.length(), "pvsimple");
1032 aPos = traceString.indexOf(MYReplaceStr, aPos);
1034 int aImportPos = traceString.indexOf(MYReplaceImportStr);
1035 if(aImportPos != -1)
1037 traceString = traceString.replace(aImportPos, MYReplaceImportStr.length(), "except:\n import pvsimple\n from pvsimple import *");
1045 \brief Saves trace string to disk file
1047 void PVGUI_Module::saveTrace(const char* theName)
1049 QFile file(theName);
1050 if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
1051 MESSAGE( "Could not open file:" << theName );
1054 QTextStream out(&file);
1055 out << getTraceString();
1060 \brief Saves ParaView state to a disk file
1062 void PVGUI_Module::saveParaviewState(const char* theFileName)
1064 pqApplicationCore::instance()->saveState(theFileName);
1068 \brief Delete all objects for Paraview Pipeline Browser
1070 void PVGUI_Module::clearParaviewState()
1072 QAction* deleteAllAction = action(DeleteAllId);
1073 if (deleteAllAction) {
1074 deleteAllAction->activate(QAction::Trigger);
1079 \brief Restores ParaView state from a disk file
1081 If toClear == true, the current ojects will be deleted
1083 void PVGUI_Module::loadParaviewState(const char* theFileName)
1085 pqApplicationCore::instance()->loadState(theFileName, getActiveServer());
1089 \brief Returns current active ParaView server
1091 pqServer* PVGUI_Module::getActiveServer()
1093 return pqApplicationCore::instance()->getActiveServer();
1098 \brief Creates PARAVIS preference pane
1100 void PVGUI_Module::createPreferences()
1102 // Paraview settings tab
1103 int aParaViewSettingsTab = addPreference( tr( "TIT_PVIEWSETTINGS" ) );
1104 int aPanel = addPreference(QString(), aParaViewSettingsTab, LightApp_Preferences::UserDefined, "PARAVIS", "");
1105 setPreferenceProperty(aPanel, "content", (qint64)(new PVGUI_ParaViewSettingsPane()));
1107 // Paravis settings tab
1108 int aParaVisSettingsTab = addPreference( tr( "TIT_PVISSETTINGS" ) );
1109 addPreference( tr( "PREF_STOP_TRACE" ), aParaVisSettingsTab, LightApp_Preferences::Bool, "PARAVIS", "stop_trace");
1111 int aSaveType = addPreference(tr( "PREF_SAVE_TYPE_LBL" ), aParaVisSettingsTab,
1112 LightApp_Preferences::Selector,
1113 "PARAVIS", "savestate_type");
1114 QList<QVariant> aIndices;
1115 QStringList aStrings;
1117 aStrings<<tr("PREF_SAVE_TYPE_0");
1118 aStrings<<tr("PREF_SAVE_TYPE_1");
1119 aStrings<<tr("PREF_SAVE_TYPE_2");
1120 setPreferenceProperty(aSaveType, "strings", aStrings);
1121 setPreferenceProperty(aSaveType, "indexes", aIndices);
1123 //rnv: imp 21712: [CEA 581] Preference to display legend by default
1124 int aDispColoreLegend = addPreference( tr( "PREF_SHOW_COLOR_LEGEND" ), aParaVisSettingsTab,
1125 LightApp_Preferences::Bool, "PARAVIS", "show_color_legend");
1129 \brief Creates ParaViS context menu popup
1131 void PVGUI_Module::contextMenuPopup(const QString& theClient, QMenu* theMenu, QString& theTitle)
1133 SalomeApp_Module::contextMenuPopup(theClient, theMenu, theTitle);
1135 // Check if we are in Object Browser
1136 SUIT_DataBrowser* ob = getApp()->objectBrowser();
1137 bool isOBClient = (ob && theClient == ob->popupClientType());
1142 // Get list of selected objects
1143 LightApp_SelectionMgr* aSelectionMgr = getApp()->selectionMgr();
1144 SALOME_ListIO aListIO;
1145 aSelectionMgr->selectedObjects(aListIO);
1146 if (aListIO.Extent() == 1 && aListIO.First()->hasEntry()) {
1147 QString entry = QString(aListIO.First()->getEntry());
1150 SalomeApp_Study* activeStudy =
1151 dynamic_cast<SalomeApp_Study*>(getApp()->activeStudy());
1156 // Get SALOMEDS client study
1157 _PTR(Study) studyDS = activeStudy->studyDS();
1162 QString paravisDataType(GetEngine()->ComponentDataType());
1163 if(activeStudy && activeStudy->isComponent(entry) &&
1164 activeStudy->componentDataType(entry) == paravisDataType) {
1165 // ParaViS module object
1166 theMenu->addSeparator();
1167 theMenu->addAction(action(SaveStatePopupId));
1170 // Try to get state object
1171 _PTR(SObject) stateSObj =
1172 studyDS->FindObjectID(entry.toLatin1().constData());
1178 _PTR(GenericAttribute) anAttr;
1179 if (!stateSObj->FindAttribute(anAttr, "AttributeLocalID")) {
1183 _PTR(AttributeLocalID) anID(anAttr);
1185 if (anID->Value() == PVSTATEID) {
1186 // Paraview state object
1187 theMenu->addSeparator();
1188 theMenu->addAction(action(AddStatePopupId));
1189 theMenu->addAction(action(CleanAndAddStatePopupId));
1190 theMenu->addSeparator();
1191 theMenu->addAction(action(ParaVisRenameId));
1192 theMenu->addAction(action(ParaVisDeleteId));
1199 \brief. Show ParaView python trace.
1201 void PVGUI_Module::onShowTrace()
1203 if (!myTraceWindow) {
1204 myTraceWindow = new pqPythonScriptEditor(getApp()->desktop());
1206 myTraceWindow->setText(getTraceString());
1207 myTraceWindow->show();
1208 myTraceWindow->raise();
1209 myTraceWindow->activateWindow();
1214 \brief. Re-initialize ParaView python trace.
1216 void PVGUI_Module::onRestartTrace()
1218 QString script = "from paraview import smtrace\n";
1219 script += "smtrace.stop_trace()\n";
1220 script += "smtrace.start_trace()\n";
1221 execPythonCommand(script, false);
1225 \brief Show ParaView view.
1227 void PVGUI_Module::onNewParaViewWindow()
1233 \brief Save state under the module root object.
1235 void PVGUI_Module::onSaveMultiState()
1237 // Create state study object
1239 // Get SALOMEDS client study
1240 _PTR(Study) studyDS = PARAVIS::GetCStudy(this);
1245 _PTR(SComponent) paravisComp =
1246 studyDS->FindComponent(GetEngine()->ComponentDataType());
1251 // Unlock the study if it is locked
1252 bool isLocked = studyDS->GetProperties()->IsLocked();
1254 studyDS->GetProperties()->SetLocked(false);
1257 QString stateName = tr("SAVED_PARAVIEW_STATE_NAME") +
1258 QString::number(myStateCounter + 1);
1260 _PTR(StudyBuilder) studyBuilder = studyDS->NewBuilder();
1261 _PTR(SObject) newSObj = studyBuilder->NewObject(paravisComp);
1264 _PTR(GenericAttribute) anAttr;
1265 anAttr = studyBuilder->FindOrCreateAttribute(newSObj, "AttributeName");
1266 _PTR(AttributeName) nameAttr(anAttr);
1268 nameAttr->SetValue(stateName.toLatin1().constData());
1271 anAttr = studyBuilder->FindOrCreateAttribute(newSObj, "AttributeLocalID");
1272 _PTR(AttributeLocalID) localIdAttr(anAttr);
1274 localIdAttr->SetValue(PVSTATEID);
1277 QString stateEntry = QString::fromStdString(newSObj->GetID());
1279 // File name for state saving
1280 QString tmpDir = QString::fromStdString(SALOMEDS_Tool::GetTmpDir());
1281 QString fileName = QString("%1_paravisstate:%2").arg(tmpDir, stateEntry);
1283 anAttr = studyBuilder->FindOrCreateAttribute(newSObj, "AttributeString");
1284 _PTR(AttributeString) stringAttr(anAttr);
1286 stringAttr->SetValue(fileName.toLatin1().constData());
1288 // Lock the study back if necessary
1290 studyDS->GetProperties()->SetLocked(true);
1294 saveParaviewState(fileName.toLatin1().constData());
1295 myTemporaryFiles.append(fileName);
1297 // Increment the counter
1304 \brief Restore the selected state by merging with the current one.
1306 void PVGUI_Module::onAddState()
1308 loadSelectedState(false);
1312 \brief Clean the current state and restore the selected one.
1314 void PVGUI_Module::onCleanAddState()
1316 loadSelectedState(true);
1320 \brief Rename the selected object.
1322 void PVGUI_Module::onRename()
1324 LightApp_SelectionMgr* aSelectionMgr = getApp()->selectionMgr();
1325 SALOME_ListIO aListIO;
1326 aSelectionMgr->selectedObjects(aListIO);
1328 if (aListIO.Extent() == 1 && aListIO.First()->hasEntry()) {
1329 std::string entry = aListIO.First()->getEntry();
1331 // Get SALOMEDS client study
1332 _PTR(Study) studyDS = PARAVIS::GetCStudy(this);
1337 // Unlock the study if it is locked
1338 bool isLocked = studyDS->GetProperties()->IsLocked();
1340 studyDS->GetProperties()->SetLocked(false);
1343 // Rename the selected state object
1344 _PTR(SObject) stateSObj = studyDS->FindObjectID(entry);
1349 _PTR(GenericAttribute) anAttr;
1350 if (stateSObj->FindAttribute(anAttr, "AttributeName")) {
1351 _PTR(AttributeName) nameAttr (anAttr);
1353 LightApp_NameDlg::getName(getApp()->desktop(), nameAttr->Value().c_str());
1354 if (!newName.isEmpty()) {
1355 nameAttr->SetValue(newName.toLatin1().constData());
1356 aListIO.First()->setName(newName.toLatin1().constData());
1360 // Lock the study back if necessary
1362 studyDS->GetProperties()->SetLocked(true);
1365 // Update object browser
1372 \brief Delete the selected objects.
1374 void PVGUI_Module::onDelete()
1376 LightApp_SelectionMgr* aSelectionMgr = getApp()->selectionMgr();
1377 SALOME_ListIO aListIO;
1378 aSelectionMgr->selectedObjects(aListIO);
1380 if (aListIO.Extent() == 1 && aListIO.First()->hasEntry()) {
1381 std::string entry = aListIO.First()->getEntry();
1383 // Get SALOMEDS client study
1384 _PTR(Study) studyDS = PARAVIS::GetCStudy(this);
1389 // Unlock the study if it is locked
1390 bool isLocked = studyDS->GetProperties()->IsLocked();
1392 studyDS->GetProperties()->SetLocked(false);
1395 // Remove the selected state from the study
1396 _PTR(StudyBuilder) studyBuilder = studyDS->NewBuilder();
1397 _PTR(SObject) stateSObj = studyDS->FindObjectID(entry);
1398 studyBuilder->RemoveObject(stateSObj);
1400 // Lock the study back if necessary
1402 studyDS->GetProperties()->SetLocked(true);
1405 // Update object browser
1410 void PVGUI_Module::onPushTraceTimer()
1412 // MESSAGE("onPushTraceTimer(): Pushing trace to engine...");
1413 GetEngine()->PutPythonTraceStringToEngine(getTraceString().toStdString().c_str());
1417 \brief Discover help project files from the resources.
1418 \return name of the help file.
1420 QString PVGUI_Module::getHelpFileName() {
1421 QString aPVHome(getenv("PVHOME"));
1422 if (aPVHome.isNull()) {
1423 qWarning("Wariable PVHOME is not defined");
1426 QChar aSep = QDir::separator();
1427 //PARAVIEW_VERSION from the vtkPVConfig.h file
1428 QString aFileName = aPVHome + aSep + "share" + aSep + "doc" + aSep + "paraview-"+ PARAVIEW_VERSION + aSep + "paraview.qch";
1434 \brief Load selected paraview state
1436 If toClear == true, the current state will be cleared
1438 void PVGUI_Module::loadSelectedState(bool toClear)
1442 LightApp_SelectionMgr* aSelectionMgr = getApp()->selectionMgr();
1443 SALOME_ListIO aListIO;
1444 aSelectionMgr->selectedObjects(aListIO);
1446 if (aListIO.Extent() == 1 && aListIO.First()->hasEntry()) {
1447 std::string entry = aListIO.First()->getEntry();
1449 // Get SALOMEDS client study
1450 _PTR(Study) studyDS = PARAVIS::GetCStudy(this);
1456 _PTR(SObject) stateSObj = studyDS->FindObjectID(entry);
1457 _PTR(GenericAttribute) anAttr;
1458 if (!stateSObj->FindAttribute(anAttr, "AttributeLocalID")) {
1461 _PTR(AttributeLocalID) anID(anAttr);
1462 if (!anID->Value() == PVSTATEID) {
1466 // Get state file name
1467 if (stateSObj->FindAttribute(anAttr, "AttributeString")) {
1468 _PTR(AttributeString) aStringAttr(anAttr);
1469 QString stringValue(aStringAttr->Value().c_str());
1471 if (QFile::exists(stringValue)) {
1472 fileName = stringValue;
1477 if (!fileName.isEmpty()) {
1479 clearParaviewState();
1482 loadParaviewState(fileName.toLatin1().constData());
1485 SUIT_MessageBox::critical(getApp()->desktop(),
1487 tr("ERR_STATE_CANNOT_BE_RESTORED"));
1491 void PVGUI_Module::onRepresentationChanged(pqRepresentation*) {
1494 //rnv: to fix the issue "21712: [CEA 581] Preference to display legend by default"
1495 // find the pqDisplayColorWidget instances and connect the variableChanged SIGNAL on the
1496 // onVariableChanged slot of this class. This connection needs to change visibility
1497 // of the "Colored Legend" after change the "Color By" array.
1498 QList<pqDisplayColorWidget*> aWidget = getApp()->desktop()->findChildren<pqDisplayColorWidget*>();
1500 for (int i = 0; i < aWidget.size() ; i++ ) {
1502 connect( aWidget[i], SIGNAL ( variableChanged ( pqVariableType, const QString ) ),
1503 this, SLOT(onVariableChanged( pqVariableType, const QString) ), Qt::UniqueConnection );
1510 \fn CAM_Module* createModule();
1511 \brief Export module instance (factory function).
1512 \return new created instance of the module
1516 #define PVGUI_EXPORT __declspec(dllexport)
1518 #define PVGUI_EXPORT
1524 PVGUI_EXPORT CAM_Module* createModule() {
1529 return new PVGUI_Module();
1532 PVGUI_EXPORT char* getModuleVersion() {
1533 return (char*)PARAVIS_VERSION_STR;