1 // PARAVIS : ParaView wrapper SALOME module
3 // Copyright (C) 2010-2019 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>
129 #if PY_VERSION_HEX < 0x03050000
131 Py_EncodeLocale(const wchar_t *arg, size_t *size)
133 return _Py_wchar2char(arg, size);
136 Py_DecodeLocale(const char *arg, size_t *size)
138 return _Py_char2wchar(arg, size);
142 //----------------------------------------------------------------------------
143 PVGUI_Module* ParavisModule = 0;
147 This is the doxygen documentation of the ParaVis module.
148 If you are looking for general information about the structure of the module, you should
149 take a look at the <a href="../index.html">Sphinx documentation</a> first.
151 The integration of ParaView into SALOME is split in two parts:
152 \li the PVViewer in the GUI module (folder *src/PVViewer*)
153 \li the ParaVis module itself (the pages you are currently browsing)
158 \brief Implementation
159 SALOME module wrapping ParaView GUI.
163 \brief Clean up function
165 Used to stop ParaView progress events when
166 exception is caught by global exception handler.
168 void paravisCleanUp()
170 if ( pqApplicationCore::instance() ) {
171 pqServer* s = pqApplicationCore::instance()->getActiveServer();
172 if ( s ) s->session()->GetProgressHandler()->CleanupPendingProgress();
177 \brief Constructor. Sets the default name for the module.
179 PVGUI_Module::PVGUI_Module()
180 : LightApp_Module( PARAVIS_MODULE_NAME ),
181 mySourcesMenuId( -1 ),
182 myFiltersMenuId( -1 ),
185 myCatalystMenuId(-1),
192 Q_INIT_RESOURCE( PVGUI );
194 ParavisModule = this;
200 PVGUI_Module::~PVGUI_Module()
207 \brief Retrieve the PVSERVER CORBA engine.
208 This uses the Python wrapper provided
209 by the PVViewer code in GUI (class PVViewer_EngineWrapper).
212 PVServer_ServiceWrapper* PVGUI_Module::GetEngine()
214 return PVServer_ServiceWrapper::GetInstance();
218 \brief Create data model.
219 \return module specific data model
221 CAM_DataModel* PVGUI_Module::createDataModel()
223 return new PVGUI_DataModel( this );
227 \brief Get the ParaView application singleton.
229 pqPVApplicationCore* PVGUI_Module::GetPVApplication()
231 return PVViewer_Core::GetPVApplication();
235 \brief Initialize module. Creates menus, prepares context menu, etc.
236 \param app SALOME GUI application instance
238 void PVGUI_Module::initialize( CAM_Application* app )
240 LightApp_Module::initialize( app );
242 // Uncomment to debug ParaView initialization
243 // "aa" used instead of "i" as GDB doesn't like "i" variables :)
251 LightApp_Application* anApp = getApp();
252 SUIT_Desktop* aDesktop = anApp->desktop();
254 // Remember current state of desktop toolbars
255 QList<QToolBar*> foreignToolbars = aDesktop->findChildren<QToolBar*>();
257 // Initialize ParaView client and associated behaviors
258 // and connect to externally launched pvserver
259 PVViewer_Core::ParaviewInitApp(aDesktop);
261 // Clear old copies of embedded macros files
262 //QString aDestPath = QString( "%1/.config/%2/Macros" ).arg( QDir::homePath() ).arg( QApplication::applicationName() );
263 QString aDestPath = pqCoreUtilities::getParaViewUserDirectory() + "/Macros";
267 QDir aDestDir(aDestPath);
268 QStringList aDestFiles = aDestDir.entryList(aFilter, QDir::Files);
269 foreach(QString aMacrosPath, getEmbeddedMacrosList()) {
270 QString aMacrosName = QFileInfo(aMacrosPath).fileName();
271 if (aDestFiles.contains(aMacrosName)) {
272 aDestDir.remove(aMacrosName);
276 myGuiElements = PVViewer_GUIElements::GetInstance(aDesktop);
279 // [ABN]: careful with the order of the GUI element creation, the loading of the configuration
280 // and the connection to the server. This order is very sensitive if one wants to make
281 // sure all menus, etc ... are correctly populated.
282 // Reference points are: ParaViewMainWindow.cxx and branded_paraview_initializer.cxx.in
289 PVViewer_Core::ParaviewInitBehaviors(true, aDesktop);
291 QList<QDockWidget*> activeDocks = aDesktop->findChildren<QDockWidget*>();
292 QList<QMenu*> activeMenus = aDesktop->findChildren<QMenu*>();
294 // Setup quick-launch shortcuts.
295 QShortcut *ctrlSpace = new QShortcut(Qt::CTRL + Qt::Key_Space, aDesktop);
296 QObject::connect(ctrlSpace, SIGNAL(activated()),
297 pqApplicationCore::instance(), SLOT(quickLaunch()));
299 // Find Plugin Dock Widgets
300 QList<QDockWidget*> currentDocks = aDesktop->findChildren<QDockWidget*>();
301 QList<QDockWidget*>::iterator i;
302 for (i = currentDocks.begin(); i != currentDocks.end(); ++i) {
303 if(!activeDocks.contains(*i)) {
304 myDockWidgets[*i] = false; // hidden by default
310 // [ABN] TODO: fix this - triggers a SEGFAULT at deactivation() time.
311 // QList<QMenu*> currentMenus = aDesktop->findChildren<QMenu*>();
312 // QList<QMenu*>::iterator im;
313 // for (im = currentMenus.begin(); im != currentMenus.end(); ++im) {
314 // if(!activeMenus.contains(*im)) {
315 // QString s = (*im)->title();
316 // std::cout << " MENU "<< s.toStdString() << std::endl;
317 // myMenus.append(*im);
321 // Connect after toolbar creation, etc ... as some activations of the toolbars is triggered
322 // by the ServerConnection event:
323 const QString configPath(PVViewer_ViewManager::GetPVConfigPath());
324 PVViewer_Core::ParaviewLoadConfigurations(configPath, true);
325 PVViewer_ViewManager::ConnectToExternalPVServer(aDesktop);
328 // Find created toolbars
329 QCoreApplication::processEvents();
331 // process PVViewer toolbars (might be added by PVViewer created BEFORE activating ParaVis)
332 QList<QToolBar*> pvToolbars = myGuiElements->getToolbars();
333 foreach(QToolBar* aBar, pvToolbars) {
334 if (!myToolbars.contains(aBar)) {
335 myToolbars[aBar] = true;
336 myToolbarBreaks[aBar] = false;
337 aBar->setVisible(false);
338 aBar->toggleViewAction()->setVisible(false);
342 // process other toolbars (possibly added by Paraview)
343 QList<QToolBar*> allToolbars = aDesktop->findChildren<QToolBar*>();
344 foreach(QToolBar* aBar, allToolbars) {
345 if (!foreignToolbars.contains(aBar) && !myToolbars.contains(aBar)) {
346 myToolbars[aBar] = true;
347 myToolbarBreaks[aBar] = false;
348 aBar->setVisible(false);
349 aBar->toggleViewAction()->setVisible(false);
355 SUIT_ResourceMgr* aResourceMgr = SUIT_Session::session()->resourceMgr();
356 bool isStop = aResourceMgr->booleanValue( PARAVIS_MODULE_NAME, "stop_trace", false );
359 // Start a timer to schedule asap:
361 myInitTimer = new QTimer(aDesktop);
362 QObject::connect(myInitTimer, SIGNAL(timeout()), this, SLOT(onInitTimer()) );
363 myInitTimer->setSingleShot(true);
364 myInitTimer->start(0);
367 this->VTKConnect = vtkEventQtSlotConnect::New();
369 vtkProcessModule* pm = vtkProcessModule::GetProcessModule();
371 vtkPVSession* pvs = dynamic_cast<vtkPVSession*>(pm->GetSession());
373 vtkPVProgressHandler* ph = pvs->GetProgressHandler();
375 this->VTKConnect->Connect(ph, vtkCommand::StartEvent,
376 this, SLOT(onStartProgress()));
377 this->VTKConnect->Connect(ph, vtkCommand::EndEvent,
378 this, SLOT(onEndProgress()));
382 connect( application(), SIGNAL( appClosed() ), this, SLOT( onStopTrace() ) );
386 * \brief Slot called when the progress bar starts.
388 void PVGUI_Module::onStartProgress()
390 // VSR 19/03/2015, issue 0023025
391 // next line is commented: it is bad idea to show wait cursor on ANY vtk event
392 // moreover, it does not work when running pvserver with --multi-client mode
393 //QApplication::setOverrideCursor(Qt::WaitCursor);
397 * \brief Slot called when the progress bar is done.
399 void PVGUI_Module::onEndProgress()
401 // VSR 19/03/2015, issue 0023025
402 // next line is commented: it is bad idea to show wait cursor on ANY vtk event
403 // moreover, it does not work when running pvserver with --multi-client mode
404 //QApplication::restoreOverrideCursor();
407 void PVGUI_Module::onDataRepresentationUpdated() {
408 LightApp_Study* activeStudy = dynamic_cast<LightApp_Study*>(application()->activeStudy());
409 if(!activeStudy) return;
411 activeStudy->Modified();
415 \brief Initialisation timer event - Starts up the Python trace
417 void PVGUI_Module::onInitTimer()
423 \brief Get list of embedded macros files
425 QStringList PVGUI_Module::getEmbeddedMacrosList()
427 QString aRootDir = getenv("PARAVIS_ROOT_DIR");
429 QString aSourcePath = aRootDir + "/bin/salome/Macro";
434 QDir aSourceDir(aSourcePath);
435 QStringList aSourceFiles = aSourceDir.entryList(aFilter, QDir::Files);
436 QStringList aFullPathSourceFiles;
437 foreach (QString aMacrosName, aSourceFiles) {
438 aFullPathSourceFiles << aSourceDir.absoluteFilePath(aMacrosName);
440 return aFullPathSourceFiles;
444 \brief Update the list of embedded macros
446 void PVGUI_Module::updateMacros()
448 pqPythonManager* aPythonManager = pqPVApplicationCore::instance()->pythonManager();
449 if(!aPythonManager) {
453 foreach (QString aStr, getEmbeddedMacrosList()) {
454 aPythonManager->addMacro(aStr);
460 \brief Get list of compliant dockable GUI elements
461 \param m map to be filled in ("type":"default_position")
463 void PVGUI_Module::windows( QMap<int, int>& m ) const
465 m.insert( LightApp_Application::WT_ObjectBrowser, Qt::LeftDockWidgetArea );
466 #ifndef DISABLE_PYCONSOLE
467 m.insert( LightApp_Application::WT_PyConsole, Qt::BottomDockWidgetArea );
469 // ParaView diagnostic output redirected here
470 m.insert( LightApp_Application::WT_LogWindow, Qt::BottomDockWidgetArea );
474 \brief Shows (toShow = true) or hides ParaView view window
476 void PVGUI_Module::showView( bool toShow )
478 // VSR: TODO: all below is not needed, if we use standard approach
479 // that consists in implementing viewManagers() function properly
480 // This should be done after we decide what to do with Log window.
481 LightApp_Application* anApp = getApp();
482 PVViewer_ViewManager* viewMgr =
483 dynamic_cast<PVViewer_ViewManager*>( anApp->getViewManager( PVViewer_Viewer::Type(), false ) );
485 viewMgr = new PVViewer_ViewManager( anApp->activeStudy(), anApp->desktop() );
486 anApp->addViewManager( viewMgr );
487 connect( viewMgr, SIGNAL( lastViewClosed( SUIT_ViewManager* ) ),
488 anApp, SLOT( onCloseView( SUIT_ViewManager* ) ) );
491 PVViewer_ViewWindow* pvWnd = dynamic_cast<PVViewer_ViewWindow*>( viewMgr->getActiveView() );
493 pvWnd = dynamic_cast<PVViewer_ViewWindow*>( viewMgr->createViewWindow() );
494 // this also connects to the pvserver and instantiates relevant PV behaviors
497 pvWnd->setVisible( toShow );
498 if ( toShow ) pvWnd->setFocus();
502 \brief Slot to show help for proxy.
504 void PVGUI_Module::showHelpForProxy( const QString& groupname, const QString& proxyname )
506 pqHelpReaction::showProxyHelp(groupname, proxyname);
510 \brief Slot to show the waiting state.
512 void PVGUI_Module::onPreAccept()
514 getApp()->desktop()->statusBar()->showMessage(tr("STB_PREACCEPT"));
515 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
519 \brief Slot to show the ready state.
521 void PVGUI_Module::onPostAccept()
523 getApp()->desktop()->statusBar()->showMessage(tr("STB_POSTACCEPT"), 2000);
524 QTimer::singleShot(0, this, SLOT(endWaitCursor()));
528 \brief Slot to switch off wait cursor.
530 void PVGUI_Module::endWaitCursor()
532 QApplication::restoreOverrideCursor();
536 \brief Activate module.
537 \param study current study
538 \return \c true if activaion is done successfully or 0 to prevent
541 bool PVGUI_Module::activateModule( SUIT_Study* study )
543 SUIT_ExceptionHandler::addCleanUpRoutine( paravisCleanUp );
545 storeCommonWindowsState();
547 bool isDone = LightApp_Module::activateModule( study );
548 if ( !isDone ) return false;
551 if ( mySourcesMenuId != -1 ) menuMgr()->show(mySourcesMenuId);
552 if ( myFiltersMenuId != -1 ) menuMgr()->show(myFiltersMenuId);
553 if ( myMacrosMenuId != -1 ) menuMgr()->show(myMacrosMenuId);
554 if ( myCatalystMenuId != -1 ) menuMgr()->show(myCatalystMenuId);
556 // Update the various menus with the content pre-loaded in myGuiElements
557 // QMenu* srcMenu = menuMgr()->findMenu( mySourcesMenuId );
558 // myGuiElements->updateSourcesMenu(srcMenu);
559 // QMenu* filtMenu = menuMgr()->findMenu( myFiltersMenuId );
560 // myGuiElements->updateFiltersMenu(filtMenu);
561 // QMenu* macMenu = menuMgr()->findMenu( myMacrosMenuId );
562 // myGuiElements->updateMacrosMenu(macMenu);
564 setMenuShown( true );
565 setToolShown( true );
567 restoreDockWidgetsState();
569 QMenu* aMenu = menuMgr()->findMenu( myRecentMenuId );
571 QList<QAction*> anActns = aMenu->actions();
572 for (int i = 0; i < anActns.size(); ++i) {
573 QAction* a = anActns.at(i);
579 QList<QMenu*>::iterator it;
580 for (it = myMenus.begin(); it != myMenus.end(); ++it) {
581 QAction* a = (*it)->menuAction();
586 if ( myRecentMenuId != -1 ) menuMgr()->show(myRecentMenuId);
588 // VSR 18/10/2018 - 0023170: Workaround to re-select current index after module activation
589 QItemSelectionModel* selection_model = myGuiElements->getPipelineBrowserWidget()->getSelectionModel();
590 QModelIndex idx = selection_model->currentIndex();
591 selection_model->clearCurrentIndex();
592 selection_model->setCurrentIndex(idx, QItemSelectionModel::ClearAndSelect);
599 \brief Deactivate module.
600 \param study current study
601 \return \c true if deactivaion is done successfully or 0 to prevent
602 deactivation on error
604 bool PVGUI_Module::deactivateModule( SUIT_Study* study )
606 MESSAGE("PARAVIS deactivation ...")
608 QMenu* aMenu = menuMgr()->findMenu( myRecentMenuId );
610 QList<QAction*> anActns = aMenu->actions();
611 for (int i = 0; i < anActns.size(); ++i) {
612 QAction* a = anActns.at(i);
614 a->setVisible(false);
618 QList<QMenu*>::iterator it;
619 for (it = myMenus.begin(); it != myMenus.end(); ++it) {
620 QAction* a = (*it)->menuAction();
622 a->setVisible(false);
625 QList<QDockWidget*> aStreamingViews = application()->desktop()->findChildren<QDockWidget*>("pqStreamingControls");
626 foreach(QDockWidget* aView, aStreamingViews) {
627 if (!myDockWidgets.contains(aView))
628 myDockWidgets[aView] = aView->isVisible();
631 /*if (pqImplementation::helpWindow) {
632 pqImplementation::helpWindow->hide();
635 menuMgr()->hide(myRecentMenuId);
636 menuMgr()->hide(mySourcesMenuId);
637 menuMgr()->hide(myFiltersMenuId);
638 menuMgr()->hide(myMacrosMenuId);
639 menuMgr()->hide(myCatalystMenuId);
640 setMenuShown( false );
641 setToolShown( false );
643 saveDockWidgetsState();
645 SUIT_ExceptionHandler::removeCleanUpRoutine( paravisCleanUp );
648 qInstallMessageHandler(myOldMsgHandler);
650 restoreCommonWindowsState();
652 return LightApp_Module::deactivateModule( study );
657 \brief Called when application is closed.
659 Process finalize application functionality from ParaView in order to save server settings
660 and nullify application pointer if the application is being closed.
662 \param theApp application
664 void PVGUI_Module::onApplicationClosed( SUIT_Application* theApp )
666 PVViewer_Core::ParaviewCleanup();
667 CAM_Module::onApplicationClosed(theApp);
671 \brief Called when study is closed.
673 Removes data model from the \a study.
675 \param study study being closed
677 void PVGUI_Module::studyClosed(SUIT_Study* study)
679 showView(false); // VSR: this seems to be not needed (all views are automatically closed)
680 clearParaviewState();
684 LightApp_Module::studyClosed(study);
688 \brief Open file of format supported by ParaView
690 void PVGUI_Module::openFile( const char* theName )
694 pqLoadDataReaction::loadData( aFiles );
698 \brief Starts Python trace.
700 Start trace invoking the newly introduced C++ API (PV 4.2)
701 (inspired from pqTraceReaction::start())
703 void PVGUI_Module::startTrace()
705 vtkSMSessionProxyManager* pxm = pqActiveObjects::instance().activeServer()->proxyManager();
707 vtkSmartPointer<vtkSMProxy> proxy;
708 proxy.TakeReference( pxm->NewProxy( "pythontracing", "PythonTraceOptions" ) );
710 vtkNew<vtkSMParaViewPipelineController> controller;
711 controller->InitializeProxy( proxy );
713 vtkSMTrace* trace = vtkSMTrace::StartTrace();
715 // Set manually the properties entered via the dialog box poping-up when requiring
716 // a trace start in PV4.2 (trace options)
717 SUIT_ResourceMgr* aResourceMgr = SUIT_Session::session()->resourceMgr();
718 int type = aResourceMgr->integerValue( PARAVIS_MODULE_NAME, "tracestate_type", 2 );
719 trace->SetPropertiesToTraceOnCreate( type );
720 trace->SetFullyTraceSupplementalProxies( false );
725 \brief Stops Python trace.
727 void PVGUI_Module::stopTrace()
729 vtkSMTrace::StopTrace();
733 \brief Execute a Python script.
735 void PVGUI_Module::executeScript( const char* script )
738 // Not sure this is the right fix, but the PYTHON_MANAGER has a function named
739 // executeScript() which seems to do what the runScript on pyShellDialog() class
742 pqPythonManager* manager =
743 qobject_cast<pqPythonManager*>(pqApplicationCore::instance()->manager("PYTHON_MANAGER"));
746 manager->executeScript(script);
751 pqPythonManager* manager = qobject_cast<pqPythonManager*>(
752 pqApplicationCore::instance()->manager( "PYTHON_MANAGER" ) );
754 pqPythonDialog* pyDiag = manager->pythonShellDialog();
756 pyDiag->runString(script);
764 // * Debug function printing out the given interpreter's execution context
766 //void printInterpContext(PyInterp_Interp * interp )
768 // // Extract __smtraceString from interpreter's context
769 // const PyObject* ctxt = interp->getExecutionContext();
771 // PyObject* lst = PyDict_Keys((PyObject *)ctxt);
772 // Py_ssize_t siz = PyList_GET_SIZE(lst);
773 // for (Py_ssize_t i = 0; i < siz; i++)
775 // PyObject * elem = PyList_GetItem(lst, i);
776 // if (PyString_Check(elem))
778 // std::cout << "At pos:" << i << ", " << Py_EncodeLocale(PyUnicode_AS_UNICODE(elem), NULL) << std::endl;
781 // std::cout << "At pos:" << i << ", not a string!" << std::endl;
787 \brief Returns trace string
789 QString PVGUI_Module::getTraceString()
791 QString traceString = "";
793 static const QString replaceStr( "paraview.simple" );
794 std::stringstream nl;
795 nl << std::endl; // surely there is some Qt trick to do that in a portable way??
796 QString end_line( nl.str().c_str() );
798 vtkSMTrace* tracer = vtkSMTrace::GetActiveTracer();
800 traceString = tracer->GetCurrentTrace();
801 // 'import pvsimple' is necessary to fix the first call to DisableFirstRenderCamera in the paraview trace
802 // 'ShowParaviewView()' ensure there is an opened viewing window (otherwise SEGFAULT!)
803 traceString = "import pvsimple" + end_line +
804 "pvsimple.ShowParaviewView()" + end_line + traceString;
806 // Replace import "paraview.simple" by "pvsimple"
807 if ( !traceString.isEmpty() ) {
808 int aPos = traceString.indexOf( replaceStr );
809 while ( aPos != -1 ) {
810 traceString = traceString.replace( aPos, replaceStr.length(), "pvsimple" );
811 aPos = traceString.indexOf( replaceStr, aPos );
816 // Save camera position to, which is no longer output by the tracer ...
818 vtkPythonScopeGilEnsurer psge;
819 PyObject * mods(PySys_GetObject(const_cast<char*>("modules")));
820 PyObject * trace_mod(PyDict_GetItemString(mods, "paraview.smtrace")); // module was already (really) imported by vtkSMTrace
821 if (trace_mod && trace_mod != Py_None && PyModule_Check(trace_mod)) {
822 vtkSmartPyObject save_cam(PyObject_GetAttrString(trace_mod, const_cast<char*>("SaveCameras")));
823 vtkSmartPyObject camera_trace(PyObject_CallMethod(save_cam, const_cast<char*>("get_trace"), NULL));
824 // Convert to a single string
825 vtkSmartPyObject ret(PyUnicode_FromUnicode(Py_DecodeLocale(end_line.toStdString().c_str(), NULL), end_line.size()));
826 vtkSmartPyObject final_string(PyObject_CallMethod(ret, const_cast<char*>("join"),
827 const_cast<char*>("O"), (PyObject*)camera_trace));
828 if (PyUnicode_CheckExact(final_string))
830 QString camera_qs(Py_EncodeLocale(PyUnicode_AS_UNICODE(final_string.GetPointer()), NULL)); // deep copy
831 traceString = traceString + end_line + end_line + QString("#### saving camera placements for all active views")
832 + end_line + end_line + camera_qs + end_line;
841 \brief Saves trace string to disk file
843 void PVGUI_Module::saveTrace( const char* theName )
845 QFile file( theName );
846 if ( !file.open( QIODevice::WriteOnly | QIODevice::Text ) ) {
847 MESSAGE( "Could not open file:" << theName );
850 QTextStream out( &file );
851 out << getTraceString();
856 \brief Saves ParaView state to a disk file
858 void PVGUI_Module::saveParaviewState( const QString& theFileName )
860 pqApplicationCore::instance()->saveState( theFileName.toStdString().c_str() );
864 \brief Delete all objects for Paraview Pipeline Browser
866 void PVGUI_Module::clearParaviewState()
868 QAction* deleteAllAction = action( DeleteAllId );
869 if ( deleteAllAction ) {
870 deleteAllAction->activate( QAction::Trigger );
875 \brief Restores ParaView state from a disk file
877 void PVGUI_Module::loadParaviewState( const QString& theFileName )
879 pqApplicationCore::instance()->loadState( theFileName.toStdString().c_str(), getActiveServer() );
883 \brief Returns current active ParaView server
885 pqServer* PVGUI_Module::getActiveServer()
887 return pqApplicationCore::instance()->getActiveServer();
892 \brief Creates PARAVIS preferences panel.
894 void PVGUI_Module::createPreferences()
896 QList<QVariant> aIndices;
897 QStringList aStrings;
899 // Paraview settings tab
900 int aParaViewSettingsTab = addPreference( tr( "TIT_PVIEWSETTINGS" ) );
902 setPreferenceProperty(aParaViewSettingsTab, "stretch", false );
903 int aPanel = addPreference( QString(), aParaViewSettingsTab,
904 LightApp_Preferences::UserDefined, PARAVIS_MODULE_NAME, "" );
906 setPreferenceProperty( aPanel, "content", (qint64)( new PVGUI_ParaViewSettingsPane( 0, getApp() ) ) );
908 // Paravis settings tab
909 int aParaVisSettingsTab = addPreference( tr( "TIT_PVISSETTINGS" ) );
911 addPreference( tr( "PREF_NO_EXT_PVSERVER" ), aParaVisSettingsTab,
912 LightApp_Preferences::Bool, PARAVIS_MODULE_NAME, "no_ext_pv_server" );
914 int aSaveType = addPreference( tr( "PREF_SAVE_TYPE_LBL" ), aParaVisSettingsTab,
915 LightApp_Preferences::Selector,
916 PARAVIS_MODULE_NAME, "savestate_type" );
920 aIndices << 0 << 1 << 2;
921 aStrings << tr("PREF_SAVE_TYPE_0") << tr("PREF_SAVE_TYPE_1") << tr("PREF_SAVE_TYPE_2");
922 setPreferenceProperty( aSaveType, "strings", aStrings );
923 setPreferenceProperty( aSaveType, "indexes", aIndices );
925 // ... "Language" group <<start>>
926 int traceGroup = addPreference( tr( "PREF_GROUP_TRACE" ), aParaVisSettingsTab );
928 int stopTrace = addPreference( tr( "PREF_STOP_TRACE" ), traceGroup,
929 LightApp_Preferences::Bool, PARAVIS_MODULE_NAME, "stop_trace" );
930 setPreferenceProperty( stopTrace, "restart", true );
932 int aTraceType = addPreference( tr( "PREF_TRACE_TYPE_LBL" ), traceGroup,
933 LightApp_Preferences::Selector,
934 PARAVIS_MODULE_NAME, "tracestate_type" );
937 aIndices << 0 << 1 << 2;
938 aStrings << tr("PREF_TRACE_TYPE_0") << tr("PREF_TRACE_TYPE_1") << tr("PREF_TRACE_TYPE_2");
939 setPreferenceProperty( aTraceType, "strings", aStrings );
940 setPreferenceProperty( aTraceType, "indexes", aIndices );
941 setPreferenceProperty( aTraceType, "restart", true );
945 \brief. Show ParaView python trace.
947 void PVGUI_Module::onShowTrace()
949 if (!myTraceWindow) {
950 myTraceWindow = new pqPythonScriptEditor(getApp()->desktop());
952 myTraceWindow->setText(getTraceString());
953 myTraceWindow->show();
954 myTraceWindow->raise();
955 myTraceWindow->activateWindow();
960 \brief. Re-initialize ParaView python trace.
962 void PVGUI_Module::onRestartTrace()
969 \brief. Close ParaView python trace.
971 void PVGUI_Module::onStopTrace()
976 \brief Called when view manager is added
978 void PVGUI_Module::onViewManagerAdded( SUIT_ViewManager* vm )
980 if ( PVViewer_ViewManager* pvvm = dynamic_cast<PVViewer_ViewManager*>( vm ) ) {
981 connect( pvvm, SIGNAL( viewCreated( SUIT_ViewWindow* ) ),
982 this, SLOT( onPVViewCreated( SUIT_ViewWindow* ) ) );
983 connect( pvvm, SIGNAL( deleteView( SUIT_ViewWindow* ) ),
984 this, SLOT( onPVViewDelete( SUIT_ViewWindow* ) ) );
989 \brief Called when view manager is removed
991 void PVGUI_Module::onViewManagerRemoved( SUIT_ViewManager* vm )
993 if ( PVViewer_ViewManager* pvvm = dynamic_cast<PVViewer_ViewManager*>( vm ) )
994 disconnect( pvvm, SIGNAL( viewCreated( SUIT_ViewWindow* ) ),
995 this, SLOT( onPVViewCreated( SUIT_ViewWindow* ) ) );
999 \brief Show toolbars at \a vw PV view window creating when PARAVIS is active.
1001 void PVGUI_Module::onPVViewCreated( SUIT_ViewWindow* vw )
1003 myGuiElements->setToolBarVisible( true );
1004 restoreDockWidgetsState();
1008 \brief Save toolbars state at \a view view closing.
1010 void PVGUI_Module::onPVViewDelete( SUIT_ViewWindow* view )
1012 if ( dynamic_cast<PVViewer_ViewWindow*>( view ) )
1013 saveDockWidgetsState( false );
1017 \fn CAM_Module* createModule();
1018 \brief Export module instance (factory function).
1019 \return new created instance of the module
1023 #define PVGUI_EXPORT __declspec(dllexport)
1025 #define PVGUI_EXPORT
1031 PVGUI_EXPORT CAM_Module* createModule() {
1032 return new PVGUI_Module();
1035 PVGUI_EXPORT char* getModuleVersion() {
1036 return (char*)PARAVIS_VERSION_STR;