1 // PARAVIS : ParaView wrapper SALOME module
3 // Copyright (C) 2010-2016 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 <vtkOutputWindow.h>
91 #include <vtkEventQtSlotConnect.h>
93 #include <vtkSMProxy.h>
94 #include <vtkSmartPointer.h>
95 #include <vtkSMSession.h>
96 #include <vtkSMTrace.h>
97 #include <vtkSMSessionProxyManager.h>
98 #include <vtkSMParaViewPipelineController.h>
99 #include <vtkSmartPyObject.h>
101 #include <pqApplicationCore.h>
102 #include <pqPVApplicationCore.h>
103 #include <pqObjectBuilder.h>
104 #include <pqOptions.h>
105 #include <pqSettings.h>
106 #include <pqServer.h>
107 #include <pqUndoStack.h>
108 #include <pqTabbedMultiViewWidget.h>
109 #include <pqActiveObjects.h>
110 #include <pqHelpReaction.h>
111 #include <pqPluginManager.h>
112 #include <pqPythonDialog.h>
113 #include <pqPythonManager.h>
114 #include <pqLoadDataReaction.h>
115 #include <pqPythonScriptEditor.h>
116 #include <pqDataRepresentation.h>
117 #include <pqDisplayColorWidget.h>
118 #include <pqColorToolbar.h>
119 #include <pqScalarBarVisibilityReaction.h>
120 #include <pqServerResource.h>
121 #include <pqServerConnectReaction.h>
122 #include <pqPluginManager.h>
123 #include <pqVCRToolbar.h>
124 #include <pqAnimationScene.h>
125 #include <pqServerManagerModel.h>
126 #include <pqAnimationTimeToolbar.h>
127 #include <pqPipelineBrowserWidget.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;
196 // Clear old copies of embedded macros files
197 QString aDestPath = QString( "%1/.config/%2/Macros" ).arg( QDir::homePath() ).arg( QApplication::applicationName() );
201 QDir aDestDir(aDestPath);
202 QStringList aDestFiles = aDestDir.entryList(aFilter, QDir::Files);
203 foreach (QString aMacrosPath, getEmbeddedMacrosList()) {
204 QString aMacrosName = QFileInfo(aMacrosPath).fileName();
205 if (aDestFiles.contains(aMacrosName)) {
206 aDestDir.remove(aMacrosName);
214 PVGUI_Module::~PVGUI_Module()
221 \brief Retrieve the PVSERVER CORBA engine.
222 This uses the Python wrapper provided
223 by the PVViewer code in GUI (class PVViewer_EngineWrapper).
226 PVServer_ServiceWrapper* PVGUI_Module::GetEngine()
228 return PVServer_ServiceWrapper::GetInstance();
232 \brief Create data model.
233 \return module specific data model
235 CAM_DataModel* PVGUI_Module::createDataModel()
237 return new PVGUI_DataModel( this );
241 \brief Get the ParaView application singleton.
243 pqPVApplicationCore* PVGUI_Module::GetPVApplication()
245 return PVViewer_Core::GetPVApplication();
249 \brief Initialize module. Creates menus, prepares context menu, etc.
250 \param app SALOME GUI application instance
252 void PVGUI_Module::initialize( CAM_Application* app )
254 LightApp_Module::initialize( app );
256 // Uncomment to debug ParaView initialization
257 // "aa" used instead of "i" as GDB doesn't like "i" variables :)
265 LightApp_Application* anApp = getApp();
266 SUIT_Desktop* aDesktop = anApp->desktop();
268 // Remember current state of desktop toolbars
269 QList<QToolBar*> foreignToolbars = aDesktop->findChildren<QToolBar*>();
271 // Initialize ParaView client and associated behaviors
272 // and connect to externally launched pvserver
273 PVViewer_Core::ParaviewInitApp(aDesktop, anApp->logWindow());
274 myGuiElements = PVViewer_GUIElements::GetInstance(aDesktop);
276 // [ABN]: careful with the order of the GUI element creation, the loading of the configuration
277 // and the connection to the server. This order is very sensitive if one wants to make
278 // sure all menus, etc ... are correctly populated.
279 // Reference points are: ParaViewMainWindow.cxx and branded_paraview_initializer.cxx.in
286 PVViewer_Core::ParaviewInitBehaviors(true, aDesktop);
288 QList<QDockWidget*> activeDocks = aDesktop->findChildren<QDockWidget*>();
289 QList<QMenu*> activeMenus = aDesktop->findChildren<QMenu*>();
291 // Setup quick-launch shortcuts.
292 QShortcut *ctrlSpace = new QShortcut(Qt::CTRL + Qt::Key_Space, aDesktop);
293 QObject::connect(ctrlSpace, SIGNAL(activated()),
294 pqApplicationCore::instance(), SLOT(quickLaunch()));
296 // Find Plugin Dock Widgets
297 QList<QDockWidget*> currentDocks = aDesktop->findChildren<QDockWidget*>();
298 QList<QDockWidget*>::iterator i;
299 for (i = currentDocks.begin(); i != currentDocks.end(); ++i) {
300 if(!activeDocks.contains(*i)) {
301 myDockWidgets[*i] = false; // hidden by default
307 // [ABN] TODO: fix this - triggers a SEGFAULT at deactivation() time.
308 // QList<QMenu*> currentMenus = aDesktop->findChildren<QMenu*>();
309 // QList<QMenu*>::iterator im;
310 // for (im = currentMenus.begin(); im != currentMenus.end(); ++im) {
311 // if(!activeMenus.contains(*im)) {
312 // QString s = (*im)->title();
313 // std::cout << " MENU "<< s.toStdString() << std::endl;
314 // myMenus.append(*im);
318 // Connect after toolbar creation, etc ... as some activations of the toolbars is triggered
319 // by the ServerConnection event:
320 const QString configPath(PVViewer_ViewManager::GetPVConfigPath());
321 PVViewer_Core::ParaviewLoadConfigurations(configPath, true);
322 PVViewer_ViewManager::ConnectToExternalPVServer(aDesktop);
325 // Find created toolbars
326 QCoreApplication::processEvents();
328 // process PVViewer toolbars (might be added by PVViewer created BEFORE activating ParaVis)
329 QList<QToolBar*> pvToolbars = myGuiElements->getToolbars();
330 foreach(QToolBar* aBar, pvToolbars) {
331 if (!myToolbars.contains(aBar)) {
332 myToolbars[aBar] = true;
333 myToolbarBreaks[aBar] = false;
334 aBar->setVisible(false);
335 aBar->toggleViewAction()->setVisible(false);
339 // process other toolbars (possibly added by Paraview)
340 QList<QToolBar*> allToolbars = aDesktop->findChildren<QToolBar*>();
341 foreach(QToolBar* aBar, allToolbars) {
342 if (!foreignToolbars.contains(aBar) && !myToolbars.contains(aBar)) {
343 myToolbars[aBar] = true;
344 myToolbarBreaks[aBar] = false;
345 aBar->setVisible(false);
346 aBar->toggleViewAction()->setVisible(false);
352 SUIT_ResourceMgr* aResourceMgr = SUIT_Session::session()->resourceMgr();
353 bool isStop = aResourceMgr->booleanValue( PARAVIS_MODULE_NAME, "stop_trace", false );
356 // Start a timer to schedule asap:
358 myInitTimer = new QTimer(aDesktop);
359 QObject::connect(myInitTimer, SIGNAL(timeout()), this, SLOT(onInitTimer()) );
360 myInitTimer->setSingleShot(true);
361 myInitTimer->start(0);
364 this->VTKConnect = vtkEventQtSlotConnect::New();
366 vtkProcessModule* pm = vtkProcessModule::GetProcessModule();
368 vtkPVSession* pvs = dynamic_cast<vtkPVSession*>(pm->GetSession());
370 vtkPVProgressHandler* ph = pvs->GetProgressHandler();
372 this->VTKConnect->Connect(ph, vtkCommand::StartEvent,
373 this, SLOT(onStartProgress()));
374 this->VTKConnect->Connect(ph, vtkCommand::EndEvent,
375 this, SLOT(onEndProgress()));
379 connect( application(), SIGNAL( appClosed() ), this, SLOT( onStopTrace() ) );
383 * \brief Slot called when the progress bar starts.
385 void PVGUI_Module::onStartProgress()
387 // VSR 19/03/2015, issue 0023025
388 // next line is commented: it is bad idea to show wait cursor on ANY vtk event
389 // moreover, it does not work when running pvserver with --multi-client mode
390 //QApplication::setOverrideCursor(Qt::WaitCursor);
394 * \brief Slot called when the progress bar is done.
396 void PVGUI_Module::onEndProgress()
398 // VSR 19/03/2015, issue 0023025
399 // next line is commented: it is bad idea to show wait cursor on ANY vtk event
400 // moreover, it does not work when running pvserver with --multi-client mode
401 //QApplication::restoreOverrideCursor();
404 void PVGUI_Module::onDataRepresentationUpdated() {
405 LightApp_Study* activeStudy = dynamic_cast<LightApp_Study*>(application()->activeStudy());
406 if(!activeStudy) return;
408 activeStudy->Modified();
412 \brief Initialisation timer event - Starts up the Python trace
414 void PVGUI_Module::onInitTimer()
420 \brief Get list of embedded macros files
422 QStringList PVGUI_Module::getEmbeddedMacrosList()
424 QString aRootDir = getenv("PARAVIS_ROOT_DIR");
426 QString aSourcePath = aRootDir + "/bin/salome/Macro";
431 QDir aSourceDir(aSourcePath);
432 QStringList aSourceFiles = aSourceDir.entryList(aFilter, QDir::Files);
433 QStringList aFullPathSourceFiles;
434 foreach (QString aMacrosName, aSourceFiles) {
435 aFullPathSourceFiles << aSourceDir.absoluteFilePath(aMacrosName);
437 return aFullPathSourceFiles;
441 \brief Update the list of embedded macros
443 void PVGUI_Module::updateMacros()
445 pqPythonManager* aPythonManager = pqPVApplicationCore::instance()->pythonManager();
446 if(!aPythonManager) {
450 foreach (QString aStr, getEmbeddedMacrosList()) {
451 aPythonManager->addMacro(aStr);
457 \brief Get list of compliant dockable GUI elements
458 \param m map to be filled in ("type":"default_position")
460 void PVGUI_Module::windows( QMap<int, int>& m ) const
462 m.insert( LightApp_Application::WT_ObjectBrowser, Qt::LeftDockWidgetArea );
463 #ifndef DISABLE_PYCONSOLE
464 m.insert( LightApp_Application::WT_PyConsole, Qt::BottomDockWidgetArea );
466 // ParaView diagnostic output redirected here
467 m.insert( LightApp_Application::WT_LogWindow, Qt::BottomDockWidgetArea );
471 \brief Shows (toShow = true) or hides ParaView view window
473 void PVGUI_Module::showView( bool toShow )
475 // VSR: TODO: all below is not needed, if we use standard approach
476 // that consists in implementing viewManagers() function properly
477 // This should be done after we decide what to do with Log window.
478 LightApp_Application* anApp = getApp();
479 PVViewer_ViewManager* viewMgr =
480 dynamic_cast<PVViewer_ViewManager*>( anApp->getViewManager( PVViewer_Viewer::Type(), false ) );
482 viewMgr = new PVViewer_ViewManager( anApp->activeStudy(), anApp->desktop(), anApp->logWindow() );
483 anApp->addViewManager( viewMgr );
484 connect( viewMgr, SIGNAL( lastViewClosed( SUIT_ViewManager* ) ),
485 anApp, SLOT( onCloseView( SUIT_ViewManager* ) ) );
488 PVViewer_ViewWindow* pvWnd = dynamic_cast<PVViewer_ViewWindow*>( viewMgr->getActiveView() );
490 pvWnd = dynamic_cast<PVViewer_ViewWindow*>( viewMgr->createViewWindow() );
491 // this also connects to the pvserver and instantiates relevant PV behaviors
494 pvWnd->setVisible( toShow );
495 if ( toShow ) pvWnd->setFocus();
499 \brief Slot to show help for proxy.
501 void PVGUI_Module::showHelpForProxy( const QString& groupname, const QString& proxyname )
503 pqHelpReaction::showProxyHelp(groupname, proxyname);
507 \brief Slot to show the waiting state.
509 void PVGUI_Module::onPreAccept()
511 getApp()->desktop()->statusBar()->showMessage(tr("STB_PREACCEPT"));
512 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
516 \brief Slot to show the ready state.
518 void PVGUI_Module::onPostAccept()
520 getApp()->desktop()->statusBar()->showMessage(tr("STB_POSTACCEPT"), 2000);
521 QTimer::singleShot(0, this, SLOT(endWaitCursor()));
525 \brief Slot to switch off wait cursor.
527 void PVGUI_Module::endWaitCursor()
529 QApplication::restoreOverrideCursor();
531 #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
533 \brief Handler method for the output of messages.
535 static void ParavisMessageOutput(QtMsgType type, const char *msg)
540 vtkOutputWindow::GetInstance()->DisplayText(msg);
543 vtkOutputWindow::GetInstance()->DisplayErrorText(msg);
546 vtkOutputWindow::GetInstance()->DisplayErrorText(msg);
549 vtkOutputWindow::GetInstance()->DisplayErrorText(msg);
555 \brief Handler method for the output of messages.
557 static void ParavisMessageOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg)
562 vtkOutputWindow::GetInstance()->DisplayText(msg.toLatin1().constData());
565 vtkOutputWindow::GetInstance()->DisplayErrorText(msg.toLatin1().constData());
568 vtkOutputWindow::GetInstance()->DisplayErrorText(msg.toLatin1().constData());
571 vtkOutputWindow::GetInstance()->DisplayErrorText(msg.toLatin1().constData());
577 \brief Activate module.
578 \param study current study
579 \return \c true if activaion is done successfully or 0 to prevent
582 bool PVGUI_Module::activateModule( SUIT_Study* study )
584 #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
585 myOldMsgHandler = qInstallMsgHandler(ParavisMessageOutput);
587 myOldMsgHandler = qInstallMessageHandler(ParavisMessageOutput);
589 SUIT_ExceptionHandler::addCleanUpRoutine( paravisCleanUp );
591 storeCommonWindowsState();
593 bool isDone = LightApp_Module::activateModule( study );
594 if ( !isDone ) return false;
597 if ( mySourcesMenuId != -1 ) menuMgr()->show(mySourcesMenuId);
598 if ( myFiltersMenuId != -1 ) menuMgr()->show(myFiltersMenuId);
599 if ( myMacrosMenuId != -1 ) menuMgr()->show(myMacrosMenuId);
600 if ( myCatalystMenuId != -1 ) menuMgr()->show(myCatalystMenuId);
602 // Update the various menus with the content pre-loaded in myGuiElements
603 // QMenu* srcMenu = menuMgr()->findMenu( mySourcesMenuId );
604 // myGuiElements->updateSourcesMenu(srcMenu);
605 // QMenu* filtMenu = menuMgr()->findMenu( myFiltersMenuId );
606 // myGuiElements->updateFiltersMenu(filtMenu);
607 // QMenu* macMenu = menuMgr()->findMenu( myMacrosMenuId );
608 // myGuiElements->updateMacrosMenu(macMenu);
610 setMenuShown( true );
611 setToolShown( true );
613 restoreDockWidgetsState();
615 QMenu* aMenu = menuMgr()->findMenu( myRecentMenuId );
617 QList<QAction*> anActns = aMenu->actions();
618 for (int i = 0; i < anActns.size(); ++i) {
619 QAction* a = anActns.at(i);
625 QList<QMenu*>::iterator it;
626 for (it = myMenus.begin(); it != myMenus.end(); ++it) {
627 QAction* a = (*it)->menuAction();
632 if ( myRecentMenuId != -1 ) menuMgr()->show(myRecentMenuId);
634 // VSR 18/10/2018 - 0023170: Workaround to re-select current index after module activation
635 QItemSelectionModel* selection_model = myGuiElements->getPipelineBrowserWidget()->getSelectionModel();
636 QModelIndex idx = selection_model->currentIndex();
637 selection_model->clearCurrentIndex();
638 selection_model->setCurrentIndex(idx, QItemSelectionModel::ClearAndSelect);
645 \brief Deactivate module.
646 \param study current study
647 \return \c true if deactivaion is done successfully or 0 to prevent
648 deactivation on error
650 bool PVGUI_Module::deactivateModule( SUIT_Study* study )
652 MESSAGE("PARAVIS deactivation ...")
654 QMenu* aMenu = menuMgr()->findMenu( myRecentMenuId );
656 QList<QAction*> anActns = aMenu->actions();
657 for (int i = 0; i < anActns.size(); ++i) {
658 QAction* a = anActns.at(i);
660 a->setVisible(false);
664 QList<QMenu*>::iterator it;
665 for (it = myMenus.begin(); it != myMenus.end(); ++it) {
666 QAction* a = (*it)->menuAction();
668 a->setVisible(false);
671 QList<QDockWidget*> aStreamingViews = application()->desktop()->findChildren<QDockWidget*>("pqStreamingControls");
672 foreach(QDockWidget* aView, aStreamingViews) {
673 if (!myDockWidgets.contains(aView))
674 myDockWidgets[aView] = aView->isVisible();
677 /*if (pqImplementation::helpWindow) {
678 pqImplementation::helpWindow->hide();
681 menuMgr()->hide(myRecentMenuId);
682 menuMgr()->hide(mySourcesMenuId);
683 menuMgr()->hide(myFiltersMenuId);
684 menuMgr()->hide(myMacrosMenuId);
685 menuMgr()->hide(myCatalystMenuId);
686 setMenuShown( false );
687 setToolShown( false );
689 saveDockWidgetsState();
691 SUIT_ExceptionHandler::removeCleanUpRoutine( paravisCleanUp );
694 #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
695 qInstallMsgHandler(myOldMsgHandler);
697 qInstallMessageHandler(myOldMsgHandler);
699 restoreCommonWindowsState();
701 return LightApp_Module::deactivateModule( study );
706 \brief Called when application is closed.
708 Process finalize application functionality from ParaView in order to save server settings
709 and nullify application pointer if the application is being closed.
711 \param theApp application
713 void PVGUI_Module::onApplicationClosed( SUIT_Application* theApp )
715 PVViewer_Core::ParaviewCleanup();
716 CAM_Module::onApplicationClosed(theApp);
720 \brief Called when study is closed.
722 Removes data model from the \a study.
724 \param study study being closed
726 void PVGUI_Module::studyClosed(SUIT_Study* study)
728 showView(false); // VSR: this seems to be not needed (all views are automatically closed)
729 clearParaviewState();
733 LightApp_Module::studyClosed(study);
737 \brief Open file of format supported by ParaView
739 void PVGUI_Module::openFile( const char* theName )
743 pqLoadDataReaction::loadData( aFiles );
747 \brief Starts Python trace.
749 Start trace invoking the newly introduced C++ API (PV 4.2)
750 (inspired from pqTraceReaction::start())
752 void PVGUI_Module::startTrace()
754 vtkSMSessionProxyManager* pxm = pqActiveObjects::instance().activeServer()->proxyManager();
756 vtkSmartPointer<vtkSMProxy> proxy;
757 proxy.TakeReference( pxm->NewProxy( "pythontracing", "PythonTraceOptions" ) );
759 vtkNew<vtkSMParaViewPipelineController> controller;
760 controller->InitializeProxy( proxy );
762 vtkSMTrace* trace = vtkSMTrace::StartTrace();
764 // Set manually the properties entered via the dialog box poping-up when requiring
765 // a trace start in PV4.2 (trace options)
766 SUIT_ResourceMgr* aResourceMgr = SUIT_Session::session()->resourceMgr();
767 int type = aResourceMgr->integerValue( PARAVIS_MODULE_NAME, "tracestate_type", 2 );
768 trace->SetPropertiesToTraceOnCreate( type );
769 trace->SetFullyTraceSupplementalProxies( false );
774 \brief Stops Python trace.
776 void PVGUI_Module::stopTrace()
778 vtkSMTrace::StopTrace();
782 \brief Execute a Python script.
784 void PVGUI_Module::executeScript( const char* script )
787 pqPythonManager* manager = qobject_cast<pqPythonManager*>(
788 pqApplicationCore::instance()->manager( "PYTHON_MANAGER" ) );
790 pqPythonDialog* pyDiag = manager->pythonShellDialog();
792 pyDiag->runString(script);
799 // * Debug function printing out the given interpreter's execution context
801 //void printInterpContext(PyInterp_Interp * interp )
803 // // Extract __smtraceString from interpreter's context
804 // const PyObject* ctxt = interp->getExecutionContext();
806 // PyObject* lst = PyDict_Keys((PyObject *)ctxt);
807 // Py_ssize_t siz = PyList_GET_SIZE(lst);
808 // for (Py_ssize_t i = 0; i < siz; i++)
810 // PyObject * elem = PyList_GetItem(lst, i);
811 // if (PyString_Check(elem))
813 // std::cout << "At pos:" << i << ", " << Py_EncodeLocale(PyUnicode_AS_UNICODE(elem), NULL) << std::endl;
816 // std::cout << "At pos:" << i << ", not a string!" << std::endl;
822 \brief Returns trace string
824 QString PVGUI_Module::getTraceString()
826 QString traceString = "";
828 static const QString replaceStr( "paraview.simple" );
829 std::stringstream nl;
830 nl << std::endl; // surely there is some Qt trick to do that in a portable way??
831 QString end_line( nl.str().c_str() );
833 vtkSMTrace* tracer = vtkSMTrace::GetActiveTracer();
835 traceString = tracer->GetCurrentTrace();
836 // 'import pvsimple' is necessary to fix the first call to DisableFirstRenderCamera in the paraview trace
837 // 'ShowParaviewView()' ensure there is an opened viewing window (otherwise SEGFAULT!)
838 traceString = "import pvsimple" + end_line +
839 "pvsimple.ShowParaviewView()" + end_line + traceString;
841 // Replace import "paraview.simple" by "pvsimple"
842 if ( !traceString.isEmpty() ) {
843 int aPos = traceString.indexOf( replaceStr );
844 while ( aPos != -1 ) {
845 traceString = traceString.replace( aPos, replaceStr.length(), "pvsimple" );
846 aPos = traceString.indexOf( replaceStr, aPos );
851 // Save camera position to, which is no longer output by the tracer ...
853 vtkPythonScopeGilEnsurer psge;
854 PyObject * mods(PySys_GetObject(const_cast<char*>("modules")));
855 PyObject * trace_mod(PyDict_GetItemString(mods, "paraview.smtrace")); // module was already (really) imported by vtkSMTrace
856 if (trace_mod && trace_mod != Py_None && PyModule_Check(trace_mod)) {
857 vtkSmartPyObject save_cam(PyObject_GetAttrString(trace_mod, const_cast<char*>("SaveCameras")));
858 vtkSmartPyObject camera_trace(PyObject_CallMethod(save_cam, const_cast<char*>("get_trace"), NULL));
859 // Convert to a single string
860 vtkSmartPyObject ret(PyUnicode_FromUnicode(Py_DecodeLocale(end_line.toStdString().c_str(), NULL), end_line.size()));
861 vtkSmartPyObject final_string(PyObject_CallMethod(ret, const_cast<char*>("join"),
862 const_cast<char*>("O"), (PyObject*)camera_trace));
863 if (PyUnicode_CheckExact(final_string))
865 QString camera_qs(Py_EncodeLocale(PyUnicode_AS_UNICODE(final_string.GetPointer()), NULL)); // deep copy
866 traceString = traceString + end_line + end_line + QString("#### saving camera placements for all active views")
867 + end_line + end_line + camera_qs + end_line;
876 \brief Saves trace string to disk file
878 void PVGUI_Module::saveTrace( const char* theName )
880 QFile file( theName );
881 if ( !file.open( QIODevice::WriteOnly | QIODevice::Text ) ) {
882 MESSAGE( "Could not open file:" << theName );
885 QTextStream out( &file );
886 out << getTraceString();
891 \brief Saves ParaView state to a disk file
893 void PVGUI_Module::saveParaviewState( const QString& theFileName )
895 pqApplicationCore::instance()->saveState( theFileName.toStdString().c_str() );
899 \brief Delete all objects for Paraview Pipeline Browser
901 void PVGUI_Module::clearParaviewState()
903 QAction* deleteAllAction = action( DeleteAllId );
904 if ( deleteAllAction ) {
905 deleteAllAction->activate( QAction::Trigger );
910 \brief Restores ParaView state from a disk file
912 void PVGUI_Module::loadParaviewState( const QString& theFileName )
914 pqApplicationCore::instance()->loadState( theFileName.toStdString().c_str(), getActiveServer() );
918 \brief Returns current active ParaView server
920 pqServer* PVGUI_Module::getActiveServer()
922 return pqApplicationCore::instance()->getActiveServer();
927 \brief Creates PARAVIS preferences panel.
929 void PVGUI_Module::createPreferences()
931 QList<QVariant> aIndices;
932 QStringList aStrings;
934 // Paraview settings tab
935 int aParaViewSettingsTab = addPreference( tr( "TIT_PVIEWSETTINGS" ) );
937 setPreferenceProperty(aParaViewSettingsTab, "stretch", false );
938 int aPanel = addPreference( QString(), aParaViewSettingsTab,
939 LightApp_Preferences::UserDefined, PARAVIS_MODULE_NAME, "" );
941 setPreferenceProperty( aPanel, "content", (qint64)( new PVGUI_ParaViewSettingsPane( 0, getApp() ) ) );
943 // Paravis settings tab
944 int aParaVisSettingsTab = addPreference( tr( "TIT_PVISSETTINGS" ) );
946 addPreference( tr( "PREF_NO_EXT_PVSERVER" ), aParaVisSettingsTab,
947 LightApp_Preferences::Bool, PARAVIS_MODULE_NAME, "no_ext_pv_server" );
949 int aSaveType = addPreference( tr( "PREF_SAVE_TYPE_LBL" ), aParaVisSettingsTab,
950 LightApp_Preferences::Selector,
951 PARAVIS_MODULE_NAME, "savestate_type" );
955 aIndices << 0 << 1 << 2;
956 aStrings << tr("PREF_SAVE_TYPE_0") << tr("PREF_SAVE_TYPE_1") << tr("PREF_SAVE_TYPE_2");
957 setPreferenceProperty( aSaveType, "strings", aStrings );
958 setPreferenceProperty( aSaveType, "indexes", aIndices );
960 // ... "Language" group <<start>>
961 int traceGroup = addPreference( tr( "PREF_GROUP_TRACE" ), aParaVisSettingsTab );
963 int stopTrace = addPreference( tr( "PREF_STOP_TRACE" ), traceGroup,
964 LightApp_Preferences::Bool, PARAVIS_MODULE_NAME, "stop_trace" );
965 setPreferenceProperty( stopTrace, "restart", true );
967 int aTraceType = addPreference( tr( "PREF_TRACE_TYPE_LBL" ), traceGroup,
968 LightApp_Preferences::Selector,
969 PARAVIS_MODULE_NAME, "tracestate_type" );
972 aIndices << 0 << 1 << 2;
973 aStrings << tr("PREF_TRACE_TYPE_0") << tr("PREF_TRACE_TYPE_1") << tr("PREF_TRACE_TYPE_2");
974 setPreferenceProperty( aTraceType, "strings", aStrings );
975 setPreferenceProperty( aTraceType, "indexes", aIndices );
976 setPreferenceProperty( aTraceType, "restart", true );
980 \brief. Show ParaView python trace.
982 void PVGUI_Module::onShowTrace()
984 if (!myTraceWindow) {
985 myTraceWindow = new pqPythonScriptEditor(getApp()->desktop());
987 myTraceWindow->setText(getTraceString());
988 myTraceWindow->show();
989 myTraceWindow->raise();
990 myTraceWindow->activateWindow();
995 \brief. Re-initialize ParaView python trace.
997 void PVGUI_Module::onRestartTrace()
1004 \brief. Close ParaView python trace.
1006 void PVGUI_Module::onStopTrace()
1011 \brief Called when view manager is added
1013 void PVGUI_Module::onViewManagerAdded( SUIT_ViewManager* vm )
1015 if ( PVViewer_ViewManager* pvvm = dynamic_cast<PVViewer_ViewManager*>( vm ) ) {
1016 connect( pvvm, SIGNAL( viewCreated( SUIT_ViewWindow* ) ),
1017 this, SLOT( onPVViewCreated( SUIT_ViewWindow* ) ) );
1018 connect( pvvm, SIGNAL( deleteView( SUIT_ViewWindow* ) ),
1019 this, SLOT( onPVViewDelete( SUIT_ViewWindow* ) ) );
1024 \brief Called when view manager is removed
1026 void PVGUI_Module::onViewManagerRemoved( SUIT_ViewManager* vm )
1028 if ( PVViewer_ViewManager* pvvm = dynamic_cast<PVViewer_ViewManager*>( vm ) )
1029 disconnect( pvvm, SIGNAL( viewCreated( SUIT_ViewWindow* ) ),
1030 this, SLOT( onPVViewCreated( SUIT_ViewWindow* ) ) );
1034 \brief Show toolbars at \a vw PV view window creating when PARAVIS is active.
1036 void PVGUI_Module::onPVViewCreated( SUIT_ViewWindow* vw )
1038 myGuiElements->setToolBarVisible( true );
1039 restoreDockWidgetsState();
1043 \brief Save toolbars state at \a view view closing.
1045 void PVGUI_Module::onPVViewDelete( SUIT_ViewWindow* view )
1047 if ( dynamic_cast<PVViewer_ViewWindow*>( view ) )
1048 saveDockWidgetsState( false );
1052 \fn CAM_Module* createModule();
1053 \brief Export module instance (factory function).
1054 \return new created instance of the module
1058 #define PVGUI_EXPORT __declspec(dllexport)
1060 #define PVGUI_EXPORT
1066 PVGUI_EXPORT CAM_Module* createModule() {
1067 return new PVGUI_Module();
1070 PVGUI_EXPORT char* getModuleVersion() {
1071 return (char*)PARAVIS_VERSION_STR;