1 // PARAVIS : ParaView wrapper SALOME module
3 // Copyright (C) 2010-2021 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 #define PARAVIS_MODULE_NAME "PARAVIS"
25 #include <Standard_math.hxx> // E.A. must be included before Python.h to fix compilation on windows
27 #undef HAVE_FINITE // VSR: avoid compilation warning on Linux : "HAVE_FINITE" redefined
29 #include <vtkPython.h> // Python first
31 #include "PVGUI_Module.h"
33 #include "PVViewer_ViewManager.h"
34 #include "PVViewer_Core.h"
35 #include "PVViewer_ViewWindow.h"
36 #include "PVViewer_ViewModel.h"
37 #include "PVGUI_ParaViewSettingsPane.h"
38 #include "PVViewer_GUIElements.h"
39 #include "PVServer_ServiceWrapper.h"
40 #include "PVGUI_DataModel.h"
43 #include <utilities.h>
44 #include <SUIT_DataBrowser.h>
45 #include <SUIT_Desktop.h>
46 #include <SUIT_MessageBox.h>
47 #include <SUIT_ResourceMgr.h>
48 #include <SUIT_Session.h>
49 #include <SUIT_OverrideCursor.h>
50 #include <SUIT_ExceptionHandler.h>
52 #include <LightApp_SelectionMgr.h>
53 #include <LightApp_NameDlg.h>
54 #include <LightApp_Application.h>
55 #include <LightApp_Study.h>
56 #include <SALOME_ListIO.hxx>
58 #include <QtxActionMenuMgr.h>
59 #include <QtxActionToolMgr.h>
61 #include <PARAVIS_version.h>
67 #include <QApplication>
73 #include <QInputDialog>
77 #include <QStringList>
80 #include <QTextStream>
82 #include <QDockWidget>
83 #include <QHelpEngine>
86 #include <vtkPVConfig.h> // for symbol PARAVIEW_VERSION
87 #include <vtkProcessModule.h>
88 #include <vtkPVSession.h>
89 #include <vtkPVProgressHandler.h>
90 #include <vtkEventQtSlotConnect.h>
92 #include <vtkSMProxy.h>
93 #include <vtkSmartPointer.h>
94 #include <vtkSMSession.h>
95 #include <vtkSMTrace.h>
96 #include <vtkSMSessionProxyManager.h>
97 #include <vtkSMParaViewPipelineController.h>
98 #include <vtkSmartPyObject.h>
100 #include <pqApplicationCore.h>
101 #include <pqPVApplicationCore.h>
102 #include <pqObjectBuilder.h>
103 #include <pqOptions.h>
104 #include <pqSettings.h>
105 #include <pqServer.h>
106 #include <pqUndoStack.h>
107 #include <pqTabbedMultiViewWidget.h>
108 #include <pqActiveObjects.h>
109 #include <pqHelpReaction.h>
110 #include <pqPluginManager.h>
111 //#include <pqPythonDialog.h>
112 #include <pqPythonManager.h>
113 #include <pqLoadDataReaction.h>
114 #include <pqPythonScriptEditor.h>
115 #include <pqDataRepresentation.h>
116 #include <pqDisplayColorWidget.h>
117 #include <pqColorToolbar.h>
118 #include <pqScalarBarVisibilityReaction.h>
119 #include <pqServerResource.h>
120 #include <pqServerConnectReaction.h>
121 #include <pqPluginManager.h>
122 #include <pqVCRToolbar.h>
123 #include <pqAnimationScene.h>
124 #include <pqServerManagerModel.h>
125 #include <pqAnimationTimeToolbar.h>
126 #include <pqPipelineBrowserWidget.h>
127 #include <pqCoreUtilities.h>
128 #include <pqLoadStateReaction.h>
130 #if PY_VERSION_HEX < 0x03050000
132 Py_EncodeLocale(const wchar_t *arg, size_t *size)
134 return _Py_wchar2char(arg, size);
137 Py_DecodeLocale(const char *arg, size_t *size)
139 return _Py_char2wchar(arg, size);
143 //----------------------------------------------------------------------------
144 PVGUI_Module* ParavisModule = 0;
148 This is the doxygen documentation of the ParaVis module.
149 If you are looking for general information about the structure of the module, you should
150 take a look at the <a href="../index.html">Sphinx documentation</a> first.
152 The integration of ParaView into SALOME is split in two parts:
153 \li the PVViewer in the GUI module (folder *src/PVViewer*)
154 \li the ParaVis module itself (the pages you are currently browsing)
159 \brief Implementation
160 SALOME module wrapping ParaView GUI.
164 \brief Clean up function
166 Used to stop ParaView progress events when
167 exception is caught by global exception handler.
169 void paravisCleanUp()
171 if ( pqApplicationCore::instance() ) {
172 pqServer* s = pqApplicationCore::instance()->getActiveServer();
173 if ( s ) s->session()->GetProgressHandler()->CleanupPendingProgress();
178 \brief Constructor. Sets the default name for the module.
180 PVGUI_Module::PVGUI_Module()
181 : LightApp_Module( PARAVIS_MODULE_NAME ),
182 mySourcesMenuId( -1 ),
183 myFiltersMenuId( -1 ),
186 myCatalystMenuId(-1),
193 Q_INIT_RESOURCE( PVGUI );
195 ParavisModule = this;
201 PVGUI_Module::~PVGUI_Module()
208 \brief Retrieve the PVSERVER CORBA engine.
209 This uses the Python wrapper provided
210 by the PVViewer code in GUI (class PVViewer_EngineWrapper).
213 PVServer_ServiceWrapper* PVGUI_Module::GetEngine()
215 return PVServer_ServiceWrapper::GetInstance();
219 \brief Create data model.
220 \return module specific data model
222 CAM_DataModel* PVGUI_Module::createDataModel()
224 return new PVGUI_DataModel( this );
228 \brief Get the ParaView application singleton.
230 pqPVApplicationCore* PVGUI_Module::GetPVApplication()
232 return PVViewer_Core::GetPVApplication();
236 \brief Initialize module. Creates menus, prepares context menu, etc.
237 \param app SALOME GUI application instance
239 void PVGUI_Module::initialize( CAM_Application* app )
241 LightApp_Module::initialize( app );
243 // Uncomment to debug ParaView initialization
244 // "aa" used instead of "i" as GDB doesn't like "i" variables :)
252 LightApp_Application* anApp = getApp();
253 SUIT_Desktop* aDesktop = anApp->desktop();
255 // Remember current state of desktop toolbars
256 QList<QToolBar*> foreignToolbars = aDesktop->findChildren<QToolBar*>();
258 // Initialize ParaView client and associated behaviors
259 // and connect to externally launched pvserver
260 PVViewer_Core::ParaviewInitApp(aDesktop);
262 // Clear old copies of embedded macros files
263 //QString aDestPath = QString( "%1/.config/%2/Macros" ).arg( QDir::homePath() ).arg( QApplication::applicationName() );
264 QString aDestPath = pqCoreUtilities::getParaViewUserDirectory() + "/Macros";
268 QDir aDestDir(aDestPath);
269 QStringList aDestFiles = aDestDir.entryList(aFilter, QDir::Files);
270 foreach(QString aMacrosPath, getEmbeddedMacrosList()) {
271 QString aMacrosName = QFileInfo(aMacrosPath).fileName();
272 if (aDestFiles.contains(aMacrosName)) {
273 aDestDir.remove(aMacrosName);
277 myGuiElements = PVViewer_GUIElements::GetInstance(aDesktop);
280 // [ABN]: careful with the order of the GUI element creation, the loading of the configuration
281 // and the connection to the server. This order is very sensitive if one wants to make
282 // sure all menus, etc ... are correctly populated.
283 // Reference points are: ParaViewMainWindow.cxx and branded_paraview_initializer.cxx.in
290 PVViewer_Core::ParaviewInitBehaviors(true, aDesktop);
292 QList<QDockWidget*> activeDocks = aDesktop->findChildren<QDockWidget*>();
293 QList<QMenu*> activeMenus = aDesktop->findChildren<QMenu*>();
295 // Setup quick-launch shortcuts.
296 QShortcut *ctrlSpace = new QShortcut(Qt::CTRL + Qt::Key_Space, aDesktop);
297 QObject::connect(ctrlSpace, SIGNAL(activated()),
298 pqApplicationCore::instance(), SLOT(quickLaunch()));
300 // Find Plugin Dock Widgets
301 QList<QDockWidget*> currentDocks = aDesktop->findChildren<QDockWidget*>();
302 QList<QDockWidget*>::iterator i;
303 for (i = currentDocks.begin(); i != currentDocks.end(); ++i) {
304 if(!activeDocks.contains(*i)) {
305 myDockWidgets[*i] = false; // hidden by default
311 // [ABN] TODO: fix this - triggers a SEGFAULT at deactivation() time.
312 // QList<QMenu*> currentMenus = aDesktop->findChildren<QMenu*>();
313 // QList<QMenu*>::iterator im;
314 // for (im = currentMenus.begin(); im != currentMenus.end(); ++im) {
315 // if(!activeMenus.contains(*im)) {
316 // QString s = (*im)->title();
317 // std::cout << " MENU "<< s.toStdString() << std::endl;
318 // myMenus.append(*im);
322 // Connect after toolbar creation, etc ... as some activations of the toolbars is triggered
323 // by the ServerConnection event:
324 const QString configPath(PVViewer_ViewManager::GetPVConfigPath());
325 PVViewer_Core::ParaviewLoadConfigurations(configPath, true);
326 PVViewer_ViewManager::ConnectToExternalPVServer(aDesktop);
329 // Find created toolbars
330 QCoreApplication::processEvents();
332 // process PVViewer toolbars (might be added by PVViewer created BEFORE activating ParaVis)
333 QList<QToolBar*> pvToolbars = myGuiElements->getToolbars();
334 foreach(QToolBar* aBar, pvToolbars) {
335 if (!myToolbars.contains(aBar)) {
336 myToolbars[aBar] = true;
337 myToolbarBreaks[aBar] = false;
338 aBar->setVisible(false);
339 aBar->toggleViewAction()->setVisible(false);
343 // process other toolbars (possibly added by Paraview)
344 QList<QToolBar*> allToolbars = aDesktop->findChildren<QToolBar*>();
345 foreach(QToolBar* aBar, allToolbars) {
346 if (!foreignToolbars.contains(aBar) && !myToolbars.contains(aBar)) {
347 myToolbars[aBar] = true;
348 myToolbarBreaks[aBar] = false;
349 aBar->setVisible(false);
350 aBar->toggleViewAction()->setVisible(false);
356 SUIT_ResourceMgr* aResourceMgr = SUIT_Session::session()->resourceMgr();
357 bool isStop = aResourceMgr->booleanValue( PARAVIS_MODULE_NAME, "stop_trace", false );
360 // Start a timer to schedule asap:
362 myInitTimer = new QTimer(aDesktop);
363 QObject::connect(myInitTimer, SIGNAL(timeout()), this, SLOT(onInitTimer()) );
364 myInitTimer->setSingleShot(true);
365 myInitTimer->start(0);
368 this->VTKConnect = vtkEventQtSlotConnect::New();
370 vtkProcessModule* pm = vtkProcessModule::GetProcessModule();
372 vtkPVSession* pvs = dynamic_cast<vtkPVSession*>(pm->GetSession());
374 vtkPVProgressHandler* ph = pvs->GetProgressHandler();
376 this->VTKConnect->Connect(ph, vtkCommand::StartEvent,
377 this, SLOT(onStartProgress()));
378 this->VTKConnect->Connect(ph, vtkCommand::EndEvent,
379 this, SLOT(onEndProgress()));
383 connect( application(), SIGNAL( appClosed() ), this, SLOT( onStopTrace() ) );
387 * \brief Slot called when the progress bar starts.
389 void PVGUI_Module::onStartProgress()
391 // VSR 19/03/2015, issue 0023025
392 // next line is commented: it is bad idea to show wait cursor on ANY vtk event
393 // moreover, it does not work when running pvserver with --multi-client mode
394 //QApplication::setOverrideCursor(Qt::WaitCursor);
398 * \brief Slot called when the progress bar is done.
400 void PVGUI_Module::onEndProgress()
402 // VSR 19/03/2015, issue 0023025
403 // next line is commented: it is bad idea to show wait cursor on ANY vtk event
404 // moreover, it does not work when running pvserver with --multi-client mode
405 //QApplication::restoreOverrideCursor();
408 void PVGUI_Module::onDataRepresentationUpdated() {
409 LightApp_Study* activeStudy = dynamic_cast<LightApp_Study*>(application()->activeStudy());
410 if(!activeStudy) return;
412 activeStudy->Modified();
416 \brief Initialisation timer event - Starts up the Python trace
418 void PVGUI_Module::onInitTimer()
424 \brief Get list of embedded macros files
426 QStringList PVGUI_Module::getEmbeddedMacrosList()
428 QString aRootDir = getenv("PARAVIS_ROOT_DIR");
430 QString aSourcePath = aRootDir + "/bin/salome/Macro";
435 QDir aSourceDir(aSourcePath);
436 QStringList aSourceFiles = aSourceDir.entryList(aFilter, QDir::Files);
437 QStringList aFullPathSourceFiles;
438 foreach (QString aMacrosName, aSourceFiles) {
439 aFullPathSourceFiles << aSourceDir.absoluteFilePath(aMacrosName);
441 return aFullPathSourceFiles;
445 \brief Update the list of embedded macros
447 void PVGUI_Module::updateMacros()
449 pqPythonManager* aPythonManager = pqPVApplicationCore::instance()->pythonManager();
450 if(!aPythonManager) {
454 foreach (QString aStr, getEmbeddedMacrosList()) {
455 aPythonManager->addMacro(aStr);
461 \brief Get list of compliant dockable GUI elements
462 \param m map to be filled in ("type":"default_position")
464 void PVGUI_Module::windows( QMap<int, int>& m ) const
466 m.insert( LightApp_Application::WT_ObjectBrowser, Qt::LeftDockWidgetArea );
467 #ifndef DISABLE_PYCONSOLE
468 m.insert( LightApp_Application::WT_PyConsole, Qt::BottomDockWidgetArea );
470 // ParaView diagnostic output redirected here
471 m.insert( LightApp_Application::WT_LogWindow, Qt::BottomDockWidgetArea );
475 \brief Shows (toShow = true) or hides ParaView view window
477 void PVGUI_Module::showView( bool toShow )
479 // VSR: TODO: all below is not needed, if we use standard approach
480 // that consists in implementing viewManagers() function properly
481 // This should be done after we decide what to do with Log window.
482 LightApp_Application* anApp = getApp();
483 PVViewer_ViewManager* viewMgr =
484 dynamic_cast<PVViewer_ViewManager*>( anApp->getViewManager( PVViewer_Viewer::Type(), false ) );
486 viewMgr = new PVViewer_ViewManager( anApp->activeStudy(), anApp->desktop() );
487 anApp->addViewManager( viewMgr );
488 connect( viewMgr, SIGNAL( lastViewClosed( SUIT_ViewManager* ) ),
489 anApp, SLOT( onCloseView( SUIT_ViewManager* ) ) );
492 PVViewer_ViewWindow* pvWnd = dynamic_cast<PVViewer_ViewWindow*>( viewMgr->getActiveView() );
494 pvWnd = dynamic_cast<PVViewer_ViewWindow*>( viewMgr->createViewWindow() );
495 // this also connects to the pvserver and instantiates relevant PV behaviors
498 pvWnd->setVisible( toShow );
499 if ( toShow ) pvWnd->setFocus();
503 \brief Slot to show help for proxy.
505 void PVGUI_Module::showHelpForProxy( const QString& groupname, const QString& proxyname )
507 pqHelpReaction::showProxyHelp(groupname, proxyname);
511 \brief Slot to show the waiting state.
513 void PVGUI_Module::onPreAccept()
515 getApp()->desktop()->statusBar()->showMessage(tr("STB_PREACCEPT"));
516 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
520 \brief Slot to show the ready state.
522 void PVGUI_Module::onPostAccept()
524 getApp()->desktop()->statusBar()->showMessage(tr("STB_POSTACCEPT"), 2000);
525 QTimer::singleShot(0, this, SLOT(endWaitCursor()));
529 \brief Slot to switch off wait cursor.
531 void PVGUI_Module::endWaitCursor()
533 QApplication::restoreOverrideCursor();
537 \brief Activate module.
538 \param study current study
539 \return \c true if activaion is done successfully or 0 to prevent
542 bool PVGUI_Module::activateModule( SUIT_Study* study )
544 SUIT_ExceptionHandler::addCleanUpRoutine( paravisCleanUp );
546 storeCommonWindowsState();
548 bool isDone = LightApp_Module::activateModule( study );
549 if ( !isDone ) return false;
552 if ( mySourcesMenuId != -1 ) menuMgr()->show(mySourcesMenuId);
553 if ( myFiltersMenuId != -1 ) menuMgr()->show(myFiltersMenuId);
554 if ( myMacrosMenuId != -1 ) menuMgr()->show(myMacrosMenuId);
555 if ( myCatalystMenuId != -1 ) menuMgr()->show(myCatalystMenuId);
557 // Update the various menus with the content pre-loaded in myGuiElements
558 // QMenu* srcMenu = menuMgr()->findMenu( mySourcesMenuId );
559 // myGuiElements->updateSourcesMenu(srcMenu);
560 // QMenu* filtMenu = menuMgr()->findMenu( myFiltersMenuId );
561 // myGuiElements->updateFiltersMenu(filtMenu);
562 // QMenu* macMenu = menuMgr()->findMenu( myMacrosMenuId );
563 // myGuiElements->updateMacrosMenu(macMenu);
565 setMenuShown( true );
566 setToolShown( true );
568 restoreDockWidgetsState();
570 QMenu* aMenu = menuMgr()->findMenu( myRecentMenuId );
572 QList<QAction*> anActns = aMenu->actions();
573 for (int i = 0; i < anActns.size(); ++i) {
574 QAction* a = anActns.at(i);
580 QList<QMenu*>::iterator it;
581 for (it = myMenus.begin(); it != myMenus.end(); ++it) {
582 QAction* a = (*it)->menuAction();
587 if ( myRecentMenuId != -1 ) menuMgr()->show(myRecentMenuId);
589 // VSR 18/10/2018 - 0023170: Workaround to re-select current index after module activation
590 QItemSelectionModel* selection_model = myGuiElements->getPipelineBrowserWidget()->getSelectionModel();
591 QModelIndex idx = selection_model->currentIndex();
592 selection_model->clearCurrentIndex();
593 selection_model->setCurrentIndex(idx, QItemSelectionModel::ClearAndSelect);
600 \brief Deactivate module.
601 \param study current study
602 \return \c true if deactivaion is done successfully or 0 to prevent
603 deactivation on error
605 bool PVGUI_Module::deactivateModule( SUIT_Study* study )
607 MESSAGE("PARAVIS deactivation ...")
609 QMenu* aMenu = menuMgr()->findMenu( myRecentMenuId );
611 QList<QAction*> anActns = aMenu->actions();
612 for (int i = 0; i < anActns.size(); ++i) {
613 QAction* a = anActns.at(i);
615 a->setVisible(false);
619 QList<QMenu*>::iterator it;
620 for (it = myMenus.begin(); it != myMenus.end(); ++it) {
621 QAction* a = (*it)->menuAction();
623 a->setVisible(false);
626 QList<QDockWidget*> aStreamingViews = application()->desktop()->findChildren<QDockWidget*>("pqStreamingControls");
627 foreach(QDockWidget* aView, aStreamingViews) {
628 if (!myDockWidgets.contains(aView))
629 myDockWidgets[aView] = aView->isVisible();
632 /*if (pqImplementation::helpWindow) {
633 pqImplementation::helpWindow->hide();
636 menuMgr()->hide(myRecentMenuId);
637 menuMgr()->hide(mySourcesMenuId);
638 menuMgr()->hide(myFiltersMenuId);
639 menuMgr()->hide(myMacrosMenuId);
640 menuMgr()->hide(myCatalystMenuId);
641 setMenuShown( false );
642 setToolShown( false );
644 saveDockWidgetsState();
646 SUIT_ExceptionHandler::removeCleanUpRoutine( paravisCleanUp );
649 qInstallMessageHandler(myOldMsgHandler);
651 restoreCommonWindowsState();
653 return LightApp_Module::deactivateModule( study );
658 \brief Called when application is closed.
660 Process finalize application functionality from ParaView in order to save server settings
661 and nullify application pointer if the application is being closed.
663 \param theApp application
665 void PVGUI_Module::onApplicationClosed( SUIT_Application* theApp )
667 PVViewer_Core::ParaviewCleanup();
668 CAM_Module::onApplicationClosed(theApp);
672 \brief Called when study is closed.
674 Removes data model from the \a study.
676 \param study study being closed
678 void PVGUI_Module::studyClosed(SUIT_Study* study)
680 showView(false); // VSR: this seems to be not needed (all views are automatically closed)
681 clearParaviewState();
685 LightApp_Module::studyClosed(study);
689 \brief Open file of format supported by ParaView
691 void PVGUI_Module::openFile( const char* theName )
695 pqLoadDataReaction::loadData( aFiles );
699 \brief Starts Python trace.
701 Start trace invoking the newly introduced C++ API (PV 4.2)
702 (inspired from pqTraceReaction::start())
704 void PVGUI_Module::startTrace()
706 vtkSMSessionProxyManager* pxm = pqActiveObjects::instance().activeServer()->proxyManager();
708 vtkSmartPointer<vtkSMProxy> proxy;
709 proxy.TakeReference( pxm->NewProxy( "pythontracing", "PythonTraceOptions" ) );
711 vtkNew<vtkSMParaViewPipelineController> controller;
712 controller->InitializeProxy( proxy );
714 vtkSMTrace* trace = vtkSMTrace::StartTrace();
716 // Set manually the properties entered via the dialog box poping-up when requiring
717 // a trace start in PV4.2 (trace options)
718 SUIT_ResourceMgr* aResourceMgr = SUIT_Session::session()->resourceMgr();
719 int type = aResourceMgr->integerValue( PARAVIS_MODULE_NAME, "tracestate_type", 2 );
720 trace->SetPropertiesToTraceOnCreate( type );
721 trace->SetFullyTraceSupplementalProxies( false );
726 \brief Stops Python trace.
728 void PVGUI_Module::stopTrace()
730 vtkSMTrace::StopTrace();
734 \brief Execute a Python script.
736 void PVGUI_Module::executeScript( const char* script )
739 // Not sure this is the right fix, but the PYTHON_MANAGER has a function named
740 // executeScript() which seems to do what the runScript on pyShellDialog() class
743 pqPythonManager* manager =
744 qobject_cast<pqPythonManager*>(pqApplicationCore::instance()->manager("PYTHON_MANAGER"));
747 manager->executeScript(script);
752 pqPythonManager* manager = qobject_cast<pqPythonManager*>(
753 pqApplicationCore::instance()->manager( "PYTHON_MANAGER" ) );
755 pqPythonDialog* pyDiag = manager->pythonShellDialog();
757 pyDiag->runString(script);
765 // * Debug function printing out the given interpreter's execution context
767 //void printInterpContext(PyInterp_Interp * interp )
769 // // Extract __smtraceString from interpreter's context
770 // const PyObject* ctxt = interp->getExecutionContext();
772 // PyObject* lst = PyDict_Keys((PyObject *)ctxt);
773 // Py_ssize_t siz = PyList_GET_SIZE(lst);
774 // for (Py_ssize_t i = 0; i < siz; i++)
776 // PyObject * elem = PyList_GetItem(lst, i);
777 // if (PyString_Check(elem))
779 // std::cout << "At pos:" << i << ", " << Py_EncodeLocale(PyUnicode_AS_UNICODE(elem), NULL) << std::endl;
782 // std::cout << "At pos:" << i << ", not a string!" << std::endl;
788 \brief Returns trace string
790 QString PVGUI_Module::getTraceString()
792 QString traceString = "";
794 static const QString replaceStr( "paraview.simple" );
795 std::stringstream nl;
796 nl << std::endl; // surely there is some Qt trick to do that in a portable way??
797 QString end_line( nl.str().c_str() );
799 vtkSMTrace* tracer = vtkSMTrace::GetActiveTracer();
801 traceString = tracer->GetCurrentTrace().c_str();
802 // 'import pvsimple' is necessary to fix the first call to DisableFirstRenderCamera in the paraview trace
803 // 'ShowParaviewView()' ensure there is an opened viewing window (otherwise SEGFAULT!)
804 traceString = "import pvsimple" + end_line +
805 "pvsimple.ShowParaviewView()" + end_line + traceString;
807 // Replace import "paraview.simple" by "pvsimple"
808 if ( !traceString.isEmpty() ) {
809 int aPos = traceString.indexOf( replaceStr );
810 while ( aPos != -1 ) {
811 traceString = traceString.replace( aPos, replaceStr.length(), "pvsimple" );
812 aPos = traceString.indexOf( replaceStr, aPos );
817 // Save camera position to, which is no longer output by the tracer ...
819 vtkPythonScopeGilEnsurer psge;
820 PyObject * mods(PySys_GetObject(const_cast<char*>("modules")));
821 PyObject * trace_mod(PyDict_GetItemString(mods, "paraview.smtrace")); // module was already (really) imported by vtkSMTrace
822 if (trace_mod && trace_mod != Py_None && PyModule_Check(trace_mod)) {
823 vtkSmartPyObject save_cam(PyObject_GetAttrString(trace_mod, const_cast<char*>("SaveCameras")));
824 vtkSmartPyObject camera_trace(PyObject_CallMethod(save_cam, const_cast<char*>("get_trace"), NULL));
825 // Convert to a single string
826 vtkSmartPyObject ret(PyUnicode_FromUnicode(Py_DecodeLocale(end_line.toStdString().c_str(), NULL), end_line.size()));
827 vtkSmartPyObject final_string(PyObject_CallMethod(ret, const_cast<char*>("join"),
828 const_cast<char*>("O"), (PyObject*)camera_trace));
829 if (PyUnicode_CheckExact(final_string))
831 QString camera_qs(Py_EncodeLocale(PyUnicode_AS_UNICODE(final_string.GetPointer()), NULL)); // deep copy
832 traceString = traceString + end_line + end_line + QString("#### saving camera placements for all active views")
833 + end_line + end_line + camera_qs + end_line;
842 \brief Saves trace string to disk file
844 void PVGUI_Module::saveTrace( const char* theName )
846 QFile file( theName );
847 if ( !file.open( QIODevice::WriteOnly | QIODevice::Text ) ) {
848 MESSAGE( "Could not open file:" << theName );
851 QTextStream out( &file );
852 out << getTraceString();
857 \brief Saves ParaView state to a disk file
859 void PVGUI_Module::saveParaviewState( const QString& theFileName )
861 pqApplicationCore::instance()->saveState( theFileName.toStdString().c_str() );
865 \brief Delete all objects for Paraview Pipeline Browser
867 void PVGUI_Module::clearParaviewState()
869 QAction* deleteAllAction = action( DeleteAllId );
870 if ( deleteAllAction ) {
871 deleteAllAction->activate( QAction::Trigger );
876 \brief Restores ParaView state from a disk file
878 void PVGUI_Module::loadParaviewState( const QString& theFileName )
880 pqApplicationCore::instance()->loadState( theFileName.toStdString().c_str(), getActiveServer() );
881 pqLoadStateReaction::activateView();
885 \brief Returns current active ParaView server
887 pqServer* PVGUI_Module::getActiveServer()
889 return pqApplicationCore::instance()->getActiveServer();
894 \brief Creates PARAVIS preferences panel.
896 void PVGUI_Module::createPreferences()
898 QList<QVariant> aIndices;
899 QStringList aStrings;
901 // Paraview settings tab
902 int aParaViewSettingsTab = addPreference( tr( "TIT_PVIEWSETTINGS" ) );
904 setPreferenceProperty(aParaViewSettingsTab, "stretch", false );
905 int aPanel = addPreference( QString(), aParaViewSettingsTab,
906 LightApp_Preferences::UserDefined, PARAVIS_MODULE_NAME, "" );
908 setPreferenceProperty( aPanel, "content", (qint64)( new PVGUI_ParaViewSettingsPane( 0, getApp() ) ) );
910 // Paravis settings tab
911 int aParaVisSettingsTab = addPreference( tr( "TIT_PVISSETTINGS" ) );
913 addPreference( tr( "PREF_NO_EXT_PVSERVER" ), aParaVisSettingsTab,
914 LightApp_Preferences::Bool, PARAVIS_MODULE_NAME, "no_ext_pv_server" );
916 int aSaveType = addPreference( tr( "PREF_SAVE_TYPE_LBL" ), aParaVisSettingsTab,
917 LightApp_Preferences::Selector,
918 PARAVIS_MODULE_NAME, "savestate_type" );
922 aIndices << 0 << 1 << 2;
923 aStrings << tr("PREF_SAVE_TYPE_0") << tr("PREF_SAVE_TYPE_1") << tr("PREF_SAVE_TYPE_2");
924 setPreferenceProperty( aSaveType, "strings", aStrings );
925 setPreferenceProperty( aSaveType, "indexes", aIndices );
927 // ... "Language" group <<start>>
928 int traceGroup = addPreference( tr( "PREF_GROUP_TRACE" ), aParaVisSettingsTab );
930 int stopTrace = addPreference( tr( "PREF_STOP_TRACE" ), traceGroup,
931 LightApp_Preferences::Bool, PARAVIS_MODULE_NAME, "stop_trace" );
932 setPreferenceProperty( stopTrace, "restart", true );
934 int aTraceType = addPreference( tr( "PREF_TRACE_TYPE_LBL" ), traceGroup,
935 LightApp_Preferences::Selector,
936 PARAVIS_MODULE_NAME, "tracestate_type" );
939 aIndices << 0 << 1 << 2;
940 aStrings << tr("PREF_TRACE_TYPE_0") << tr("PREF_TRACE_TYPE_1") << tr("PREF_TRACE_TYPE_2");
941 setPreferenceProperty( aTraceType, "strings", aStrings );
942 setPreferenceProperty( aTraceType, "indexes", aIndices );
943 setPreferenceProperty( aTraceType, "restart", true );
947 \brief. Show ParaView python trace.
949 void PVGUI_Module::onShowTrace()
951 if (!myTraceWindow) {
952 myTraceWindow = new pqPythonScriptEditor(getApp()->desktop());
954 myTraceWindow->setText(getTraceString());
955 myTraceWindow->show();
956 myTraceWindow->raise();
957 myTraceWindow->activateWindow();
962 \brief. Re-initialize ParaView python trace.
964 void PVGUI_Module::onRestartTrace()
971 \brief. Close ParaView python trace.
973 void PVGUI_Module::onStopTrace()
978 \brief Called when view manager is added
980 void PVGUI_Module::onViewManagerAdded( SUIT_ViewManager* vm )
982 if ( PVViewer_ViewManager* pvvm = dynamic_cast<PVViewer_ViewManager*>( vm ) ) {
983 connect( pvvm, SIGNAL( viewCreated( SUIT_ViewWindow* ) ),
984 this, SLOT( onPVViewCreated( SUIT_ViewWindow* ) ) );
985 connect( pvvm, SIGNAL( deleteView( SUIT_ViewWindow* ) ),
986 this, SLOT( onPVViewDelete( SUIT_ViewWindow* ) ) );
991 \brief Called when view manager is removed
993 void PVGUI_Module::onViewManagerRemoved( SUIT_ViewManager* vm )
995 if ( PVViewer_ViewManager* pvvm = dynamic_cast<PVViewer_ViewManager*>( vm ) )
996 disconnect( pvvm, SIGNAL( viewCreated( SUIT_ViewWindow* ) ),
997 this, SLOT( onPVViewCreated( SUIT_ViewWindow* ) ) );
1001 \brief Show toolbars at \a vw PV view window creating when PARAVIS is active.
1003 void PVGUI_Module::onPVViewCreated( SUIT_ViewWindow* /*vw*/ )
1005 myGuiElements->setToolBarVisible( true );
1006 restoreDockWidgetsState();
1010 \brief Save toolbars state at \a view view closing.
1012 void PVGUI_Module::onPVViewDelete( SUIT_ViewWindow* view )
1014 if ( dynamic_cast<PVViewer_ViewWindow*>( view ) )
1015 saveDockWidgetsState( false );
1019 \fn CAM_Module* createModule();
1020 \brief Export module instance (factory function).
1021 \return new created instance of the module
1025 #define PVGUI_EXPORT __declspec(dllexport)
1027 #define PVGUI_EXPORT
1033 PVGUI_EXPORT CAM_Module* createModule() {
1034 return new PVGUI_Module();
1037 PVGUI_EXPORT char* getModuleVersion() {
1038 return (char*)PARAVIS_VERSION_STR;