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 pqPythonManager* manager = qobject_cast<pqPythonManager*>(
739 pqApplicationCore::instance()->manager( "PYTHON_MANAGER" ) );
741 pqPythonDialog* pyDiag = manager->pythonShellDialog();
743 pyDiag->runString(script);
750 // * Debug function printing out the given interpreter's execution context
752 //void printInterpContext(PyInterp_Interp * interp )
754 // // Extract __smtraceString from interpreter's context
755 // const PyObject* ctxt = interp->getExecutionContext();
757 // PyObject* lst = PyDict_Keys((PyObject *)ctxt);
758 // Py_ssize_t siz = PyList_GET_SIZE(lst);
759 // for (Py_ssize_t i = 0; i < siz; i++)
761 // PyObject * elem = PyList_GetItem(lst, i);
762 // if (PyString_Check(elem))
764 // std::cout << "At pos:" << i << ", " << Py_EncodeLocale(PyUnicode_AS_UNICODE(elem), NULL) << std::endl;
767 // std::cout << "At pos:" << i << ", not a string!" << std::endl;
773 \brief Returns trace string
775 QString PVGUI_Module::getTraceString()
777 QString traceString = "";
779 static const QString replaceStr( "paraview.simple" );
780 std::stringstream nl;
781 nl << std::endl; // surely there is some Qt trick to do that in a portable way??
782 QString end_line( nl.str().c_str() );
784 vtkSMTrace* tracer = vtkSMTrace::GetActiveTracer();
786 traceString = tracer->GetCurrentTrace();
787 // 'import pvsimple' is necessary to fix the first call to DisableFirstRenderCamera in the paraview trace
788 // 'ShowParaviewView()' ensure there is an opened viewing window (otherwise SEGFAULT!)
789 traceString = "import pvsimple" + end_line +
790 "pvsimple.ShowParaviewView()" + end_line + traceString;
792 // Replace import "paraview.simple" by "pvsimple"
793 if ( !traceString.isEmpty() ) {
794 int aPos = traceString.indexOf( replaceStr );
795 while ( aPos != -1 ) {
796 traceString = traceString.replace( aPos, replaceStr.length(), "pvsimple" );
797 aPos = traceString.indexOf( replaceStr, aPos );
802 // Save camera position to, which is no longer output by the tracer ...
804 vtkPythonScopeGilEnsurer psge;
805 PyObject * mods(PySys_GetObject(const_cast<char*>("modules")));
806 PyObject * trace_mod(PyDict_GetItemString(mods, "paraview.smtrace")); // module was already (really) imported by vtkSMTrace
807 if (trace_mod && trace_mod != Py_None && PyModule_Check(trace_mod)) {
808 vtkSmartPyObject save_cam(PyObject_GetAttrString(trace_mod, const_cast<char*>("SaveCameras")));
809 vtkSmartPyObject camera_trace(PyObject_CallMethod(save_cam, const_cast<char*>("get_trace"), NULL));
810 // Convert to a single string
811 vtkSmartPyObject ret(PyUnicode_FromUnicode(Py_DecodeLocale(end_line.toStdString().c_str(), NULL), end_line.size()));
812 vtkSmartPyObject final_string(PyObject_CallMethod(ret, const_cast<char*>("join"),
813 const_cast<char*>("O"), (PyObject*)camera_trace));
814 if (PyUnicode_CheckExact(final_string))
816 QString camera_qs(Py_EncodeLocale(PyUnicode_AS_UNICODE(final_string.GetPointer()), NULL)); // deep copy
817 traceString = traceString + end_line + end_line + QString("#### saving camera placements for all active views")
818 + end_line + end_line + camera_qs + end_line;
827 \brief Saves trace string to disk file
829 void PVGUI_Module::saveTrace( const char* theName )
831 QFile file( theName );
832 if ( !file.open( QIODevice::WriteOnly | QIODevice::Text ) ) {
833 MESSAGE( "Could not open file:" << theName );
836 QTextStream out( &file );
837 out << getTraceString();
842 \brief Saves ParaView state to a disk file
844 void PVGUI_Module::saveParaviewState( const QString& theFileName )
846 pqApplicationCore::instance()->saveState( theFileName.toStdString().c_str() );
850 \brief Delete all objects for Paraview Pipeline Browser
852 void PVGUI_Module::clearParaviewState()
854 QAction* deleteAllAction = action( DeleteAllId );
855 if ( deleteAllAction ) {
856 deleteAllAction->activate( QAction::Trigger );
861 \brief Restores ParaView state from a disk file
863 void PVGUI_Module::loadParaviewState( const QString& theFileName )
865 pqApplicationCore::instance()->loadState( theFileName.toStdString().c_str(), getActiveServer() );
869 \brief Returns current active ParaView server
871 pqServer* PVGUI_Module::getActiveServer()
873 return pqApplicationCore::instance()->getActiveServer();
878 \brief Creates PARAVIS preferences panel.
880 void PVGUI_Module::createPreferences()
882 QList<QVariant> aIndices;
883 QStringList aStrings;
885 // Paraview settings tab
886 int aParaViewSettingsTab = addPreference( tr( "TIT_PVIEWSETTINGS" ) );
888 setPreferenceProperty(aParaViewSettingsTab, "stretch", false );
889 int aPanel = addPreference( QString(), aParaViewSettingsTab,
890 LightApp_Preferences::UserDefined, PARAVIS_MODULE_NAME, "" );
892 setPreferenceProperty( aPanel, "content", (qint64)( new PVGUI_ParaViewSettingsPane( 0, getApp() ) ) );
894 // Paravis settings tab
895 int aParaVisSettingsTab = addPreference( tr( "TIT_PVISSETTINGS" ) );
897 addPreference( tr( "PREF_NO_EXT_PVSERVER" ), aParaVisSettingsTab,
898 LightApp_Preferences::Bool, PARAVIS_MODULE_NAME, "no_ext_pv_server" );
900 int aSaveType = addPreference( tr( "PREF_SAVE_TYPE_LBL" ), aParaVisSettingsTab,
901 LightApp_Preferences::Selector,
902 PARAVIS_MODULE_NAME, "savestate_type" );
906 aIndices << 0 << 1 << 2;
907 aStrings << tr("PREF_SAVE_TYPE_0") << tr("PREF_SAVE_TYPE_1") << tr("PREF_SAVE_TYPE_2");
908 setPreferenceProperty( aSaveType, "strings", aStrings );
909 setPreferenceProperty( aSaveType, "indexes", aIndices );
911 // ... "Language" group <<start>>
912 int traceGroup = addPreference( tr( "PREF_GROUP_TRACE" ), aParaVisSettingsTab );
914 int stopTrace = addPreference( tr( "PREF_STOP_TRACE" ), traceGroup,
915 LightApp_Preferences::Bool, PARAVIS_MODULE_NAME, "stop_trace" );
916 setPreferenceProperty( stopTrace, "restart", true );
918 int aTraceType = addPreference( tr( "PREF_TRACE_TYPE_LBL" ), traceGroup,
919 LightApp_Preferences::Selector,
920 PARAVIS_MODULE_NAME, "tracestate_type" );
923 aIndices << 0 << 1 << 2;
924 aStrings << tr("PREF_TRACE_TYPE_0") << tr("PREF_TRACE_TYPE_1") << tr("PREF_TRACE_TYPE_2");
925 setPreferenceProperty( aTraceType, "strings", aStrings );
926 setPreferenceProperty( aTraceType, "indexes", aIndices );
927 setPreferenceProperty( aTraceType, "restart", true );
931 \brief. Show ParaView python trace.
933 void PVGUI_Module::onShowTrace()
935 if (!myTraceWindow) {
936 myTraceWindow = new pqPythonScriptEditor(getApp()->desktop());
938 myTraceWindow->setText(getTraceString());
939 myTraceWindow->show();
940 myTraceWindow->raise();
941 myTraceWindow->activateWindow();
946 \brief. Re-initialize ParaView python trace.
948 void PVGUI_Module::onRestartTrace()
955 \brief. Close ParaView python trace.
957 void PVGUI_Module::onStopTrace()
962 \brief Called when view manager is added
964 void PVGUI_Module::onViewManagerAdded( SUIT_ViewManager* vm )
966 if ( PVViewer_ViewManager* pvvm = dynamic_cast<PVViewer_ViewManager*>( vm ) ) {
967 connect( pvvm, SIGNAL( viewCreated( SUIT_ViewWindow* ) ),
968 this, SLOT( onPVViewCreated( SUIT_ViewWindow* ) ) );
969 connect( pvvm, SIGNAL( deleteView( SUIT_ViewWindow* ) ),
970 this, SLOT( onPVViewDelete( SUIT_ViewWindow* ) ) );
975 \brief Called when view manager is removed
977 void PVGUI_Module::onViewManagerRemoved( SUIT_ViewManager* vm )
979 if ( PVViewer_ViewManager* pvvm = dynamic_cast<PVViewer_ViewManager*>( vm ) )
980 disconnect( pvvm, SIGNAL( viewCreated( SUIT_ViewWindow* ) ),
981 this, SLOT( onPVViewCreated( SUIT_ViewWindow* ) ) );
985 \brief Show toolbars at \a vw PV view window creating when PARAVIS is active.
987 void PVGUI_Module::onPVViewCreated( SUIT_ViewWindow* vw )
989 myGuiElements->setToolBarVisible( true );
990 restoreDockWidgetsState();
994 \brief Save toolbars state at \a view view closing.
996 void PVGUI_Module::onPVViewDelete( SUIT_ViewWindow* view )
998 if ( dynamic_cast<PVViewer_ViewWindow*>( view ) )
999 saveDockWidgetsState( false );
1003 \fn CAM_Module* createModule();
1004 \brief Export module instance (factory function).
1005 \return new created instance of the module
1009 #define PVGUI_EXPORT __declspec(dllexport)
1011 #define PVGUI_EXPORT
1017 PVGUI_EXPORT CAM_Module* createModule() {
1018 return new PVGUI_Module();
1021 PVGUI_EXPORT char* getModuleVersion() {
1022 return (char*)PARAVIS_VERSION_STR;