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>
128 //----------------------------------------------------------------------------
129 PVGUI_Module* ParavisModule = 0;
133 This is the doxygen documentation of the ParaVis module.
134 If you are looking for general information about the structure of the module, you should
135 take a look at the <a href="../index.html">Sphinx documentation</a> first.
137 The integration of ParaView into SALOME is split in two parts:
138 \li the PVViewer in the GUI module (folder *src/PVViewer*)
139 \li the ParaVis module itself (the pages you are currently browsing)
144 \brief Implementation
145 SALOME module wrapping ParaView GUI.
149 \brief Clean up function
151 Used to stop ParaView progress events when
152 exception is caught by global exception handler.
154 void paravisCleanUp()
156 if ( pqApplicationCore::instance() ) {
157 pqServer* s = pqApplicationCore::instance()->getActiveServer();
158 if ( s ) s->session()->GetProgressHandler()->CleanupPendingProgress();
163 \brief Constructor. Sets the default name for the module.
165 PVGUI_Module::PVGUI_Module()
166 : LightApp_Module( PARAVIS_MODULE_NAME ),
167 mySourcesMenuId( -1 ),
168 myFiltersMenuId( -1 ),
177 Q_INIT_RESOURCE( PVGUI );
179 ParavisModule = this;
181 // Clear old copies of embedded macros files
182 QString aDestPath = QString( "%1/.config/%2/Macros" ).arg( QDir::homePath() ).arg( QApplication::applicationName() );
186 QDir aDestDir(aDestPath);
187 QStringList aDestFiles = aDestDir.entryList(aFilter, QDir::Files);
188 foreach (QString aMacrosPath, getEmbeddedMacrosList()) {
189 QString aMacrosName = QFileInfo(aMacrosPath).fileName();
190 if (aDestFiles.contains(aMacrosName)) {
191 aDestDir.remove(aMacrosName);
199 PVGUI_Module::~PVGUI_Module()
206 \brief Retrieve the PVSERVER CORBA engine.
207 This uses the Python wrapper provided
208 by the PVViewer code in GUI (class PVViewer_EngineWrapper).
211 PVServer_ServiceWrapper* PVGUI_Module::GetEngine()
213 return PVServer_ServiceWrapper::GetInstance();
217 \brief Create data model.
218 \return module specific data model
220 CAM_DataModel* PVGUI_Module::createDataModel()
222 return new PVGUI_DataModel( this );
226 \brief Get the ParaView application singleton.
228 pqPVApplicationCore* PVGUI_Module::GetPVApplication()
230 return PVViewer_Core::GetPVApplication();
234 \brief Initialize module. Creates menus, prepares context menu, etc.
235 \param app SALOME GUI application instance
237 void PVGUI_Module::initialize( CAM_Application* app )
239 LightApp_Module::initialize( app );
241 // Uncomment to debug ParaView initialization
242 // "aa" used instead of "i" as GDB doesn't like "i" variables :)
250 LightApp_Application* anApp = getApp();
251 SUIT_Desktop* aDesktop = anApp->desktop();
253 // Remember current state of desktop toolbars
254 QList<QToolBar*> foreignToolbars = aDesktop->findChildren<QToolBar*>();
256 // Initialize ParaView client and associated behaviors
257 // and connect to externally launched pvserver
258 PVViewer_Core::ParaviewInitApp(aDesktop, anApp->logWindow());
259 myGuiElements = PVViewer_GUIElements::GetInstance(aDesktop);
261 // [ABN]: careful with the order of the GUI element creation, the loading of the configuration
262 // and the connection to the server. This order is very sensitive if one wants to make
263 // sure all menus, etc ... are correctly populated.
264 // Reference points are: ParaViewMainWindow.cxx and branded_paraview_initializer.cxx.in
271 PVViewer_Core::ParaviewInitBehaviors(true, aDesktop);
273 QList<QDockWidget*> activeDocks = aDesktop->findChildren<QDockWidget*>();
274 QList<QMenu*> activeMenus = aDesktop->findChildren<QMenu*>();
276 // Setup quick-launch shortcuts.
277 QShortcut *ctrlSpace = new QShortcut(Qt::CTRL + Qt::Key_Space, aDesktop);
278 QObject::connect(ctrlSpace, SIGNAL(activated()),
279 pqApplicationCore::instance(), SLOT(quickLaunch()));
281 // Find Plugin Dock Widgets
282 QList<QDockWidget*> currentDocks = aDesktop->findChildren<QDockWidget*>();
283 QList<QDockWidget*>::iterator i;
284 for (i = currentDocks.begin(); i != currentDocks.end(); ++i) {
285 if(!activeDocks.contains(*i)) {
286 myDockWidgets[*i] = false; // hidden by default
292 // [ABN] TODO: fix this - triggers a SEGFAULT at deactivation() time.
293 // QList<QMenu*> currentMenus = aDesktop->findChildren<QMenu*>();
294 // QList<QMenu*>::iterator im;
295 // for (im = currentMenus.begin(); im != currentMenus.end(); ++im) {
296 // if(!activeMenus.contains(*im)) {
297 // QString s = (*im)->title();
298 // std::cout << " MENU "<< s.toStdString() << std::endl;
299 // myMenus.append(*im);
303 // Connect after toolbar creation, etc ... as some activations of the toolbars is triggered
304 // by the ServerConnection event:
305 const QString configPath(PVViewer_ViewManager::GetPVConfigPath());
306 PVViewer_Core::ParaviewLoadConfigurations(configPath, true);
307 PVViewer_ViewManager::ConnectToExternalPVServer(aDesktop);
310 // Find created toolbars
311 QCoreApplication::processEvents();
313 // process PVViewer toolbars (might be added by PVViewer created BEFORE activating ParaVis)
314 QList<QToolBar*> pvToolbars = myGuiElements->getToolbars();
315 foreach(QToolBar* aBar, pvToolbars) {
316 if (!myToolbars.contains(aBar)) {
317 myToolbars[aBar] = true;
318 myToolbarBreaks[aBar] = false;
319 aBar->setVisible(false);
320 aBar->toggleViewAction()->setVisible(false);
324 // process other toolbars (possibly added by Paraview)
325 QList<QToolBar*> allToolbars = aDesktop->findChildren<QToolBar*>();
326 foreach(QToolBar* aBar, allToolbars) {
327 if (!foreignToolbars.contains(aBar) && !myToolbars.contains(aBar)) {
328 myToolbars[aBar] = true;
329 myToolbarBreaks[aBar] = false;
330 aBar->setVisible(false);
331 aBar->toggleViewAction()->setVisible(false);
337 SUIT_ResourceMgr* aResourceMgr = SUIT_Session::session()->resourceMgr();
338 bool isStop = aResourceMgr->booleanValue( PARAVIS_MODULE_NAME, "stop_trace", false );
341 // Start a timer to schedule asap:
343 myInitTimer = new QTimer(aDesktop);
344 QObject::connect(myInitTimer, SIGNAL(timeout()), this, SLOT(onInitTimer()) );
345 myInitTimer->setSingleShot(true);
346 myInitTimer->start(0);
349 this->VTKConnect = vtkEventQtSlotConnect::New();
351 vtkProcessModule* pm = vtkProcessModule::GetProcessModule();
353 vtkPVSession* pvs = dynamic_cast<vtkPVSession*>(pm->GetSession());
355 vtkPVProgressHandler* ph = pvs->GetProgressHandler();
357 this->VTKConnect->Connect(ph, vtkCommand::StartEvent,
358 this, SLOT(onStartProgress()));
359 this->VTKConnect->Connect(ph, vtkCommand::EndEvent,
360 this, SLOT(onEndProgress()));
364 connect( application(), SIGNAL( appClosed() ), this, SLOT( onStopTrace() ) );
368 * \brief Slot called when the progress bar starts.
370 void PVGUI_Module::onStartProgress()
372 // VSR 19/03/2015, issue 0023025
373 // next line is commented: it is bad idea to show wait cursor on ANY vtk event
374 // moreover, it does not work when running pvserver with --multi-client mode
375 //QApplication::setOverrideCursor(Qt::WaitCursor);
379 * \brief Slot called when the progress bar is done.
381 void PVGUI_Module::onEndProgress()
383 // VSR 19/03/2015, issue 0023025
384 // next line is commented: it is bad idea to show wait cursor on ANY vtk event
385 // moreover, it does not work when running pvserver with --multi-client mode
386 //QApplication::restoreOverrideCursor();
389 void PVGUI_Module::onDataRepresentationUpdated() {
390 LightApp_Study* activeStudy = dynamic_cast<LightApp_Study*>(application()->activeStudy());
391 if(!activeStudy) return;
393 activeStudy->Modified();
397 \brief Initialisation timer event - Starts up the Python trace
399 void PVGUI_Module::onInitTimer()
405 \brief Get list of embedded macros files
407 QStringList PVGUI_Module::getEmbeddedMacrosList()
409 QString aRootDir = getenv("PARAVIS_ROOT_DIR");
411 QString aSourcePath = aRootDir + "/bin/salome/Macro";
416 QDir aSourceDir(aSourcePath);
417 QStringList aSourceFiles = aSourceDir.entryList(aFilter, QDir::Files);
418 QStringList aFullPathSourceFiles;
419 foreach (QString aMacrosName, aSourceFiles) {
420 aFullPathSourceFiles << aSourceDir.absoluteFilePath(aMacrosName);
422 return aFullPathSourceFiles;
426 \brief Update the list of embedded macros
428 void PVGUI_Module::updateMacros()
430 pqPythonManager* aPythonManager = pqPVApplicationCore::instance()->pythonManager();
431 if(!aPythonManager) {
435 foreach (QString aStr, getEmbeddedMacrosList()) {
436 aPythonManager->addMacro(aStr);
442 \brief Get list of compliant dockable GUI elements
443 \param m map to be filled in ("type":"default_position")
445 void PVGUI_Module::windows( QMap<int, int>& m ) const
447 m.insert( LightApp_Application::WT_ObjectBrowser, Qt::LeftDockWidgetArea );
448 #ifndef DISABLE_PYCONSOLE
449 m.insert( LightApp_Application::WT_PyConsole, Qt::BottomDockWidgetArea );
451 // ParaView diagnostic output redirected here
452 m.insert( LightApp_Application::WT_LogWindow, Qt::BottomDockWidgetArea );
456 \brief Shows (toShow = true) or hides ParaView view window
458 void PVGUI_Module::showView( bool toShow )
460 // VSR: TODO: all below is not needed, if we use standard approach
461 // that consists in implementing viewManagers() function properly
462 // This should be done after we decide what to do with Log window.
463 LightApp_Application* anApp = getApp();
464 PVViewer_ViewManager* viewMgr =
465 dynamic_cast<PVViewer_ViewManager*>( anApp->getViewManager( PVViewer_Viewer::Type(), false ) );
467 viewMgr = new PVViewer_ViewManager( anApp->activeStudy(), anApp->desktop(), anApp->logWindow() );
468 anApp->addViewManager( viewMgr );
469 connect( viewMgr, SIGNAL( lastViewClosed( SUIT_ViewManager* ) ),
470 anApp, SLOT( onCloseView( SUIT_ViewManager* ) ) );
473 PVViewer_ViewWindow* pvWnd = dynamic_cast<PVViewer_ViewWindow*>( viewMgr->getActiveView() );
475 pvWnd = dynamic_cast<PVViewer_ViewWindow*>( viewMgr->createViewWindow() );
476 // this also connects to the pvserver and instantiates relevant PV behaviors
479 pvWnd->setVisible( toShow );
480 if ( toShow ) pvWnd->setFocus();
484 \brief Slot to show help for proxy.
486 void PVGUI_Module::showHelpForProxy( const QString& groupname, const QString& proxyname )
488 pqHelpReaction::showProxyHelp(groupname, proxyname);
492 \brief Slot to show the waiting state.
494 void PVGUI_Module::onPreAccept()
496 getApp()->desktop()->statusBar()->showMessage(tr("STB_PREACCEPT"));
497 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
501 \brief Slot to show the ready state.
503 void PVGUI_Module::onPostAccept()
505 getApp()->desktop()->statusBar()->showMessage(tr("STB_POSTACCEPT"), 2000);
506 QTimer::singleShot(0, this, SLOT(endWaitCursor()));
510 \brief Slot to switch off wait cursor.
512 void PVGUI_Module::endWaitCursor()
514 QApplication::restoreOverrideCursor();
516 #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
518 \brief Handler method for the output of messages.
520 static void ParavisMessageOutput(QtMsgType type, const char *msg)
525 vtkOutputWindow::GetInstance()->DisplayText(msg);
528 vtkOutputWindow::GetInstance()->DisplayErrorText(msg);
531 vtkOutputWindow::GetInstance()->DisplayErrorText(msg);
534 vtkOutputWindow::GetInstance()->DisplayErrorText(msg);
540 \brief Handler method for the output of messages.
542 static void ParavisMessageOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg)
547 vtkOutputWindow::GetInstance()->DisplayText(msg.toLatin1().constData());
550 vtkOutputWindow::GetInstance()->DisplayErrorText(msg.toLatin1().constData());
553 vtkOutputWindow::GetInstance()->DisplayErrorText(msg.toLatin1().constData());
556 vtkOutputWindow::GetInstance()->DisplayErrorText(msg.toLatin1().constData());
562 \brief Activate module.
563 \param study current study
564 \return \c true if activaion is done successfully or 0 to prevent
567 bool PVGUI_Module::activateModule( SUIT_Study* study )
569 #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
570 myOldMsgHandler = qInstallMsgHandler(ParavisMessageOutput);
572 myOldMsgHandler = qInstallMessageHandler(ParavisMessageOutput);
574 SUIT_ExceptionHandler::addCleanUpRoutine( paravisCleanUp );
576 storeCommonWindowsState();
578 bool isDone = LightApp_Module::activateModule( study );
579 if ( !isDone ) return false;
582 if ( mySourcesMenuId != -1 ) menuMgr()->show(mySourcesMenuId);
583 if ( myFiltersMenuId != -1 ) menuMgr()->show(myFiltersMenuId);
584 if ( myMacrosMenuId != -1 ) menuMgr()->show(myMacrosMenuId);
586 // Update the various menus with the content pre-loaded in myGuiElements
587 // QMenu* srcMenu = menuMgr()->findMenu( mySourcesMenuId );
588 // myGuiElements->updateSourcesMenu(srcMenu);
589 // QMenu* filtMenu = menuMgr()->findMenu( myFiltersMenuId );
590 // myGuiElements->updateFiltersMenu(filtMenu);
591 // QMenu* macMenu = menuMgr()->findMenu( myMacrosMenuId );
592 // myGuiElements->updateMacrosMenu(macMenu);
594 setMenuShown( true );
595 setToolShown( true );
597 restoreDockWidgetsState();
599 QMenu* aMenu = menuMgr()->findMenu( myRecentMenuId );
601 QList<QAction*> anActns = aMenu->actions();
602 for (int i = 0; i < anActns.size(); ++i) {
603 QAction* a = anActns.at(i);
609 QList<QMenu*>::iterator it;
610 for (it = myMenus.begin(); it != myMenus.end(); ++it) {
611 QAction* a = (*it)->menuAction();
616 if ( myRecentMenuId != -1 ) menuMgr()->show(myRecentMenuId);
623 \brief Deactivate module.
624 \param study current study
625 \return \c true if deactivaion is done successfully or 0 to prevent
626 deactivation on error
628 bool PVGUI_Module::deactivateModule( SUIT_Study* study )
630 MESSAGE("PARAVIS deactivation ...")
632 QMenu* aMenu = menuMgr()->findMenu( myRecentMenuId );
634 QList<QAction*> anActns = aMenu->actions();
635 for (int i = 0; i < anActns.size(); ++i) {
636 QAction* a = anActns.at(i);
638 a->setVisible(false);
642 QList<QMenu*>::iterator it;
643 for (it = myMenus.begin(); it != myMenus.end(); ++it) {
644 QAction* a = (*it)->menuAction();
646 a->setVisible(false);
649 QList<QDockWidget*> aStreamingViews = application()->desktop()->findChildren<QDockWidget*>("pqStreamingControls");
650 foreach(QDockWidget* aView, aStreamingViews) {
651 if (!myDockWidgets.contains(aView))
652 myDockWidgets[aView] = aView->isVisible();
655 /*if (pqImplementation::helpWindow) {
656 pqImplementation::helpWindow->hide();
659 menuMgr()->hide(myRecentMenuId);
660 menuMgr()->hide(mySourcesMenuId);
661 menuMgr()->hide(myFiltersMenuId);
662 menuMgr()->hide(myMacrosMenuId);
663 setMenuShown( false );
664 setToolShown( false );
666 saveDockWidgetsState();
668 SUIT_ExceptionHandler::removeCleanUpRoutine( paravisCleanUp );
671 #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0)
672 qInstallMsgHandler(myOldMsgHandler);
674 qInstallMessageHandler(myOldMsgHandler);
676 restoreCommonWindowsState();
678 return LightApp_Module::deactivateModule( study );
683 \brief Called when application is closed.
685 Process finalize application functionality from ParaView in order to save server settings
686 and nullify application pointer if the application is being closed.
688 \param theApp application
690 void PVGUI_Module::onApplicationClosed( SUIT_Application* theApp )
692 PVViewer_Core::ParaviewCleanup();
693 CAM_Module::onApplicationClosed(theApp);
697 \brief Called when study is closed.
699 Removes data model from the \a study.
701 \param study study being closed
703 void PVGUI_Module::studyClosed(SUIT_Study* study)
705 showView(false); // VSR: this seems to be not needed (all views are automatically closed)
706 clearParaviewState();
710 LightApp_Module::studyClosed(study);
714 \brief Open file of format supported by ParaView
716 void PVGUI_Module::openFile( const char* theName )
720 pqLoadDataReaction::loadData( aFiles );
724 \brief Starts Python trace.
726 Start trace invoking the newly introduced C++ API (PV 4.2)
727 (inspired from pqTraceReaction::start())
729 void PVGUI_Module::startTrace()
731 vtkSMSessionProxyManager* pxm = pqActiveObjects::instance().activeServer()->proxyManager();
733 vtkSmartPointer<vtkSMProxy> proxy;
734 proxy.TakeReference( pxm->NewProxy( "pythontracing", "PythonTraceOptions" ) );
736 vtkNew<vtkSMParaViewPipelineController> controller;
737 controller->InitializeProxy( proxy );
739 vtkSMTrace* trace = vtkSMTrace::StartTrace();
741 // Set manually the properties entered via the dialog box poping-up when requiring
742 // a trace start in PV4.2 (trace options)
743 SUIT_ResourceMgr* aResourceMgr = SUIT_Session::session()->resourceMgr();
744 int type = aResourceMgr->integerValue( PARAVIS_MODULE_NAME, "tracestate_type", 2 );
745 trace->SetPropertiesToTraceOnCreate( type );
746 trace->SetFullyTraceSupplementalProxies( false );
751 \brief Stops Python trace.
753 void PVGUI_Module::stopTrace()
755 vtkSMTrace::StopTrace();
759 \brief Execute a Python script.
761 void PVGUI_Module::executeScript( const char* script )
764 pqPythonManager* manager = qobject_cast<pqPythonManager*>(
765 pqApplicationCore::instance()->manager( "PYTHON_MANAGER" ) );
767 pqPythonDialog* pyDiag = manager->pythonShellDialog();
769 pyDiag->runString(script);
776 // * Debug function printing out the given interpreter's execution context
778 //void printInterpContext(PyInterp_Interp * interp )
780 // // Extract __smtraceString from interpreter's context
781 // const PyObject* ctxt = interp->getExecutionContext();
783 // PyObject* lst = PyDict_Keys((PyObject *)ctxt);
784 // Py_ssize_t siz = PyList_GET_SIZE(lst);
785 // for (Py_ssize_t i = 0; i < siz; i++)
787 // PyObject * elem = PyList_GetItem(lst, i);
788 // if (PyString_Check(elem))
790 // std::cout << "At pos:" << i << ", " << PyString_AsString(elem) << std::endl;
793 // std::cout << "At pos:" << i << ", not a string!" << std::endl;
799 \brief Returns trace string
801 QString PVGUI_Module::getTraceString()
803 QString traceString = "";
805 static const QString replaceStr( "paraview.simple" );
806 std::stringstream nl;
807 nl << std::endl; // surely there is some Qt trick to do that in a portable way??
808 QString end_line( nl.str().c_str() );
810 vtkSMTrace* tracer = vtkSMTrace::GetActiveTracer();
812 traceString = tracer->GetCurrentTrace();
813 // 'import pvsimple' is necessary to fix the first call to DisableFirstRenderCamera in the paraview trace
814 // 'ShowParaviewView()' ensure there is an opened viewing window (otherwise SEGFAULT!)
815 traceString = "import pvsimple" + end_line +
816 "pvsimple.ShowParaviewView()" + end_line + traceString;
818 // Replace import "paraview.simple" by "pvsimple"
819 if ( !traceString.isEmpty() ) {
820 int aPos = traceString.indexOf( replaceStr );
821 while ( aPos != -1 ) {
822 traceString = traceString.replace( aPos, replaceStr.length(), "pvsimple" );
823 aPos = traceString.indexOf( replaceStr, aPos );
828 // Save camera position to, which is no longer output by the tracer ...
830 vtkPythonScopeGilEnsurer psge;
831 PyObject * mods(PySys_GetObject(const_cast<char*>("modules")));
832 PyObject * trace_mod(PyDict_GetItemString(mods, "paraview.smtrace")); // module was already (really) imported by vtkSMTrace
833 if (PyModule_Check(trace_mod)) {
834 vtkSmartPyObject save_cam(PyObject_GetAttrString(trace_mod, const_cast<char*>("SaveCameras")));
835 vtkSmartPyObject camera_trace(PyObject_CallMethod(save_cam, const_cast<char*>("get_trace"), NULL));
836 // Convert to a single string
837 vtkSmartPyObject ret(PyString_FromString(end_line.toStdString().c_str()));
838 vtkSmartPyObject final_string(PyObject_CallMethod(ret, const_cast<char*>("join"),
839 const_cast<char*>("O"), (PyObject*)camera_trace));
840 if (PyString_CheckExact(final_string))
842 QString camera_qs(PyString_AsString(final_string)); // deep copy
843 traceString = traceString + end_line + end_line + QString("#### saving camera placements for all active views")
844 + end_line + end_line + camera_qs + end_line;
853 \brief Saves trace string to disk file
855 void PVGUI_Module::saveTrace( const char* theName )
857 QFile file( theName );
858 if ( !file.open( QIODevice::WriteOnly | QIODevice::Text ) ) {
859 MESSAGE( "Could not open file:" << theName );
862 QTextStream out( &file );
863 out << getTraceString();
868 \brief Saves ParaView state to a disk file
870 void PVGUI_Module::saveParaviewState( const QString& theFileName )
872 pqApplicationCore::instance()->saveState( theFileName.toStdString().c_str() );
876 \brief Delete all objects for Paraview Pipeline Browser
878 void PVGUI_Module::clearParaviewState()
880 QAction* deleteAllAction = action( DeleteAllId );
881 if ( deleteAllAction ) {
882 deleteAllAction->activate( QAction::Trigger );
887 \brief Restores ParaView state from a disk file
889 void PVGUI_Module::loadParaviewState( const QString& theFileName )
891 pqApplicationCore::instance()->loadState( theFileName.toStdString().c_str(), getActiveServer() );
895 \brief Returns current active ParaView server
897 pqServer* PVGUI_Module::getActiveServer()
899 return pqApplicationCore::instance()->getActiveServer();
904 \brief Creates PARAVIS preferences panel.
906 void PVGUI_Module::createPreferences()
908 QList<QVariant> aIndices;
909 QStringList aStrings;
911 // Paraview settings tab
912 int aParaViewSettingsTab = addPreference( tr( "TIT_PVIEWSETTINGS" ) );
914 setPreferenceProperty(aParaViewSettingsTab, "stretch", false );
915 int aPanel = addPreference( QString(), aParaViewSettingsTab,
916 LightApp_Preferences::UserDefined, PARAVIS_MODULE_NAME, "" );
918 setPreferenceProperty( aPanel, "content", (qint64)( new PVGUI_ParaViewSettingsPane( 0, getApp() ) ) );
920 // Paravis settings tab
921 int aParaVisSettingsTab = addPreference( tr( "TIT_PVISSETTINGS" ) );
923 addPreference( tr( "PREF_NO_EXT_PVSERVER" ), aParaVisSettingsTab,
924 LightApp_Preferences::Bool, PARAVIS_MODULE_NAME, "no_ext_pv_server" );
926 int aSaveType = addPreference( tr( "PREF_SAVE_TYPE_LBL" ), aParaVisSettingsTab,
927 LightApp_Preferences::Selector,
928 PARAVIS_MODULE_NAME, "savestate_type" );
932 aIndices << 0 << 1 << 2;
933 aStrings << tr("PREF_SAVE_TYPE_0") << tr("PREF_SAVE_TYPE_1") << tr("PREF_SAVE_TYPE_2");
934 setPreferenceProperty( aSaveType, "strings", aStrings );
935 setPreferenceProperty( aSaveType, "indexes", aIndices );
937 // ... "Language" group <<start>>
938 int traceGroup = addPreference( tr( "PREF_GROUP_TRACE" ), aParaVisSettingsTab );
940 int stopTrace = addPreference( tr( "PREF_STOP_TRACE" ), traceGroup,
941 LightApp_Preferences::Bool, PARAVIS_MODULE_NAME, "stop_trace" );
942 setPreferenceProperty( stopTrace, "restart", true );
944 int aTraceType = addPreference( tr( "PREF_TRACE_TYPE_LBL" ), traceGroup,
945 LightApp_Preferences::Selector,
946 PARAVIS_MODULE_NAME, "tracestate_type" );
949 aIndices << 0 << 1 << 2;
950 aStrings << tr("PREF_TRACE_TYPE_0") << tr("PREF_TRACE_TYPE_1") << tr("PREF_TRACE_TYPE_2");
951 setPreferenceProperty( aTraceType, "strings", aStrings );
952 setPreferenceProperty( aTraceType, "indexes", aIndices );
953 setPreferenceProperty( aTraceType, "restart", true );
957 \brief. Show ParaView python trace.
959 void PVGUI_Module::onShowTrace()
961 if (!myTraceWindow) {
962 myTraceWindow = new pqPythonScriptEditor(getApp()->desktop());
964 myTraceWindow->setText(getTraceString());
965 myTraceWindow->show();
966 myTraceWindow->raise();
967 myTraceWindow->activateWindow();
972 \brief. Re-initialize ParaView python trace.
974 void PVGUI_Module::onRestartTrace()
981 \brief. Close ParaView python trace.
983 void PVGUI_Module::onStopTrace()
988 \brief Called when view manager is added
990 void PVGUI_Module::onViewManagerAdded( SUIT_ViewManager* vm )
992 if ( PVViewer_ViewManager* pvvm = dynamic_cast<PVViewer_ViewManager*>( vm ) ) {
993 connect( pvvm, SIGNAL( viewCreated( SUIT_ViewWindow* ) ),
994 this, SLOT( onPVViewCreated( SUIT_ViewWindow* ) ) );
995 connect( pvvm, SIGNAL( deleteView( SUIT_ViewWindow* ) ),
996 this, SLOT( onPVViewDelete( SUIT_ViewWindow* ) ) );
1001 \brief Called when view manager is removed
1003 void PVGUI_Module::onViewManagerRemoved( SUIT_ViewManager* vm )
1005 if ( PVViewer_ViewManager* pvvm = dynamic_cast<PVViewer_ViewManager*>( vm ) )
1006 disconnect( pvvm, SIGNAL( viewCreated( SUIT_ViewWindow* ) ),
1007 this, SLOT( onPVViewCreated( SUIT_ViewWindow* ) ) );
1011 \brief Show toolbars at \a vw PV view window creating when PARAVIS is active.
1013 void PVGUI_Module::onPVViewCreated( SUIT_ViewWindow* vw )
1015 myGuiElements->setToolBarVisible( true );
1016 restoreDockWidgetsState();
1020 \brief Save toolbars state at \a view view closing.
1022 void PVGUI_Module::onPVViewDelete( SUIT_ViewWindow* view )
1024 if ( dynamic_cast<PVViewer_ViewWindow*>( view ) )
1025 saveDockWidgetsState( false );
1029 \fn CAM_Module* createModule();
1030 \brief Export module instance (factory function).
1031 \return new created instance of the module
1035 #define PVGUI_EXPORT __declspec(dllexport)
1037 #define PVGUI_EXPORT
1043 PVGUI_EXPORT CAM_Module* createModule() {
1044 return new PVGUI_Module();
1047 PVGUI_EXPORT char* getModuleVersion() {
1048 return (char*)PARAVIS_VERSION_STR;