1 // PARAVIS : ParaView wrapper SALOME module
3 // Copyright (C) 2010-2012 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.
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 #include "SALOMEconfig.h"
33 #include CORBA_CLIENT_HEADER(VISU_Gen)
35 #include CORBA_SERVER_HEADER(SALOMEDS)
38 #include "PARAVIS_Gen_i.hh"
42 #include "PVGUI_ViewModel.h"
43 #include "PVGUI_ViewManager.h"
44 #include "PVGUI_ViewWindow.h"
45 #include "PVGUI_Tools.h"
46 #include "PVGUI_ParaViewSettingsPane.h"
47 #include "PVGUI_OutputWindowAdapter.h"
49 #include <SUIT_DataBrowser.h>
50 #include <SUIT_Desktop.h>
51 #include <SUIT_MessageBox.h>
52 #include <SUIT_ResourceMgr.h>
53 #include <SUIT_Session.h>
54 #include <SUIT_OverrideCursor.h>
57 #include "SALOME_LifeCycleCORBA.hxx"
58 #include "SALOMEDS_SObject.hxx"
60 #include "LightApp_SelectionMgr.h"
61 #include "LightApp_NameDlg.h"
63 #include <SalomeApp_Application.h>
64 #include <SalomeApp_Study.h>
65 #include <SALOME_ListIO.hxx>
66 #include <SALOMEDS_Tool.hxx>
67 #include <PyInterp_Dispatcher.h>
69 #include <QtxActionMenuMgr.h>
70 #include <QtxActionToolMgr.h>
73 #include <QApplication>
79 #include <QInputDialog>
83 #include <QStringList>
86 #include <QTextStream>
88 #include <QDockWidget>
89 #include <QHelpEngine>
91 #include <pqApplicationCore.h>
92 #include <pqPVApplicationCore.h>
93 #include <pqActiveView.h>
94 #include <pqObjectBuilder.h>
95 #include <pqOptions.h>
96 #include <pqRenderView.h>
98 #include <pqUndoStack.h>
99 #include <pqVCRController.h>
100 #include <pqTabbedMultiViewWidget.h>
101 #include <pqPipelineSource.h>
102 #include <pqActiveObjects.h>
103 #include <vtkProcessModule.h>
104 #include <pqParaViewBehaviors.h>
105 #include <pqHelpReaction.h>
106 #include <vtkOutputWindow.h>
107 #include <pqPluginManager.h>
108 //#include <vtkPVPluginInformation.h>
109 #include "pqInterfaceTracker.h"
110 #include <pqSettings.h>
111 #include <pqPythonDialog.h>
112 #include <pqPythonManager.h>
113 #include <pqPythonShell.h>
114 #include <pqBrandPluginsLoader.h>
115 #include <pqLoadDataReaction.h>
116 #include <vtkEventQtSlotConnect.h>
117 #include <pqPythonScriptEditor.h>
118 #include <pqStandardSummaryPanelImplementation.h>
119 #include <pqCollaborationBehavior.h>
120 #include <pqDataRepresentation.h>
121 #include <pqPipelineRepresentation.h>
122 #include <pqLookupTableManager.h>
123 #include <pqDisplayColorWidget.h>
125 #include <PARAVIS_version.h>
127 #include <vtkPVConfig.h>
129 #include CORBA_SERVER_HEADER(SALOME_ModuleCatalog)
132 * Make sure all the kits register their classes with vtkInstantiator.
133 * Since ParaView uses Tcl wrapping, all of VTK is already compiled in
134 * anyway. The instantiators will add no more code for the linker to
138 #include <vtkCommonInstantiator.h>
139 #include <vtkFilteringInstantiator.h>
140 #include <vtkGenericFilteringInstantiator.h>
141 #include <vtkIOInstantiator.h>
142 #include <vtkImagingInstantiator.h>
143 #include <vtkInfovisInstantiator.h>
144 #include <vtkGraphicsInstantiator.h>
146 #include <vtkRenderingInstantiator.h>
147 #include <vtkVolumeRenderingInstantiator.h>
148 #include <vtkHybridInstantiator.h>
149 #include <vtkParallelInstantiator.h>
151 #include <pqAlwaysConnectedBehavior.h>
152 #include <pqApplicationCore.h>
153 #include <pqAutoLoadPluginXMLBehavior.h>
154 #include <pqCommandLineOptionsBehavior.h>
155 #include <pqCrashRecoveryBehavior.h>
156 #include <pqDataTimeStepBehavior.h>
157 #include <pqDefaultViewBehavior.h>
158 #include <pqDeleteBehavior.h>
159 #include <pqObjectPickingBehavior.h>
160 #include <pqPersistentMainWindowStateBehavior.h>
161 #include <pqPipelineContextMenuBehavior.h>
162 #include <pqPluginActionGroupBehavior.h>
163 #include <pqPluginDockWidgetsBehavior.h>
164 #include <pqPluginManager.h>
165 #include <pqPVNewSourceBehavior.h>
166 #include <pqSpreadSheetVisibilityBehavior.h>
167 #include <pqStandardViewModules.h>
168 #include <pqUndoRedoBehavior.h>
169 #include <pqViewFrameActionsBehavior.h>
170 #include <pqServerManagerObserver.h>
172 #include <vtkClientServerInterpreterInitializer.h>
175 //----------------------------------------------------------------------------
176 pqPVApplicationCore* PVGUI_Module::MyCoreApp = 0;
177 //PVGUI_OutputWindowAdapter* PVGUI_Module::pqImplementation::OutputWindowAdapter = 0;
178 //QPointer<pqHelpWindow> PVGUI_Module::pqImplementation::helpWindow = 0;
180 PVGUI_Module* ParavisModule = 0;
185 <h2>Building and installing PARAVIS</h2>
186 As any other SALOME module, PARAVIS requires PARAVIS_ROOT_DIR environment variable to be set to PARAVIS
187 installation directory.
188 Other variables needed for correct detection of ParaView location:
189 \li PVHOME - points at the ParaView installation directory tree
190 \li PVVERSION - number of ParaView version
192 It also requires common SALOME environment including GUI_ROOT_DIR and other prerequsites.
195 PARAVIS module can be launched using the following commands:
196 \li Full SALOME configuration
198 runSalome --modules="PARAVIS"
201 <h2>ParaView GUI integration</h2>
202 <h3>ParaView GUI integration overview</h3>
204 The main idea is to reuse ParaView GUI internal logic as much as possible, providing a layer
205 between it and SALOME GUI that hides the following SALOME GUI implementation details from ParaView:
207 \li SALOME GUI executable and Qt event loop
208 \li SALOME GUI desktop
209 \li Dock windows areas
210 \li SALOME menu and toolbar managers
212 Major part of the integration is implemented in PVGUI_Module class.
214 <h3>ParaView client initalization</h3>
216 ParaView client initalization is performed when an instance of PVGUI_Module class has been created
217 and \link PVGUI_Module::initialize() PVGUI_Module::initialize()\endlink method is called by SALOME GUI.
218 The actual client start-up is done in \link PVGUI_Module::pvInit() PVGUI_Module::pvInit()\endlink method.
221 <h3>Multi-view manager</h3>
223 SALOME GUI requires that each kind of view be implemnted with help of (at least) three classes. For ParaView multi-view manager
226 \li PVGUI_ViewManager - view manager class
227 \li PVGUI_Viewer - view model class
228 \li PVGUI_ViewWindow - view window class that acts as a parent for %pqViewManager
230 Single instances of PVGUI_ViewManager and PVGUI_ViewWindow classes are created by \link PVGUI_Module::showView()
231 PVGUI_Module::showView()\endlink method upon the first PARAVIS module activation. The same method hides the multi-view manager
232 when the module is deactivated (the user switches to another module or a study is closed).
233 A special trick is used to make PVGUI_ViewWindow the parent of %pqViewManager widget. It is created initally by %pqMainWindowCore
234 with the desktop as a parent, so when it is shown PVGUI_ViewWindow instance is passed to its setParent() method. In
235 \link PVGUI_ViewWindow::~PVGUI_ViewWindow() PVGUI_ViewWindow::~PVGUI_ViewWindow()\endlink the parent is nullified to avoid deletion
236 of %pqViewManager widget that would break %pqMainWindowCore class.
238 <h3>ParaView plugins</h3>
239 ParaView server and client plugins are managed by %pqMainWindowCore slots that has full access to PARAVIS menus and toolbars.
240 As a result they appears automatically in PARAVIS menus and toolbars if loaded successfully.
245 \brief Implementation
246 SALOME module wrapping ParaView GUI.
251 Fix for the issue 21730: [CEA 596] Slice of polyhedron in PARAVIS returns no cell.
252 Wrap vtkEDFCutter filter.
255 extern "C" void vtkEDFCutterCS_Initialize(vtkClientServerInterpreter*);
256 static void vtkEDFHelperInit();
258 void vtkEDFHelperInit(vtkClientServerInterpreter* interp){
259 vtkEDFCutterCS_Initialize(interp);
262 void vtkEDFHelperInit() {
263 vtkClientServerInterpreterInitializer::GetInitializer()->
264 RegisterCallback(&vtkEDFHelperInit);
269 ClientFindOrCreateParavisComponent(_PTR(Study) theStudyDocument)
271 _PTR(SComponent) aSComponent = theStudyDocument->FindComponent("PARAVIS");
273 _PTR(StudyBuilder) aStudyBuilder = theStudyDocument->NewBuilder();
274 aStudyBuilder->NewCommand();
275 int aLocked = theStudyDocument->GetProperties()->IsLocked();
276 if (aLocked) theStudyDocument->GetProperties()->SetLocked(false);
277 aSComponent = aStudyBuilder->NewComponent("PARAVIS");
278 _PTR(GenericAttribute) anAttr =
279 aStudyBuilder->FindOrCreateAttribute(aSComponent, "AttributeName");
280 _PTR(AttributeName) aName (anAttr);
282 CORBA::ORB_var anORB = PARAVIS::PARAVIS_Gen_i::GetORB();
283 SALOME_NamingService *NamingService = new SALOME_NamingService( anORB );
284 CORBA::Object_var objVarN = NamingService->Resolve("/Kernel/ModulCatalog");
285 SALOME_ModuleCatalog::ModuleCatalog_var Catalogue =
286 SALOME_ModuleCatalog::ModuleCatalog::_narrow(objVarN);
287 SALOME_ModuleCatalog::Acomponent_var Comp = Catalogue->GetComponent( "PARAVIS" );
288 if (!Comp->_is_nil()) {
289 aName->SetValue(Comp->componentusername());
292 anAttr = aStudyBuilder->FindOrCreateAttribute(aSComponent, "AttributePixMap");
293 _PTR(AttributePixMap) aPixmap (anAttr);
294 aPixmap->SetPixMap( "pqAppIcon16.png" );
296 // Create Attribute parameters for future using
297 anAttr = aStudyBuilder->FindOrCreateAttribute(aSComponent, "AttributeParameter");
300 PARAVIS::PARAVIS_Gen_var aPARAVIS = PARAVIS::PARAVIS_Gen_i::GetParavisGenImpl()->_this();
302 aStudyBuilder->DefineComponentInstance(aSComponent, aPARAVIS->GetIOR());
303 if (aLocked) theStudyDocument->GetProperties()->SetLocked(true);
304 aStudyBuilder->CommitCommand();
310 \brief Constructor. Sets the default name for the module.
312 PVGUI_Module::PVGUI_Module()
313 : SalomeApp_Module( "PARAVIS" ),
314 LightApp_Module( "PARAVIS" ),
315 // Implementation( 0 ),
316 mySelectionControlsTb( -1 ),
317 mySourcesMenuId( -1 ),
318 myFiltersMenuId( -1 ),
320 myToolbarsMenuId(-1),
327 Q_INIT_RESOURCE( PVGUI );
329 ParavisModule = this;
332 QString aDestPath = QString( "%1/.config/%2/Macros" ).arg( QDir::homePath() ).arg( QApplication::applicationName() );
336 QDir aDestDir(aDestPath);
337 QStringList aDestFiles = aDestDir.entryList(aFilter, QDir::Files);
338 foreach (QString aStr, aDestFiles) {
339 aDestDir.remove(aStr);
346 PVGUI_Module::~PVGUI_Module()
353 \brief Initialize module. Creates menus, prepares context menu, etc.
354 \param app SALOME GUI application instance
356 void PVGUI_Module::initialize( CAM_Application* app )
358 SalomeApp_Module::initialize( app );
360 // Create ParaViS actions
362 // Create ParaViS menus
365 // Uncomment to debug ParaView initialization
366 // "aa" used instead of "i" as GDB doesn't like "i" variables :)
374 // Initialize ParaView client
377 // Create GUI elements (menus, toolbars, dock widgets)
378 //if ( !Implementation ){
379 SalomeApp_Application* anApp = getApp();
380 SUIT_Desktop* aDesktop = anApp->desktop();
382 // connect(aDesktop, SIGNAL()
384 // Remember current state of desktop toolbars
385 QList<QToolBar*> foreignToolbars = aDesktop->findChildren<QToolBar*>();
387 // Simulate ParaView client main window
388 //Implementation = new pqImplementation( aDesktop );
396 // new pqParaViewBehaviors(anApp->desktop(), this);
397 // Has to be replaced in order to exclude using of pqQtMessageHandlerBehaviour
398 // Start pqParaViewBehaviors
399 // Register ParaView interfaces.
400 //pqPluginManager* pgm = pqApplicationCore::instance()->getPluginManager();
401 pqInterfaceTracker* pgm = pqApplicationCore::instance()->interfaceTracker();
403 // * adds support for standard paraview views.
404 pgm->addInterface(new pqStandardViewModules(pgm));
405 pgm->addInterface(new pqStandardSummaryPanelImplementation(pgm));
407 // Load plugins distributed with application.
408 pqApplicationCore::instance()->loadDistributedPlugins();
410 // Define application behaviors.
411 //new pqQtMessageHandlerBehavior(this);
412 new pqDataTimeStepBehavior(this);
413 new pqViewFrameActionsBehavior(this);
414 new pqSpreadSheetVisibilityBehavior(this);
415 new pqPipelineContextMenuBehavior(this);
416 new pqDefaultViewBehavior(this);
417 new pqAlwaysConnectedBehavior(this);
418 new pqPVNewSourceBehavior(this);
419 new pqDeleteBehavior(this);
420 new pqUndoRedoBehavior(this);
421 new pqCrashRecoveryBehavior(this);
422 new pqAutoLoadPluginXMLBehavior(this);
423 new pqPluginDockWidgetsBehavior(aDesktop);
424 //new pqVerifyRequiredPluginBehavior(this);
425 new pqPluginActionGroupBehavior(aDesktop);
426 //new pqFixPathsInStateFilesBehavior(this);
427 new pqCommandLineOptionsBehavior(this);
428 new pqPersistentMainWindowStateBehavior(aDesktop);
429 new pqObjectPickingBehavior(aDesktop);
430 new pqCollaborationBehavior(this);
432 // Setup quick-launch shortcuts.
433 QShortcut *ctrlSpace = new QShortcut(Qt::CTRL + Qt::Key_Space, aDesktop);
434 QObject::connect(ctrlSpace, SIGNAL(activated()),
435 pqApplicationCore::instance(), SLOT(quickLaunch()));
436 QShortcut *altSpace = new QShortcut(Qt::ALT + Qt::Key_Space, aDesktop);
437 QObject::connect(altSpace, SIGNAL(activated()),
438 pqApplicationCore::instance(), SLOT(quickLaunch()));
439 // End pqParaViewBehaviors
442 SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr();
443 QString aPath = resMgr->stringValue("resources", "PARAVIS", QString());
444 if (!aPath.isNull()) {
445 MyCoreApp->loadConfiguration(aPath + QDir::separator() + "ParaViewFilters.xml");
446 MyCoreApp->loadConfiguration(aPath + QDir::separator() + "ParaViewReaders.xml");
447 MyCoreApp->loadConfiguration(aPath + QDir::separator() + "ParaViewSources.xml");
448 MyCoreApp->loadConfiguration(aPath + QDir::separator() + "ParaViewWriters.xml");
451 // Force creation of engine
452 PARAVIS::GetParavisGen(this);
455 // Find created toolbars
456 QCoreApplication::processEvents();
458 QList<QToolBar*> allToolbars = aDesktop->findChildren<QToolBar*>();
459 foreach(QToolBar* aBar, allToolbars) {
460 if (!foreignToolbars.contains(aBar)) {
461 myToolbars[aBar] = true;
462 myToolbarBreaks[aBar] = false;
463 aBar->setVisible(false);
464 aBar->toggleViewAction()->setVisible(false);
471 // we need to start trace after connection is done
472 connect(pqApplicationCore::instance()->getObjectBuilder(), SIGNAL(finishedAddingServer(pqServer*)),
473 this, SLOT(onFinishedAddingServer(pqServer*)));
475 connect(pqApplicationCore::instance()->getObjectBuilder(), SIGNAL(dataRepresentationCreated(pqDataRepresentation*)),
476 this, SLOT(onDataRepresentationCreated(pqDataRepresentation*)));
479 SUIT_ResourceMgr* aResourceMgr = SUIT_Session::session()->resourceMgr();
480 bool isStop = aResourceMgr->booleanValue( "PARAVIS", "stop_trace", false );
481 // start timer to activate trace in a proper moment
485 this->VTKConnect = vtkEventQtSlotConnect::New();
486 vtkProcessModule* pm = vtkProcessModule::GetProcessModule();
488 this->VTKConnect->Connect(pm, vtkCommand::StartEvent,
489 this, SLOT(onStartProgress()));
490 this->VTKConnect->Connect(pm, vtkCommand::EndEvent,
491 this, SLOT(onEndProgress()));
493 connect(&pqActiveObjects::instance(),
494 SIGNAL(representationChanged(pqRepresentation*)),
495 this, SLOT(onRepresentationChanged(pqRepresentation*)));
498 void PVGUI_Module::onStartProgress()
500 QApplication::setOverrideCursor(Qt::WaitCursor);
503 void PVGUI_Module::onEndProgress()
505 QApplication::restoreOverrideCursor();
508 void PVGUI_Module::onFinishedAddingServer(pqServer* /*server*/)
510 SUIT_ResourceMgr* aResourceMgr = SUIT_Session::session()->resourceMgr();
511 bool isStop = aResourceMgr->booleanValue( "PARAVIS", "stop_trace", false );
516 void PVGUI_Module::onDataRepresentationCreated(pqDataRepresentation* data) {
520 if(!data->getLookupTable())
523 SUIT_ResourceMgr* aResourceMgr = SUIT_Session::session()->resourceMgr();
527 bool visible = aResourceMgr->booleanValue( "PARAVIS", "show_color_legend", false );
528 pqLookupTableManager* lut_mgr = pqApplicationCore::instance()->getLookupTableManager();
531 lut_mgr->setScalarBarVisibility(data,visible);
535 void PVGUI_Module::onVariableChanged(pqVariableType t, const QString) {
537 pqDisplayColorWidget* colorWidget = qobject_cast<pqDisplayColorWidget*>(sender());
541 if( t == VARIABLE_TYPE_NONE )
544 pqDataRepresentation* data = colorWidget->getRepresentation();
546 if( !data->getLookupTable() )
549 SUIT_ResourceMgr* aResourceMgr = SUIT_Session::session()->resourceMgr();
554 bool visible = aResourceMgr->booleanValue( "PARAVIS", "show_color_legend", false );
559 pqLookupTableManager* lut_mgr = pqApplicationCore::instance()->getLookupTableManager();
562 lut_mgr->setScalarBarVisibility(data,visible);
569 \brief Launches a tracing of current server
571 void PVGUI_Module::timerEvent(QTimerEvent* te )
574 PyInterp_Dispatcher* aDispatcher = PyInterp_Dispatcher::Get();
575 if ( !aDispatcher->IsBusy() ) {
576 pqPythonManager* manager = qobject_cast<pqPythonManager*>
577 ( pqApplicationCore::instance()->manager( "PYTHON_MANAGER" ) );
579 pqPythonDialog* pyDiag = manager->pythonShellDialog();
581 pqPythonShell* shell = pyDiag->shell();
583 QString script = "from paraview import smtrace\nsmtrace.start_trace()\n";
584 shell->executeScript(script);
585 killTimer( te->timerId() );
593 void PVGUI_Module::updateMacros()
595 pqPythonManager* aPythonManager = pqPVApplicationCore::instance()->pythonManager();
596 if(!aPythonManager) {
600 QString aRootDir = getenv("PARAVIS_ROOT_DIR");
602 QString aSourcePath = aRootDir + "/bin/salome/Macro";
607 QDir aSourceDir(aSourcePath);
608 QStringList aSourceFiles = aSourceDir.entryList(aFilter, QDir::Files);
609 foreach (QString aStr, aSourceFiles) {
610 aPythonManager->addMacro(aSourcePath + "/" + aStr);
616 \brief Get list of compliant dockable GUI elements
617 \param m map to be filled in ("type":"default_position")
619 void PVGUI_Module::windows( QMap<int, int>& m ) const
621 m.insert( LightApp_Application::WT_ObjectBrowser, Qt::LeftDockWidgetArea );
622 m.insert( LightApp_Application::WT_PyConsole, Qt::BottomDockWidgetArea );
623 // ParaView diagnostic output redirected here
624 m.insert( LightApp_Application::WT_LogWindow, Qt::BottomDockWidgetArea );
628 \brief Static method, performs initialization of ParaView session.
629 \return \c true if ParaView has been initialized successfully, otherwise false
631 bool PVGUI_Module::pvInit()
633 // if ( !pqImplementation::Core ){
635 // Obtain command-line arguments
638 QString aOptions = getenv("PARAVIS_OPTIONS");
639 QStringList aOptList = aOptions.split(":", QString::SkipEmptyParts);
640 argv = new char*[aOptList.size() + 1];
641 QStringList args = QApplication::arguments();
642 argv[0] = (args.size() > 0)? strdup(args[0].toLatin1().constData()) : strdup("paravis");
645 foreach (QString aStr, aOptList) {
646 argv[argc] = strdup( aStr.toLatin1().constData() );
649 MyCoreApp = new pqPVApplicationCore (argc, argv);
650 if (MyCoreApp->getOptions()->GetHelpSelected() ||
651 MyCoreApp->getOptions()->GetUnknownArgument() ||
652 MyCoreApp->getOptions()->GetErrorMessage() ||
653 MyCoreApp->getOptions()->GetTellVersion()) {
657 // Not sure why this is needed. Andy added this ages ago with comment saying
658 // needed for Mac apps. Need to check that it's indeed still required.
659 QDir dir(QApplication::applicationDirPath());
662 QApplication::addLibraryPath(dir.absolutePath());
663 // Load required application plugins.
664 QString plugin_string = "";
665 QStringList plugin_list = plugin_string.split(';',QString::SkipEmptyParts);
666 pqBrandPluginsLoader loader;
667 if (loader.loadPlugins(plugin_list) == false) {
668 printf("Failed to load required plugins for this application\n");
672 // Load optional plugins.
674 plugin_list = plugin_string.split(';',QString::SkipEmptyParts);
675 loader.loadPlugins(plugin_list, true); //quietly skip not-found plugins.
677 // End of Initializer code
679 vtkOutputWindow::SetInstance(PVGUI_OutputWindowAdapter::New());
681 new pqTabbedMultiViewWidget(); // it registers as "MULTIVIEW_WIDGET on creation
683 for (int i = 0; i < argc; i++)
692 \brief Shows (toShow = true) or hides ParaView view window
694 void PVGUI_Module::showView( bool toShow )
696 SalomeApp_Application* anApp = getApp();
697 PVGUI_ViewManager* viewMgr =
698 dynamic_cast<PVGUI_ViewManager*>( anApp->getViewManager( PVGUI_Viewer::Type(), false ) );
700 viewMgr = new PVGUI_ViewManager( anApp->activeStudy(), anApp->desktop() );
701 anApp->addViewManager( viewMgr );
702 connect( viewMgr, SIGNAL( lastViewClosed( SUIT_ViewManager* ) ),
703 anApp, SLOT( onCloseView( SUIT_ViewManager* ) ) );
706 PVGUI_ViewWindow* pvWnd = dynamic_cast<PVGUI_ViewWindow*>( viewMgr->getActiveView() );
708 pvWnd = dynamic_cast<PVGUI_ViewWindow*>( viewMgr->createViewWindow() );
711 pvWnd->setShown( toShow );
712 if ( toShow ) pvWnd->setFocus();
716 \brief Slot to show help for proxy.
718 void PVGUI_Module::showHelpForProxy( const QString& groupname, const QString& proxyname )
720 pqHelpReaction::showProxyHelp(groupname, proxyname);
725 \brief Slot to show the waiting state.
727 void PVGUI_Module::onPreAccept()
729 getApp()->desktop()->statusBar()->showMessage(tr("STB_PREACCEPT"));
730 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
734 \brief Slot to show the ready state.
736 void PVGUI_Module::onPostAccept()
738 getApp()->desktop()->statusBar()->showMessage(tr("STB_POSTACCEPT"), 2000);
739 QTimer::singleShot(0, this, SLOT(endWaitCursor()));
743 \brief Slot to switch off wait cursor.
745 void PVGUI_Module::endWaitCursor()
747 QApplication::restoreOverrideCursor();
751 \brief Returns the ParaView multi-view manager.
753 pqTabbedMultiViewWidget* PVGUI_Module::getMultiViewManager() const
755 return qobject_cast<pqTabbedMultiViewWidget*>(pqApplicationCore::instance()->manager("MULTIVIEW_WIDGET"));
759 static void ParavisMessageOutput(QtMsgType type, const char *msg)
764 vtkOutputWindow::GetInstance()->DisplayText(msg);
767 vtkOutputWindow::GetInstance()->DisplayErrorText(msg);
770 vtkOutputWindow::GetInstance()->DisplayErrorText(msg);
773 vtkOutputWindow::GetInstance()->DisplayErrorText(msg);
781 \brief Activate module.
782 \param study current study
783 \return \c true if activaion is done successfully or 0 to prevent
786 bool PVGUI_Module::activateModule( SUIT_Study* study )
788 myOldMsgHandler = qInstallMsgHandler(ParavisMessageOutput);
790 bool isDone = SalomeApp_Module::activateModule( study );
791 if ( !isDone ) return false;
794 if ( mySourcesMenuId != -1 ) menuMgr()->show(mySourcesMenuId);
795 if ( myFiltersMenuId != -1 ) menuMgr()->show(myFiltersMenuId);
796 if ( myFiltersMenuId != -1 ) menuMgr()->show(myMacrosMenuId);
797 if ( myFiltersMenuId != -1 ) menuMgr()->show(myToolbarsMenuId);
798 setMenuShown( true );
799 setToolShown( true );
801 restoreDockWidgetsState();
803 QMenu* aMenu = menuMgr()->findMenu( myRecentMenuId );
805 QList<QAction*> anActns = aMenu->actions();
806 for (int i = 0; i < anActns.size(); ++i) {
807 QAction* a = anActns.at(i);
813 if ( myRecentMenuId != -1 ) menuMgr()->show(myRecentMenuId);
815 ClientFindOrCreateParavisComponent(PARAVIS::GetCStudy(this));
822 \brief Deactivate module.
823 \param study current study
824 \return \c true if deactivaion is done successfully or 0 to prevent
825 deactivation on error
827 bool PVGUI_Module::deactivateModule( SUIT_Study* study )
829 QMenu* aMenu = menuMgr()->findMenu( myRecentMenuId );
831 QList<QAction*> anActns = aMenu->actions();
832 for (int i = 0; i < anActns.size(); ++i) {
833 QAction* a = anActns.at(i);
835 a->setVisible(false);
839 QList<QDockWidget*> aStreamingViews = application()->desktop()->findChildren<QDockWidget*>("pqStreamingControls");
840 foreach(QDockWidget* aView, aStreamingViews) {
841 if (!myDockWidgets.contains(aView))
842 myDockWidgets[aView] = aView->isVisible();
845 /*if (pqImplementation::helpWindow) {
846 pqImplementation::helpWindow->hide();
850 menuMgr()->hide(myRecentMenuId);
851 menuMgr()->hide(mySourcesMenuId);
852 menuMgr()->hide(myFiltersMenuId);
853 menuMgr()->hide(myMacrosMenuId);
854 menuMgr()->hide(myToolbarsMenuId);
855 setMenuShown( false );
856 setToolShown( false );
859 saveDockWidgetsState();
862 qInstallMsgHandler(myOldMsgHandler);
864 return SalomeApp_Module::deactivateModule( study );
869 \brief Called when application is closed.
871 Process finalize application functionality from ParaView in order to save server settings
872 and nullify application pointer if the application is being closed.
874 \param theApp application
876 void PVGUI_Module::onApplicationClosed( SUIT_Application* theApp )
878 pqApplicationCore::instance()->settings()->sync();
879 int aAppsNb = SUIT_Session::session()->applications().size();
881 deleteTemporaryFiles();
882 MyCoreApp->deleteLater();
884 CAM_Module::onApplicationClosed(theApp);
889 \brief Called when study is closed.
891 Removes data model from the \a study.
893 \param study study being closed
895 void PVGUI_Module::studyClosed(SUIT_Study* study)
897 clearParaviewState();
899 SalomeApp_Module::studyClosed(study);
903 \brief Called when study is opened.
905 void PVGUI_Module::onModelOpened()
907 _PTR(Study) studyDS = PARAVIS::GetCStudy(this);
912 _PTR(SComponent) paravisComp =
913 studyDS->FindComponent(PARAVIS::GetParavisGen(this)->ComponentDataType());
918 _PTR(ChildIterator) anIter(studyDS->NewChildIterator(paravisComp));
919 for (; anIter->More(); anIter->Next()) {
920 _PTR(SObject) aSObj = anIter->Value();
921 _PTR(GenericAttribute) anAttr;
922 if (!aSObj->FindAttribute(anAttr, "AttributeLocalID")) {
925 _PTR(AttributeLocalID) anID(anAttr);
926 if (anID->Value() == PVSTATEID) {
933 \brief Returns IOR of current engine
935 QString PVGUI_Module::engineIOR() const
937 CORBA::String_var anIOR = PARAVIS::GetParavisGen(this)->GetIOR();
938 return QString(anIOR.in());
943 \brief Open file of format supported by ParaView
945 void PVGUI_Module::openFile(const char* theName)
949 pqLoadDataReaction::loadData(aFiles);
952 void PVGUI_Module::executeScript(const char *script)
955 pqPythonManager* manager = qobject_cast<pqPythonManager*>(
956 pqApplicationCore::instance()->manager("PYTHON_MANAGER"));
958 pqPythonDialog* pyDiag = manager->pythonShellDialog();
960 pyDiag->runString(script);
967 \brief Returns trace string
969 static const QString MYReplaceStr("paraview.simple");
970 static const QString MYReplaceImportStr("except: from pvsimple import *");
971 QString PVGUI_Module::getTraceString()
975 pqPythonManager* manager = qobject_cast<pqPythonManager*>(
976 pqApplicationCore::instance()->manager("PYTHON_MANAGER"));
978 pqPythonDialog* pyDiag = manager->pythonShellDialog();
980 pyDiag->runString("from paraview import smtrace\n"
981 "__smtraceString = smtrace.get_trace_string()\n");
982 pyDiag->shell()->makeCurrent();
983 PyObject* main_module = PyImport_AddModule((char*)"__main__");
984 PyObject* global_dict = PyModule_GetDict(main_module);
985 PyObject* string_object = PyDict_GetItemString(global_dict, "__smtraceString");
986 char* string_ptr = string_object ? PyString_AsString(string_object) : 0;
988 traceString = string_ptr;
990 pyDiag->shell()->releaseControl();
993 if ((!traceString.isNull()) && traceString.length() != 0) {
994 int aPos = traceString.indexOf(MYReplaceStr);
996 traceString = traceString.replace(aPos, MYReplaceStr.length(), "pvsimple");
997 aPos = traceString.indexOf(MYReplaceStr, aPos);
999 int aImportPos = traceString.indexOf(MYReplaceImportStr);
1000 if(aImportPos != -1)
1002 traceString = traceString.replace(aImportPos, MYReplaceImportStr.length(), "except:\n import pvsimple\n from pvsimple import *");
1010 \brief Saves trace string to disk file
1012 void PVGUI_Module::saveTrace(const char* theName)
1014 QFile file(theName);
1015 if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
1016 MESSAGE( "Could not open file:" << theName );
1019 QTextStream out(&file);
1020 out << getTraceString();
1025 \brief Saves ParaView state to a disk file
1027 void PVGUI_Module::saveParaviewState(const char* theFileName)
1029 pqApplicationCore::instance()->saveState(theFileName);
1033 \brief Delete all objects for Paraview Pipeline Browser
1035 void PVGUI_Module::clearParaviewState()
1037 QAction* deleteAllAction = action(DeleteAllId);
1038 if (deleteAllAction) {
1039 deleteAllAction->activate(QAction::Trigger);
1044 \brief Restores ParaView state from a disk file
1046 If toClear == true, the current ojects will be deleted
1048 void PVGUI_Module::loadParaviewState(const char* theFileName)
1050 pqApplicationCore::instance()->loadState(theFileName, getActiveServer());
1054 \brief Imports MED data from VISU module by data entry
1056 void PVGUI_Module::onImportFromVisu(QString theEntry)
1059 SUIT_OverrideCursor aWaitCursor;
1062 SalomeApp_Study* activeStudy = dynamic_cast<SalomeApp_Study*>(application()->activeStudy());
1063 if(!activeStudy) return;
1065 // get SALOMEDS client study
1066 _PTR(Study) aStudy = activeStudy->studyDS();
1069 // find VISU component in a study
1070 _PTR(SComponent) aVisuComp = aStudy->FindComponent( "VISU" );
1071 if(!aVisuComp) return;
1073 // get SObject client by entry
1074 _PTR(SObject) aSObj = aStudy->FindObjectID(qPrintable(theEntry));
1077 // get CORBA SObject
1078 SALOMEDS_SObject* aSObject = _CAST(SObject, aSObj);
1079 if ( !aSObject ) return;
1082 SALOME_NamingService* aNamingService = SalomeApp_Application::namingService();
1083 SALOME_LifeCycleCORBA aLCC(aNamingService);
1085 Engines::EngineComponent_var aComponent = aLCC.FindOrLoad_Component("FactoryServer","VISU");
1086 VISU::VISU_Gen_var aVISU = VISU::VISU_Gen::_narrow(aComponent);
1087 if(CORBA::is_nil(aVISU)) return;
1089 _PTR(StudyBuilder) aStudyBuilder = aStudy->NewBuilder();
1090 aStudyBuilder->LoadWith( aVisuComp, SalomeApp_Application::orb()->object_to_string(aVISU) );
1092 // get VISU result object
1093 CORBA::Object_var aResultObject = aSObject->GetObject();
1094 if (CORBA::is_nil(aResultObject)) return;
1095 VISU::Result_var aResult = VISU::Result::_narrow( aResultObject );
1096 if (CORBA::is_nil(aResult)) return;
1098 // export VISU result to the MED file
1099 std::string aTmpDir = SALOMEDS_Tool::GetTmpDir();
1100 std::string aFileName = aSObject->GetName();
1101 std::string aFilePath = aTmpDir + aFileName;
1103 if (aResult->ExportMED(aFilePath.c_str())) {
1104 openFile(aFilePath.c_str());
1105 myTemporaryFiles.append(QString(aFilePath.c_str()));
1108 MESSAGE("Visu module is not found.");
1113 \brief Deletes temporary files created during import operation from VISU
1115 void PVGUI_Module::deleteTemporaryFiles()
1117 foreach(QString aFile, myTemporaryFiles) {
1118 if (QFile::exists(aFile)) {
1119 QFile::remove(aFile);
1126 \brief Returns current active ParaView server
1128 pqServer* PVGUI_Module::getActiveServer()
1130 return pqApplicationCore::instance()->getActiveServer();
1135 \brief Creates PARAVIS preference pane
1137 void PVGUI_Module::createPreferences()
1139 // Paraview settings tab
1140 int aParaViewSettingsTab = addPreference( tr( "TIT_PVIEWSETTINGS" ) );
1141 int aPanel = addPreference(QString(), aParaViewSettingsTab, LightApp_Preferences::UserDefined, "PARAVIS", "");
1142 setPreferenceProperty(aPanel, "content", (qint64)(new PVGUI_ParaViewSettingsPane()));
1144 // Paravis settings tab
1145 int aParaVisSettingsTab = addPreference( tr( "TIT_PVISSETTINGS" ) );
1146 addPreference( tr( "PREF_STOP_TRACE" ), aParaVisSettingsTab, LightApp_Preferences::Bool, "PARAVIS", "stop_trace");
1148 int aSaveType = addPreference(tr( "PREF_SAVE_TYPE_LBL" ), aParaVisSettingsTab,
1149 LightApp_Preferences::Selector,
1150 "PARAVIS", "savestate_type");
1151 QList<QVariant> aIndices;
1152 QStringList aStrings;
1154 aStrings<<tr("PREF_SAVE_TYPE_0");
1155 aStrings<<tr("PREF_SAVE_TYPE_1");
1156 aStrings<<tr("PREF_SAVE_TYPE_2");
1157 setPreferenceProperty(aSaveType, "strings", aStrings);
1158 setPreferenceProperty(aSaveType, "indexes", aIndices);
1160 //rnv: imp 21712: [CEA 581] Preference to display legend by default
1161 int aDispColoreLegend = addPreference( tr( "PREF_SHOW_COLOR_LEGEND" ), aParaVisSettingsTab,
1162 LightApp_Preferences::Bool, "PARAVIS", "show_color_legend");
1166 \brief Creates ParaViS context menu popup
1168 void PVGUI_Module::contextMenuPopup(const QString& theClient, QMenu* theMenu, QString& theTitle)
1170 SalomeApp_Module::contextMenuPopup(theClient, theMenu, theTitle);
1172 // Check if we are in Object Browser
1173 SUIT_DataBrowser* ob = getApp()->objectBrowser();
1174 bool isOBClient = (ob && theClient == ob->popupClientType());
1179 // Get list of selected objects
1180 LightApp_SelectionMgr* aSelectionMgr = getApp()->selectionMgr();
1181 SALOME_ListIO aListIO;
1182 aSelectionMgr->selectedObjects(aListIO);
1183 if (aListIO.Extent() == 1 && aListIO.First()->hasEntry()) {
1184 QString entry = QString(aListIO.First()->getEntry());
1187 SalomeApp_Study* activeStudy =
1188 dynamic_cast<SalomeApp_Study*>(getApp()->activeStudy());
1193 // Get SALOMEDS client study
1194 _PTR(Study) studyDS = activeStudy->studyDS();
1199 QString paravisDataType(PARAVIS::GetParavisGen(this)->ComponentDataType());
1200 if(activeStudy && activeStudy->isComponent(entry) &&
1201 activeStudy->componentDataType(entry) == paravisDataType) {
1202 // ParaViS module object
1203 theMenu->addSeparator();
1204 theMenu->addAction(action(SaveStatePopupId));
1207 // Try to get state object
1208 _PTR(SObject) stateSObj =
1209 studyDS->FindObjectID(entry.toLatin1().constData());
1215 _PTR(GenericAttribute) anAttr;
1216 if (!stateSObj->FindAttribute(anAttr, "AttributeLocalID")) {
1220 _PTR(AttributeLocalID) anID(anAttr);
1222 if (anID->Value() == PVSTATEID) {
1223 // Paraview state object
1224 theMenu->addSeparator();
1225 theMenu->addAction(action(AddStatePopupId));
1226 theMenu->addAction(action(CleanAndAddStatePopupId));
1227 theMenu->addSeparator();
1228 theMenu->addAction(action(ParaVisRenameId));
1229 theMenu->addAction(action(ParaVisDeleteId));
1235 void PVGUI_Module::onShowTrace()
1237 if (!myTraceWindow) {
1238 myTraceWindow = new pqPythonScriptEditor(getApp()->desktop());
1240 myTraceWindow->setText(getTraceString());
1241 myTraceWindow->show();
1242 myTraceWindow->raise();
1243 myTraceWindow->activateWindow();
1247 \brief Show ParaView view.
1249 void PVGUI_Module::onNewParaViewWindow()
1255 \brief Save state under the module root object.
1257 void PVGUI_Module::onSaveMultiState()
1259 // Create state study object
1261 // Get SALOMEDS client study
1262 _PTR(Study) studyDS = PARAVIS::GetCStudy(this);
1267 _PTR(SComponent) paravisComp =
1268 studyDS->FindComponent(PARAVIS::GetParavisGen(this)->ComponentDataType());
1273 // Unlock the study if it is locked
1274 bool isLocked = studyDS->GetProperties()->IsLocked();
1276 studyDS->GetProperties()->SetLocked(false);
1279 QString stateName = tr("SAVED_PARAVIEW_STATE_NAME") +
1280 QString::number(myStateCounter + 1);
1282 _PTR(StudyBuilder) studyBuilder = studyDS->NewBuilder();
1283 _PTR(SObject) newSObj = studyBuilder->NewObject(paravisComp);
1286 _PTR(GenericAttribute) anAttr;
1287 anAttr = studyBuilder->FindOrCreateAttribute(newSObj, "AttributeName");
1288 _PTR(AttributeName) nameAttr(anAttr);
1290 nameAttr->SetValue(stateName.toLatin1().constData());
1293 anAttr = studyBuilder->FindOrCreateAttribute(newSObj, "AttributeLocalID");
1294 _PTR(AttributeLocalID) localIdAttr(anAttr);
1296 localIdAttr->SetValue(PVSTATEID);
1299 QString stateEntry = QString::fromStdString(newSObj->GetID());
1301 // File name for state saving
1302 QString tmpDir = QString::fromStdString(SALOMEDS_Tool::GetTmpDir());
1303 QString fileName = QString("%1_paravisstate:%2").arg(tmpDir,
1306 anAttr = studyBuilder->FindOrCreateAttribute(newSObj, "AttributeString");
1307 _PTR(AttributeString) stringAttr(anAttr);
1309 stringAttr->SetValue(fileName.toLatin1().constData());
1311 // Lock the study back if necessary
1313 studyDS->GetProperties()->SetLocked(true);
1317 saveParaviewState(fileName.toLatin1().constData());
1318 myTemporaryFiles.append(fileName);
1320 // Increment the counter
1327 \brief Restore the selected state by merging with the current one.
1329 void PVGUI_Module::onAddState()
1331 loadSelectedState(false);
1335 \brief Clean the current state and restore the selected one.
1337 void PVGUI_Module::onCleanAddState()
1339 loadSelectedState(true);
1343 \brief Rename the selected object.
1345 void PVGUI_Module::onRename()
1347 LightApp_SelectionMgr* aSelectionMgr = getApp()->selectionMgr();
1348 SALOME_ListIO aListIO;
1349 aSelectionMgr->selectedObjects(aListIO);
1351 if (aListIO.Extent() == 1 && aListIO.First()->hasEntry()) {
1352 std::string entry = aListIO.First()->getEntry();
1354 // Get SALOMEDS client study
1355 _PTR(Study) studyDS = PARAVIS::GetCStudy(this);
1360 // Unlock the study if it is locked
1361 bool isLocked = studyDS->GetProperties()->IsLocked();
1363 studyDS->GetProperties()->SetLocked(false);
1366 // Rename the selected state object
1367 _PTR(SObject) stateSObj = studyDS->FindObjectID(entry);
1372 _PTR(GenericAttribute) anAttr;
1373 if (stateSObj->FindAttribute(anAttr, "AttributeName")) {
1374 _PTR(AttributeName) nameAttr (anAttr);
1376 LightApp_NameDlg::getName(getApp()->desktop(), nameAttr->Value().c_str());
1377 if (!newName.isEmpty()) {
1378 nameAttr->SetValue(newName.toLatin1().constData());
1379 aListIO.First()->setName(newName.toLatin1().constData());
1383 // Lock the study back if necessary
1385 studyDS->GetProperties()->SetLocked(true);
1388 // Update object browser
1395 \brief Delete the selected objects.
1397 void PVGUI_Module::onDelete()
1399 LightApp_SelectionMgr* aSelectionMgr = getApp()->selectionMgr();
1400 SALOME_ListIO aListIO;
1401 aSelectionMgr->selectedObjects(aListIO);
1403 if (aListIO.Extent() == 1 && aListIO.First()->hasEntry()) {
1404 std::string entry = aListIO.First()->getEntry();
1406 // Get SALOMEDS client study
1407 _PTR(Study) studyDS = PARAVIS::GetCStudy(this);
1412 // Unlock the study if it is locked
1413 bool isLocked = studyDS->GetProperties()->IsLocked();
1415 studyDS->GetProperties()->SetLocked(false);
1418 // Remove the selected state from the study
1419 _PTR(StudyBuilder) studyBuilder = studyDS->NewBuilder();
1420 _PTR(SObject) stateSObj = studyDS->FindObjectID(entry);
1421 studyBuilder->RemoveObject(stateSObj);
1423 // Lock the study back if necessary
1425 studyDS->GetProperties()->SetLocked(true);
1428 // Update object browser
1434 \brief Discover help project files from the resources.
1435 \return name of the help file.
1437 QString PVGUI_Module::getHelpFileName() {
1438 QString aPVHome(getenv("PVHOME"));
1439 if (aPVHome.isNull()) {
1440 qWarning("Wariable PVHOME is not defined");
1443 QChar aSep = QDir::separator();
1444 //PARAVIEW_VERSION from the vtkPVConfig.h file
1445 QString aFileName = aPVHome + aSep + "share" + aSep + "doc" + aSep + "paraview-"+ PARAVIEW_VERSION + aSep + "paraview.qch";
1451 \brief Load selected paraview state
1453 If toClear == true, the current state will be cleared
1455 void PVGUI_Module::loadSelectedState(bool toClear)
1459 LightApp_SelectionMgr* aSelectionMgr = getApp()->selectionMgr();
1460 SALOME_ListIO aListIO;
1461 aSelectionMgr->selectedObjects(aListIO);
1463 if (aListIO.Extent() == 1 && aListIO.First()->hasEntry()) {
1464 std::string entry = aListIO.First()->getEntry();
1466 // Get SALOMEDS client study
1467 _PTR(Study) studyDS = PARAVIS::GetCStudy(this);
1473 _PTR(SObject) stateSObj = studyDS->FindObjectID(entry);
1474 _PTR(GenericAttribute) anAttr;
1475 if (!stateSObj->FindAttribute(anAttr, "AttributeLocalID")) {
1478 _PTR(AttributeLocalID) anID(anAttr);
1479 if (!anID->Value() == PVSTATEID) {
1483 // Get state file name
1484 if (stateSObj->FindAttribute(anAttr, "AttributeString")) {
1485 _PTR(AttributeString) aStringAttr(anAttr);
1486 QString stringValue(aStringAttr->Value().c_str());
1488 if (QFile::exists(stringValue)) {
1489 fileName = stringValue;
1494 if (!fileName.isEmpty()) {
1496 clearParaviewState();
1499 loadParaviewState(fileName.toLatin1().constData());
1502 SUIT_MessageBox::critical(getApp()->desktop(),
1504 tr("ERR_STATE_CANNOT_BE_RESTORED"));
1508 void PVGUI_Module::onRepresentationChanged(pqRepresentation*) {
1511 //rnv: to fix the issue "21712: [CEA 581] Preference to display legend by default"
1512 // find the pqDisplayColorWidget instances and connect the variableChanged SIGNAL on the
1513 // onVariableChanged slot of this class. This connection needs to change visibility
1514 // of the "Colored Legend" after change the "Color By" array.
1515 QList<pqDisplayColorWidget*> aWidget = getApp()->desktop()->findChildren<pqDisplayColorWidget*>();
1517 for (int i = 0; i < aWidget.size() ; i++ ) {
1519 connect( aWidget[i], SIGNAL ( variableChanged ( pqVariableType, const QString ) ),
1520 this, SLOT(onVariableChanged( pqVariableType, const QString) ), Qt::UniqueConnection );
1527 \fn CAM_Module* createModule();
1528 \brief Export module instance (factory function).
1529 \return new created instance of the module
1533 #define PVGUI_EXPORT __declspec(dllexport)
1535 #define PVGUI_EXPORT
1541 PVGUI_EXPORT CAM_Module* createModule() {
1546 return new PVGUI_Module();
1549 PVGUI_EXPORT char* getModuleVersion() {
1550 return (char*)PARAVIS_VERSION_STR;