1 // PARAVIS : ParaView wrapper SALOME module
3 // Copyright (C) 2010-2014 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 #include <Standard_math.hxx> // E.A. must be included before Python.h to fix compilation on windows
25 #undef HAVE_FINITE // VSR: avoid compilation warning on Linux : "HAVE_FINITE" redefined
27 #include <vtkPython.h> // Python first
28 #include "PVGUI_Module.h"
30 #ifdef PARAVIS_WITH_FULL_CORBA
31 # include "PARAVIS_Gen_i.hh"
34 #include CORBA_SERVER_HEADER(SALOME_ModuleCatalog)
35 #include CORBA_SERVER_HEADER(SALOMEDS)
37 #include "PVGUI_ViewModel.h"
38 #include "PVGUI_ViewManager.h"
39 #include "PVGUI_ViewWindow.h"
40 #include "PVGUI_Tools.h"
41 #include "PVGUI_ParaViewSettingsPane.h"
42 #include "PVGUI_OutputWindowAdapter.h"
43 #include "PVGUI_Behaviors.h"
46 #include <SUIT_DataBrowser.h>
47 #include <SUIT_Desktop.h>
48 #include <SUIT_MessageBox.h>
49 #include <SUIT_ResourceMgr.h>
50 #include <SUIT_Session.h>
51 #include <SUIT_OverrideCursor.h>
52 #include <SUIT_ExceptionHandler.h>
54 #include <SALOME_LifeCycleCORBA.hxx>
55 #include <SALOMEDS_SObject.hxx>
57 #include <LightApp_SelectionMgr.h>
58 #include <LightApp_NameDlg.h>
59 #include <SalomeApp_Application.h>
60 #include <SalomeApp_Study.h>
61 #include <SALOME_ListIO.hxx>
62 #include <SALOMEDS_Tool.hxx>
63 #include <Utils_ORB_INIT.hxx>
64 #include <Utils_SINGLETON.hxx>
66 #include <QtxActionMenuMgr.h>
67 #include <QtxActionToolMgr.h>
69 #include <PARAVIS_version.h>
75 #include <QApplication>
81 #include <QInputDialog>
85 #include <QStringList>
88 #include <QTextStream>
90 #include <QDockWidget>
91 #include <QHelpEngine>
94 #include <vtkPVConfig.h> // for symbol PARAVIEW_VERSION
95 #include <vtkProcessModule.h>
96 #include <vtkPVSession.h>
97 #include <vtkPVProgressHandler.h>
98 #include <vtkOutputWindow.h>
99 #include <vtkEventQtSlotConnect.h>
101 #include <vtkSMProxy.h>
102 #include <vtkSmartPointer.h>
103 #include <vtkSMSession.h>
104 #include <vtkSMTrace.h>
105 #include <vtkSMSessionProxyManager.h>
106 #include <vtkSMParaViewPipelineController.h>
108 #include <pqApplicationCore.h>
109 //#include <pqPVApplicationCore.h>
110 #include <pqActiveView.h>
111 #include <pqObjectBuilder.h>
112 #include <pqOptions.h>
113 #include <pqSettings.h>
114 #include <pqServer.h>
115 #include <pqUndoStack.h>
116 #include <pqTabbedMultiViewWidget.h>
117 #include <pqActiveObjects.h>
118 #include <pqHelpReaction.h>
119 #include <pqPluginManager.h>
120 #include <pqPythonDialog.h>
121 #include <pqPythonManager.h>
122 #include <pqLoadDataReaction.h>
123 #include <pqPythonScriptEditor.h>
124 #include <pqDataRepresentation.h>
125 #include <pqDisplayColorWidget.h>
126 #include <pqColorToolbar.h>
127 #include <pqScalarBarVisibilityReaction.h>
128 #include <pqServerResource.h>
129 #include <pqServerConnectReaction.h>
130 #include <pqServerDisconnectReaction.h>
132 //----------------------------------------------------------------------------
133 PVGUI_Module* ParavisModule = 0;
138 <h2>Building and installing PARAVIS</h2>
139 As any other SALOME module, PARAVIS requires PARAVIS_ROOT_DIR environment variable to be set to PARAVIS
140 installation directory.
141 Other variables needed for correct detection of ParaView location:
142 \li PVHOME - points at the ParaView installation directory tree
143 \li PVVERSION - number of ParaView version
145 It also requires common SALOME environment including GUI_ROOT_DIR and other prerequsites.
148 PARAVIS module can be launched using the following commands:
149 \li Full SALOME configuration
151 runSalome --modules="PARAVIS"
154 <h2>ParaView GUI integration</h2>
155 <h3>ParaView GUI integration overview</h3>
157 The main idea is to reuse ParaView GUI internal logic as much as possible, providing a layer
158 between it and SALOME GUI that hides the following SALOME GUI implementation details from ParaView:
160 \li SALOME GUI executable and Qt event loop
161 \li SALOME GUI desktop
162 \li Dock windows areas
163 \li SALOME menu and toolbar managers
165 Major part of the integration is implemented in PVGUI_Module class.
167 <h3>ParaView client initalization</h3>
169 ParaView client initalization is performed when an instance of PVGUI_Module class has been created
170 and \link PVGUI_Module::initialize() PVGUI_Module::initialize()\endlink method is called by SALOME GUI.
171 The actual client start-up is done in \link PVGUI_Module::pvInit() PVGUI_Module::pvInit()\endlink method.
174 <h3>Multi-view manager</h3>
176 SALOME GUI requires that each kind of view be implemnted with help of (at least) three classes. For ParaView multi-view manager
179 \li PVGUI_ViewManager - view manager class
180 \li PVGUI_Viewer - view model class
181 \li PVGUI_ViewWindow - view window class that acts as a parent for %pqViewManager
183 Single instances of PVGUI_ViewManager and PVGUI_ViewWindow classes are created by \link PVGUI_Module::showView()
184 PVGUI_Module::showView()\endlink method upon the first PARAVIS module activation. The same method hides the multi-view manager
185 when the module is deactivated (the user switches to another module or a study is closed).
186 A special trick is used to make PVGUI_ViewWindow the parent of %pqViewManager widget. It is created initally by %pqMainWindowCore
187 with the desktop as a parent, so when it is shown PVGUI_ViewWindow instance is passed to its setParent() method. In
188 \link PVGUI_ViewWindow::~PVGUI_ViewWindow() PVGUI_ViewWindow::~PVGUI_ViewWindow()\endlink the parent is nullified to avoid deletion
189 of %pqViewManager widget that would break %pqMainWindowCore class.
191 <h3>ParaView plugins</h3>
192 ParaView server and client plugins are managed by %pqMainWindowCore slots that has full access to PARAVIS menus and toolbars.
193 As a result they appears automatically in PARAVIS menus and toolbars if loaded successfully.
198 \brief Implementation
199 SALOME module wrapping ParaView GUI.
203 Clean up function; used to stop ParaView progress events when
204 exception is caught by global exception handler.
206 void paravisCleanUp()
208 if ( pqApplicationCore::instance() ) {
209 pqServer* s = pqApplicationCore::instance()->getActiveServer();
210 if ( s ) s->session()->GetProgressHandler()->CleanupPendingProgress();
215 \brief Constructor. Sets the default name for the module.
217 PVGUI_Module::PVGUI_Module()
218 : SalomeApp_Module( "PARAVIS" ),
219 mySelectionControlsTb( -1 ),
220 mySourcesMenuId( -1 ),
221 myFiltersMenuId( -1 ),
223 myToolbarsMenuId(-1),
232 Q_INIT_RESOURCE( PVGUI );
234 ParavisModule = this;
236 // Clear old copies of embedded macros files
237 QString aDestPath = QString( "%1/.config/%2/Macros" ).arg( QDir::homePath() ).arg( QApplication::applicationName() );
241 QDir aDestDir(aDestPath);
242 QStringList aDestFiles = aDestDir.entryList(aFilter, QDir::Files);
243 foreach (QString aMacrosPath, getEmbeddedMacrosList()) {
244 QString aMacrosName = QFileInfo(aMacrosPath).fileName();
245 if (aDestFiles.contains(aMacrosName)) {
246 aDestDir.remove(aMacrosName);
254 PVGUI_Module::~PVGUI_Module()
256 if (myPushTraceTimer)
257 delete myPushTraceTimer;
260 // Disconnect from server
261 pqServer* server = pqActiveObjects::instance().activeServer();
262 if (server && server->isRemote())
264 MESSAGE("~PVGUI_Module(): Disconnecting from remote server ...");
265 pqServerDisconnectReaction::disconnectFromServer();
269 PARAVIS_ORB::PARAVIS_Gen_var PVGUI_Module::GetEngine()
271 return PVGUI_ViewerModel::GetEngine();
275 \brief Initialize module. Creates menus, prepares context menu, etc.
276 \param app SALOME GUI application instance
278 void PVGUI_Module::initialize( CAM_Application* app )
280 SalomeApp_Module::initialize( app );
282 // Create ParaViS actions
284 // Create ParaViS menus
287 // Uncomment to debug ParaView initialization
288 // "aa" used instead of "i" as GDB doesn't like "i" variables :)
296 // Initialize ParaView client
299 // Create GUI elements (menus, toolbars, dock widgets)
300 SalomeApp_Application* anApp = getApp();
301 SUIT_Desktop* aDesktop = anApp->desktop();
303 // Remember current state of desktop toolbars
304 QList<QToolBar*> foreignToolbars = aDesktop->findChildren<QToolBar*>();
312 QList<QDockWidget*> activeDocks = aDesktop->findChildren<QDockWidget*>();
313 QList<QMenu*> activeMenus = aDesktop->findChildren<QMenu*>();
315 PVGUI_Behaviors * behav = new PVGUI_Behaviors(this);
316 behav->instanciateAllBehaviors(aDesktop);
318 // Setup quick-launch shortcuts.
319 QShortcut *ctrlSpace = new QShortcut(Qt::CTRL + Qt::Key_Space, aDesktop);
320 QObject::connect(ctrlSpace, SIGNAL(activated()),
321 pqApplicationCore::instance(), SLOT(quickLaunch()));
323 // Find Plugin Dock Widgets
324 QList<QDockWidget*> currentDocks = aDesktop->findChildren<QDockWidget*>();
325 QList<QDockWidget*>::iterator i;
326 for (i = currentDocks.begin(); i != currentDocks.end(); ++i) {
327 if(!activeDocks.contains(*i)) {
328 myDockWidgets[*i] = false; // hidden by default
334 // [ABN] TODO: fix this - triggers a SEGFAULT at deactivation() time.
335 // QList<QMenu*> currentMenus = aDesktop->findChildren<QMenu*>();
336 // QList<QMenu*>::iterator im;
337 // for (im = currentMenus.begin(); im != currentMenus.end(); ++im) {
338 // if(!activeMenus.contains(*im)) {
339 // QString s = (*im)->title();
340 // std::cout << " MENU "<< s.toStdString() << std::endl;
341 // myMenus.append(*im);
345 SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr();
346 QString aPath = resMgr->stringValue("resources", "PARAVIS", QString());
347 if (!aPath.isNull()) {
348 MyCoreApp->loadConfiguration(aPath + QDir::separator() + "ParaViewFilters.xml");
349 MyCoreApp->loadConfiguration(aPath + QDir::separator() + "ParaViewReaders.xml");
350 MyCoreApp->loadConfiguration(aPath + QDir::separator() + "ParaViewSources.xml");
351 MyCoreApp->loadConfiguration(aPath + QDir::separator() + "ParaViewWriters.xml");
354 // Force creation of the PARAVIS engine
358 // Find created toolbars
359 QCoreApplication::processEvents();
361 QList<QToolBar*> allToolbars = aDesktop->findChildren<QToolBar*>();
362 foreach(QToolBar* aBar, allToolbars) {
363 if (!foreignToolbars.contains(aBar)) {
364 myToolbars[aBar] = true;
365 myToolbarBreaks[aBar] = false;
366 aBar->setVisible(false);
367 aBar->toggleViewAction()->setVisible(false);
373 SUIT_ResourceMgr* aResourceMgr = SUIT_Session::session()->resourceMgr();
374 bool isStop = aResourceMgr->booleanValue( "PARAVIS", "stop_trace", false );
377 // Start a timer to schedule asap:
378 // - the connection to the server
380 myInitTimer = new QTimer(aDesktop);
381 QObject::connect(myInitTimer, SIGNAL(timeout()), this, SLOT(onInitTimer()) );
382 myInitTimer->setSingleShot(true);
383 myInitTimer->start(0);
385 // Another timer to regularly push the trace onto the engine:
386 myPushTraceTimer = new QTimer(aDesktop);
387 QObject::connect(myPushTraceTimer, SIGNAL(timeout()), this, SLOT(onPushTraceTimer()) );
388 myPushTraceTimer->setSingleShot(false);
389 myPushTraceTimer->start(500);
392 this->VTKConnect = vtkEventQtSlotConnect::New();
394 vtkProcessModule* pm = vtkProcessModule::GetProcessModule();
396 vtkPVSession* pvs = dynamic_cast<vtkPVSession*>(pm->GetSession());
398 vtkPVProgressHandler* ph = pvs->GetProgressHandler();
400 this->VTKConnect->Connect(ph, vtkCommand::StartEvent,
401 this, SLOT(onStartProgress()));
402 this->VTKConnect->Connect(ph, vtkCommand::EndEvent,
403 this, SLOT(onEndProgress()));
409 void PVGUI_Module::onStartProgress()
411 QApplication::setOverrideCursor(Qt::WaitCursor);
414 void PVGUI_Module::onEndProgress()
416 QApplication::restoreOverrideCursor();
419 void PVGUI_Module::onDataRepresentationUpdated() {
420 SalomeApp_Study* activeStudy = dynamic_cast<SalomeApp_Study*>(application()->activeStudy());
421 if(!activeStudy) return;
423 activeStudy->Modified();
427 \brief Initialisation timer event - fired only once, after the GUI loop is ready.
428 See creation in initialize().
430 void PVGUI_Module::onInitTimer()
432 #ifndef PARAVIS_WITH_FULL_CORBA
433 connectToExternalPVServer();
439 \brief Get list of embedded macros files
441 QStringList PVGUI_Module::getEmbeddedMacrosList()
443 QString aRootDir = getenv("PARAVIS_ROOT_DIR");
445 QString aSourcePath = aRootDir + "/bin/salome/Macro";
450 QDir aSourceDir(aSourcePath);
451 QStringList aSourceFiles = aSourceDir.entryList(aFilter, QDir::Files);
452 QStringList aFullPathSourceFiles;
453 foreach (QString aMacrosName, aSourceFiles) {
454 aFullPathSourceFiles << aSourceDir.absoluteFilePath(aMacrosName);
456 return aFullPathSourceFiles;
459 void PVGUI_Module::updateMacros()
461 pqPythonManager* aPythonManager = pqPVApplicationCore::instance()->pythonManager();
462 if(!aPythonManager) {
466 foreach (QString aStr, getEmbeddedMacrosList()) {
467 aPythonManager->addMacro(aStr);
473 \brief Get list of compliant dockable GUI elements
474 \param m map to be filled in ("type":"default_position")
476 void PVGUI_Module::windows( QMap<int, int>& m ) const
478 m.insert( LightApp_Application::WT_ObjectBrowser, Qt::LeftDockWidgetArea );
479 m.insert( LightApp_Application::WT_PyConsole, Qt::BottomDockWidgetArea );
480 // ParaView diagnostic output redirected here
481 m.insert( LightApp_Application::WT_LogWindow, Qt::BottomDockWidgetArea );
485 \brief Shows (toShow = true) or hides ParaView view window
487 void PVGUI_Module::showView( bool toShow )
490 SalomeApp_Application* anApp = getApp();
491 PVGUI_ViewManager* viewMgr =
492 dynamic_cast<PVGUI_ViewManager*>( anApp->getViewManager( PVGUI_Viewer::Type(), false ) );
494 viewMgr = new PVGUI_ViewManager( anApp->activeStudy(), anApp->desktop() );
495 anApp->addViewManager( viewMgr );
496 connect( viewMgr, SIGNAL( lastViewClosed( SUIT_ViewManager* ) ),
497 anApp, SLOT( onCloseView( SUIT_ViewManager* ) ) );
500 PVGUI_ViewWindow* pvWnd = dynamic_cast<PVGUI_ViewWindow*>( viewMgr->getActiveView() );
502 pvWnd = dynamic_cast<PVGUI_ViewWindow*>( viewMgr->createViewWindow() );
505 pvWnd->setShown( toShow );
506 if ( toShow ) pvWnd->setFocus();
510 \brief Slot to show help for proxy.
512 void PVGUI_Module::showHelpForProxy( const QString& groupname, const QString& proxyname )
514 pqHelpReaction::showProxyHelp(groupname, proxyname);
519 \brief Slot to show the waiting state.
521 void PVGUI_Module::onPreAccept()
523 getApp()->desktop()->statusBar()->showMessage(tr("STB_PREACCEPT"));
524 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
528 \brief Slot to show the ready state.
530 void PVGUI_Module::onPostAccept()
532 getApp()->desktop()->statusBar()->showMessage(tr("STB_POSTACCEPT"), 2000);
533 QTimer::singleShot(0, this, SLOT(endWaitCursor()));
537 \brief Slot to switch off wait cursor.
539 void PVGUI_Module::endWaitCursor()
541 QApplication::restoreOverrideCursor();
544 static void ParavisMessageOutput(QtMsgType type, const char *msg)
549 vtkOutputWindow::GetInstance()->DisplayText(msg);
552 vtkOutputWindow::GetInstance()->DisplayErrorText(msg);
555 vtkOutputWindow::GetInstance()->DisplayErrorText(msg);
558 vtkOutputWindow::GetInstance()->DisplayErrorText(msg);
564 \brief Activate module.
565 \param study current study
566 \return \c true if activaion is done successfully or 0 to prevent
569 bool PVGUI_Module::activateModule( SUIT_Study* study )
571 myOldMsgHandler = qInstallMsgHandler(ParavisMessageOutput);
573 SUIT_ExceptionHandler::addCleanUpRoutine( paravisCleanUp );
575 storeCommonWindowsState();
577 bool isDone = SalomeApp_Module::activateModule( study );
578 if ( !isDone ) return false;
581 if ( mySourcesMenuId != -1 ) menuMgr()->show(mySourcesMenuId);
582 if ( myFiltersMenuId != -1 ) menuMgr()->show(myFiltersMenuId);
583 if ( myFiltersMenuId != -1 ) menuMgr()->show(myMacrosMenuId);
584 if ( myFiltersMenuId != -1 ) menuMgr()->show(myToolbarsMenuId);
585 setMenuShown( true );
586 setToolShown( true );
588 restoreDockWidgetsState();
590 QMenu* aMenu = menuMgr()->findMenu( myRecentMenuId );
592 QList<QAction*> anActns = aMenu->actions();
593 for (int i = 0; i < anActns.size(); ++i) {
594 QAction* a = anActns.at(i);
600 QList<QMenu*>::iterator it;
601 for (it = myMenus.begin(); it != myMenus.end(); ++it) {
602 QAction* a = (*it)->menuAction();
607 if ( myRecentMenuId != -1 ) menuMgr()->show(myRecentMenuId);
609 // ClientFindOrCreateParavisComponent(PARAVIS::GetCStudy(this));
616 \brief Deactivate module.
617 \param study current study
618 \return \c true if deactivaion is done successfully or 0 to prevent
619 deactivation on error
621 bool PVGUI_Module::deactivateModule( SUIT_Study* study )
623 MESSAGE("PARAVIS deactivation ...")
625 QMenu* aMenu = menuMgr()->findMenu( myRecentMenuId );
627 QList<QAction*> anActns = aMenu->actions();
628 for (int i = 0; i < anActns.size(); ++i) {
629 QAction* a = anActns.at(i);
631 a->setVisible(false);
635 QList<QMenu*>::iterator it;
636 for (it = myMenus.begin(); it != myMenus.end(); ++it) {
637 QAction* a = (*it)->menuAction();
639 a->setVisible(false);
642 QList<QDockWidget*> aStreamingViews = application()->desktop()->findChildren<QDockWidget*>("pqStreamingControls");
643 foreach(QDockWidget* aView, aStreamingViews) {
644 if (!myDockWidgets.contains(aView))
645 myDockWidgets[aView] = aView->isVisible();
648 /*if (pqImplementation::helpWindow) {
649 pqImplementation::helpWindow->hide();
653 menuMgr()->hide(myRecentMenuId);
654 menuMgr()->hide(mySourcesMenuId);
655 menuMgr()->hide(myFiltersMenuId);
656 menuMgr()->hide(myMacrosMenuId);
657 menuMgr()->hide(myToolbarsMenuId);
658 setMenuShown( false );
659 setToolShown( false );
661 saveDockWidgetsState();
663 SUIT_ExceptionHandler::removeCleanUpRoutine( paravisCleanUp );
666 qInstallMsgHandler(myOldMsgHandler);
668 restoreCommonWindowsState();
670 return SalomeApp_Module::deactivateModule( study );
675 \brief Called when application is closed.
677 Process finalize application functionality from ParaView in order to save server settings
678 and nullify application pointer if the application is being closed.
680 \param theApp application
682 void PVGUI_Module::onApplicationClosed( SUIT_Application* theApp )
684 pqApplicationCore::instance()->settings()->sync();
685 int aAppsNb = SUIT_Session::session()->applications().size();
687 deleteTemporaryFiles();
688 MyCoreApp->deleteLater();
690 CAM_Module::onApplicationClosed(theApp);
695 \brief Deletes temporary files created during import operation from VISU
697 void PVGUI_Module::deleteTemporaryFiles()
699 foreach(QString aFile, myTemporaryFiles) {
700 if (QFile::exists(aFile)) {
701 QFile::remove(aFile);
708 \brief Called when study is closed.
710 Removes data model from the \a study.
712 \param study study being closed
714 void PVGUI_Module::studyClosed(SUIT_Study* study)
716 clearParaviewState();
718 SalomeApp_Module::studyClosed(study);
722 \brief Called when study is opened.
724 void PVGUI_Module::onModelOpened()
726 _PTR(Study) studyDS = PARAVIS::GetCStudy(this);
731 _PTR(SComponent) paravisComp =
732 studyDS->FindComponent(GetEngine()->ComponentDataType());
737 _PTR(ChildIterator) anIter(studyDS->NewChildIterator(paravisComp));
738 for (; anIter->More(); anIter->Next()) {
739 _PTR(SObject) aSObj = anIter->Value();
740 _PTR(GenericAttribute) anAttr;
741 if (!aSObj->FindAttribute(anAttr, "AttributeLocalID")) {
744 _PTR(AttributeLocalID) anID(anAttr);
745 if (anID->Value() == PVSTATEID) {
752 \brief Returns IOR of current engine
754 QString PVGUI_Module::engineIOR() const
756 CORBA::String_var anIOR = GetEngine()->GetIOR();
757 return QString(anIOR.in());
761 \brief Open file of format supported by ParaView
763 void PVGUI_Module::openFile(const char* theName)
767 pqLoadDataReaction::loadData(aFiles);
771 * Start trace invoking the newly introduced C++ API (PV 4.2)
772 * (inspired from pqTraceReaction::start())
774 void PVGUI_Module::startTrace()
776 vtkSMSessionProxyManager* pxm = pqActiveObjects::instance().activeServer()->proxyManager();
778 vtkSmartPointer<vtkSMProxy> proxy;
779 proxy.TakeReference(pxm->NewProxy("pythontracing", "PythonTraceOptions"));
782 vtkNew<vtkSMParaViewPipelineController> controller;
783 controller->InitializeProxy(proxy);
785 vtkSMTrace* trace = vtkSMTrace::StartTrace();
788 // Set manually the properties entered via the dialog box poping-up when requiring
789 // a trace start in PV4.2 (trace options)
790 trace->SetPropertiesToTraceOnCreate(vtkSMTrace::RECORD_USER_MODIFIED_PROPERTIES);
791 trace->SetFullyTraceSupplementalProxies(false);
795 void PVGUI_Module::stopTrace()
797 vtkSMTrace::StopTrace();
800 void PVGUI_Module::executeScript(const char *script)
803 pqPythonManager* manager = qobject_cast<pqPythonManager*>(
804 pqApplicationCore::instance()->manager("PYTHON_MANAGER"));
806 pqPythonDialog* pyDiag = manager->pythonShellDialog();
808 pyDiag->runString(script);
815 // * Debug function printing out the given interpreter's execution context
817 //void printInterpContext(PyInterp_Interp * interp )
819 // // Extract __smtraceString from interpreter's context
820 // const PyObject* ctxt = interp->getExecutionContext();
822 // PyObject* lst = PyDict_Keys((PyObject *)ctxt);
823 // Py_ssize_t siz = PyList_GET_SIZE(lst);
824 // for (Py_ssize_t i = 0; i < siz; i++)
826 // PyObject * elem = PyList_GetItem(lst, i);
827 // if (PyString_Check(elem))
829 // std::cout << "At pos:" << i << ", " << PyString_AsString(elem) << std::endl;
832 // std::cout << "At pos:" << i << ", not a string!" << std::endl;
838 \brief Returns trace string
840 static const QString MYReplaceStr("paraview.simple");
841 static const QString MYReplaceImportStr("except: from pvsimple import *");
842 QString PVGUI_Module::getTraceString()
844 vtkSMTrace *tracer = vtkSMTrace::GetActiveTracer();
845 if (!tracer) // trace is not started
848 QString traceString(tracer->GetCurrentTrace());
850 // Replace import "paraview.simple" by "pvsimple"
851 if ((!traceString.isNull()) && traceString.length() != 0) {
852 int aPos = traceString.indexOf(MYReplaceStr);
854 traceString = traceString.replace(aPos, MYReplaceStr.length(), "pvsimple");
855 aPos = traceString.indexOf(MYReplaceStr, aPos);
857 int aImportPos = traceString.indexOf(MYReplaceImportStr);
860 traceString = traceString.replace(aImportPos, MYReplaceImportStr.length(), "except:\n import pvsimple\n from pvsimple import *");
868 \brief Saves trace string to disk file
870 void PVGUI_Module::saveTrace(const char* theName)
873 if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
874 MESSAGE( "Could not open file:" << theName );
877 QTextStream out(&file);
878 out << getTraceString();
883 \brief Saves ParaView state to a disk file
885 void PVGUI_Module::saveParaviewState(const char* theFileName)
887 pqApplicationCore::instance()->saveState(theFileName);
891 \brief Delete all objects for Paraview Pipeline Browser
893 void PVGUI_Module::clearParaviewState()
895 QAction* deleteAllAction = action(DeleteAllId);
896 if (deleteAllAction) {
897 deleteAllAction->activate(QAction::Trigger);
902 \brief Restores ParaView state from a disk file
904 If toClear == true, the current ojects will be deleted
906 void PVGUI_Module::loadParaviewState(const char* theFileName)
908 pqApplicationCore::instance()->loadState(theFileName, getActiveServer());
912 \brief Returns current active ParaView server
914 pqServer* PVGUI_Module::getActiveServer()
916 return pqApplicationCore::instance()->getActiveServer();
921 \brief Creates PARAVIS preference pane
923 void PVGUI_Module::createPreferences()
925 // Paraview settings tab
926 int aParaViewSettingsTab = addPreference( tr( "TIT_PVIEWSETTINGS" ) );
927 int aPanel = addPreference(QString(), aParaViewSettingsTab, LightApp_Preferences::UserDefined, "PARAVIS", "");
928 setPreferenceProperty(aPanel, "content", (qint64)(new PVGUI_ParaViewSettingsPane()));
930 // Paravis settings tab
931 int aParaVisSettingsTab = addPreference( tr( "TIT_PVISSETTINGS" ) );
932 addPreference( tr( "PREF_STOP_TRACE" ), aParaVisSettingsTab, LightApp_Preferences::Bool, "PARAVIS", "stop_trace");
934 int aSaveType = addPreference(tr( "PREF_SAVE_TYPE_LBL" ), aParaVisSettingsTab,
935 LightApp_Preferences::Selector,
936 "PARAVIS", "savestate_type");
937 QList<QVariant> aIndices;
938 QStringList aStrings;
940 aStrings<<tr("PREF_SAVE_TYPE_0");
941 aStrings<<tr("PREF_SAVE_TYPE_1");
942 aStrings<<tr("PREF_SAVE_TYPE_2");
943 setPreferenceProperty(aSaveType, "strings", aStrings);
944 setPreferenceProperty(aSaveType, "indexes", aIndices);
948 \brief Creates ParaViS context menu popup
950 void PVGUI_Module::contextMenuPopup(const QString& theClient, QMenu* theMenu, QString& theTitle)
952 SalomeApp_Module::contextMenuPopup(theClient, theMenu, theTitle);
954 // Check if we are in Object Browser
955 SUIT_DataBrowser* ob = getApp()->objectBrowser();
956 bool isOBClient = (ob && theClient == ob->popupClientType());
961 // Get list of selected objects
962 LightApp_SelectionMgr* aSelectionMgr = getApp()->selectionMgr();
963 SALOME_ListIO aListIO;
964 aSelectionMgr->selectedObjects(aListIO);
965 if (aListIO.Extent() == 1 && aListIO.First()->hasEntry()) {
966 QString entry = QString(aListIO.First()->getEntry());
969 SalomeApp_Study* activeStudy =
970 dynamic_cast<SalomeApp_Study*>(getApp()->activeStudy());
975 // Get SALOMEDS client study
976 _PTR(Study) studyDS = activeStudy->studyDS();
981 QString paravisDataType(GetEngine()->ComponentDataType());
982 if(activeStudy && activeStudy->isComponent(entry) &&
983 activeStudy->componentDataType(entry) == paravisDataType) {
984 // ParaViS module object
985 theMenu->addSeparator();
986 theMenu->addAction(action(SaveStatePopupId));
989 // Try to get state object
990 _PTR(SObject) stateSObj =
991 studyDS->FindObjectID(entry.toLatin1().constData());
997 _PTR(GenericAttribute) anAttr;
998 if (!stateSObj->FindAttribute(anAttr, "AttributeLocalID")) {
1002 _PTR(AttributeLocalID) anID(anAttr);
1004 if (anID->Value() == PVSTATEID) {
1005 // Paraview state object
1006 theMenu->addSeparator();
1007 theMenu->addAction(action(AddStatePopupId));
1008 theMenu->addAction(action(CleanAndAddStatePopupId));
1009 theMenu->addSeparator();
1010 theMenu->addAction(action(ParaVisRenameId));
1011 theMenu->addAction(action(ParaVisDeleteId));
1018 \brief. Show ParaView python trace.
1020 void PVGUI_Module::onShowTrace()
1022 if (!myTraceWindow) {
1023 myTraceWindow = new pqPythonScriptEditor(getApp()->desktop());
1025 myTraceWindow->setText(getTraceString());
1026 myTraceWindow->show();
1027 myTraceWindow->raise();
1028 myTraceWindow->activateWindow();
1033 \brief. Re-initialize ParaView python trace.
1035 void PVGUI_Module::onRestartTrace()
1042 \brief Show ParaView view.
1044 void PVGUI_Module::onNewParaViewWindow()
1050 \brief Save state under the module root object.
1052 void PVGUI_Module::onSaveMultiState()
1054 // Create state study object
1056 // Get SALOMEDS client study
1057 _PTR(Study) studyDS = PARAVIS::GetCStudy(this);
1062 _PTR(SComponent) paravisComp =
1063 studyDS->FindComponent(GetEngine()->ComponentDataType());
1068 // Unlock the study if it is locked
1069 bool isLocked = studyDS->GetProperties()->IsLocked();
1071 studyDS->GetProperties()->SetLocked(false);
1074 QString stateName = tr("SAVED_PARAVIEW_STATE_NAME") +
1075 QString::number(myStateCounter + 1);
1077 _PTR(StudyBuilder) studyBuilder = studyDS->NewBuilder();
1078 _PTR(SObject) newSObj = studyBuilder->NewObject(paravisComp);
1081 _PTR(GenericAttribute) anAttr;
1082 anAttr = studyBuilder->FindOrCreateAttribute(newSObj, "AttributeName");
1083 _PTR(AttributeName) nameAttr(anAttr);
1085 nameAttr->SetValue(stateName.toLatin1().constData());
1088 anAttr = studyBuilder->FindOrCreateAttribute(newSObj, "AttributeLocalID");
1089 _PTR(AttributeLocalID) localIdAttr(anAttr);
1091 localIdAttr->SetValue(PVSTATEID);
1094 QString stateEntry = QString::fromStdString(newSObj->GetID());
1096 // File name for state saving
1097 QString tmpDir = QString::fromStdString(SALOMEDS_Tool::GetTmpDir());
1098 QString fileName = QString("%1_paravisstate:%2").arg(tmpDir, stateEntry);
1100 anAttr = studyBuilder->FindOrCreateAttribute(newSObj, "AttributeString");
1101 _PTR(AttributeString) stringAttr(anAttr);
1103 stringAttr->SetValue(fileName.toLatin1().constData());
1105 // Lock the study back if necessary
1107 studyDS->GetProperties()->SetLocked(true);
1111 saveParaviewState(fileName.toLatin1().constData());
1112 myTemporaryFiles.append(fileName);
1114 // Increment the counter
1121 \brief Restore the selected state by merging with the current one.
1123 void PVGUI_Module::onAddState()
1125 loadSelectedState(false);
1129 \brief Clean the current state and restore the selected one.
1131 void PVGUI_Module::onCleanAddState()
1133 loadSelectedState(true);
1137 \brief Rename the selected object.
1139 void PVGUI_Module::onRename()
1141 LightApp_SelectionMgr* aSelectionMgr = getApp()->selectionMgr();
1142 SALOME_ListIO aListIO;
1143 aSelectionMgr->selectedObjects(aListIO);
1145 if (aListIO.Extent() == 1 && aListIO.First()->hasEntry()) {
1146 std::string entry = aListIO.First()->getEntry();
1148 // Get SALOMEDS client study
1149 _PTR(Study) studyDS = PARAVIS::GetCStudy(this);
1154 // Unlock the study if it is locked
1155 bool isLocked = studyDS->GetProperties()->IsLocked();
1157 studyDS->GetProperties()->SetLocked(false);
1160 // Rename the selected state object
1161 _PTR(SObject) stateSObj = studyDS->FindObjectID(entry);
1166 _PTR(GenericAttribute) anAttr;
1167 if (stateSObj->FindAttribute(anAttr, "AttributeName")) {
1168 _PTR(AttributeName) nameAttr (anAttr);
1170 LightApp_NameDlg::getName(getApp()->desktop(), nameAttr->Value().c_str());
1171 if (!newName.isEmpty()) {
1172 nameAttr->SetValue(newName.toLatin1().constData());
1173 aListIO.First()->setName(newName.toLatin1().constData());
1177 // Lock the study back if necessary
1179 studyDS->GetProperties()->SetLocked(true);
1182 // Update object browser
1189 \brief Delete the selected objects.
1191 void PVGUI_Module::onDelete()
1193 LightApp_SelectionMgr* aSelectionMgr = getApp()->selectionMgr();
1194 SALOME_ListIO aListIO;
1195 aSelectionMgr->selectedObjects(aListIO);
1197 if (aListIO.Extent() == 1 && aListIO.First()->hasEntry()) {
1198 std::string entry = aListIO.First()->getEntry();
1200 // Get SALOMEDS client study
1201 _PTR(Study) studyDS = PARAVIS::GetCStudy(this);
1206 // Unlock the study if it is locked
1207 bool isLocked = studyDS->GetProperties()->IsLocked();
1209 studyDS->GetProperties()->SetLocked(false);
1212 // Remove the selected state from the study
1213 _PTR(StudyBuilder) studyBuilder = studyDS->NewBuilder();
1214 _PTR(SObject) stateSObj = studyDS->FindObjectID(entry);
1215 studyBuilder->RemoveObject(stateSObj);
1217 // Lock the study back if necessary
1219 studyDS->GetProperties()->SetLocked(true);
1222 // Update object browser
1227 void PVGUI_Module::onPushTraceTimer()
1229 // MESSAGE("onPushTraceTimer(): Pushing trace to engine...");
1230 GetEngine()->PutPythonTraceStringToEngine(getTraceString().toStdString().c_str());
1234 \brief Discover help project files from the resources.
1235 \return name of the help file.
1237 QString PVGUI_Module::getHelpFileName() {
1238 QString aPVHome(getenv("PVHOME"));
1239 if (aPVHome.isNull()) {
1240 qWarning("Wariable PVHOME is not defined");
1243 QChar aSep = QDir::separator();
1244 //PARAVIEW_VERSION from the vtkPVConfig.h file
1245 QString aFileName = aPVHome + aSep + "share" + aSep + "doc" + aSep + "paraview-"+ PARAVIEW_VERSION + aSep + "paraview.qch";
1251 \brief Load selected paraview state
1253 If toClear == true, the current state will be cleared
1255 void PVGUI_Module::loadSelectedState(bool toClear)
1259 LightApp_SelectionMgr* aSelectionMgr = getApp()->selectionMgr();
1260 SALOME_ListIO aListIO;
1261 aSelectionMgr->selectedObjects(aListIO);
1263 if (aListIO.Extent() == 1 && aListIO.First()->hasEntry()) {
1264 std::string entry = aListIO.First()->getEntry();
1266 // Get SALOMEDS client study
1267 _PTR(Study) studyDS = PARAVIS::GetCStudy(this);
1273 _PTR(SObject) stateSObj = studyDS->FindObjectID(entry);
1274 _PTR(GenericAttribute) anAttr;
1275 if (!stateSObj->FindAttribute(anAttr, "AttributeLocalID")) {
1278 _PTR(AttributeLocalID) anID(anAttr);
1279 if (!anID->Value() == PVSTATEID) {
1283 // Get state file name
1284 if (stateSObj->FindAttribute(anAttr, "AttributeString")) {
1285 _PTR(AttributeString) aStringAttr(anAttr);
1286 QString stringValue(aStringAttr->Value().c_str());
1288 if (QFile::exists(stringValue)) {
1289 fileName = stringValue;
1294 if (!fileName.isEmpty()) {
1296 clearParaviewState();
1299 loadParaviewState(fileName.toLatin1().constData());
1302 SUIT_MessageBox::critical(getApp()->desktop(),
1304 tr("ERR_STATE_CANNOT_BE_RESTORED"));
1309 \fn CAM_Module* createModule();
1310 \brief Export module instance (factory function).
1311 \return new created instance of the module
1315 #define PVGUI_EXPORT __declspec(dllexport)
1317 #define PVGUI_EXPORT
1323 PVGUI_EXPORT CAM_Module* createModule() {
1324 return new PVGUI_Module();
1327 PVGUI_EXPORT char* getModuleVersion() {
1328 return (char*)PARAVIS_VERSION_STR;