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 pqPVApplicationCore* PVGUI_Module::MyCoreApp = 0;
135 PVGUI_Module* ParavisModule = 0;
137 PARAVIS_ORB::PARAVIS_Gen_var PVGUI_Module::myEngine;
142 <h2>Building and installing PARAVIS</h2>
143 As any other SALOME module, PARAVIS requires PARAVIS_ROOT_DIR environment variable to be set to PARAVIS
144 installation directory.
145 Other variables needed for correct detection of ParaView location:
146 \li PVHOME - points at the ParaView installation directory tree
147 \li PVVERSION - number of ParaView version
149 It also requires common SALOME environment including GUI_ROOT_DIR and other prerequsites.
152 PARAVIS module can be launched using the following commands:
153 \li Full SALOME configuration
155 runSalome --modules="PARAVIS"
158 <h2>ParaView GUI integration</h2>
159 <h3>ParaView GUI integration overview</h3>
161 The main idea is to reuse ParaView GUI internal logic as much as possible, providing a layer
162 between it and SALOME GUI that hides the following SALOME GUI implementation details from ParaView:
164 \li SALOME GUI executable and Qt event loop
165 \li SALOME GUI desktop
166 \li Dock windows areas
167 \li SALOME menu and toolbar managers
169 Major part of the integration is implemented in PVGUI_Module class.
171 <h3>ParaView client initalization</h3>
173 ParaView client initalization is performed when an instance of PVGUI_Module class has been created
174 and \link PVGUI_Module::initialize() PVGUI_Module::initialize()\endlink method is called by SALOME GUI.
175 The actual client start-up is done in \link PVGUI_Module::pvInit() PVGUI_Module::pvInit()\endlink method.
178 <h3>Multi-view manager</h3>
180 SALOME GUI requires that each kind of view be implemnted with help of (at least) three classes. For ParaView multi-view manager
183 \li PVGUI_ViewManager - view manager class
184 \li PVGUI_Viewer - view model class
185 \li PVGUI_ViewWindow - view window class that acts as a parent for %pqViewManager
187 Single instances of PVGUI_ViewManager and PVGUI_ViewWindow classes are created by \link PVGUI_Module::showView()
188 PVGUI_Module::showView()\endlink method upon the first PARAVIS module activation. The same method hides the multi-view manager
189 when the module is deactivated (the user switches to another module or a study is closed).
190 A special trick is used to make PVGUI_ViewWindow the parent of %pqViewManager widget. It is created initally by %pqMainWindowCore
191 with the desktop as a parent, so when it is shown PVGUI_ViewWindow instance is passed to its setParent() method. In
192 \link PVGUI_ViewWindow::~PVGUI_ViewWindow() PVGUI_ViewWindow::~PVGUI_ViewWindow()\endlink the parent is nullified to avoid deletion
193 of %pqViewManager widget that would break %pqMainWindowCore class.
195 <h3>ParaView plugins</h3>
196 ParaView server and client plugins are managed by %pqMainWindowCore slots that has full access to PARAVIS menus and toolbars.
197 As a result they appears automatically in PARAVIS menus and toolbars if loaded successfully.
202 \brief Implementation
203 SALOME module wrapping ParaView GUI.
207 Clean up function; used to stop ParaView progress events when
208 exception is caught by global exception handler.
210 void paravisCleanUp()
212 if ( pqApplicationCore::instance() ) {
213 pqServer* s = pqApplicationCore::instance()->getActiveServer();
214 if ( s ) s->session()->GetProgressHandler()->CleanupPendingProgress();
219 \brief Constructor. Sets the default name for the module.
221 PVGUI_Module::PVGUI_Module()
222 : SalomeApp_Module( "PARAVIS" ),
223 mySelectionControlsTb( -1 ),
224 mySourcesMenuId( -1 ),
225 myFiltersMenuId( -1 ),
227 myToolbarsMenuId(-1),
236 Q_INIT_RESOURCE( PVGUI );
238 ParavisModule = this;
240 // Clear old copies of embedded macros files
241 QString aDestPath = QString( "%1/.config/%2/Macros" ).arg( QDir::homePath() ).arg( QApplication::applicationName() );
245 QDir aDestDir(aDestPath);
246 QStringList aDestFiles = aDestDir.entryList(aFilter, QDir::Files);
247 foreach (QString aMacrosPath, getEmbeddedMacrosList()) {
248 QString aMacrosName = QFileInfo(aMacrosPath).fileName();
249 if (aDestFiles.contains(aMacrosName)) {
250 aDestDir.remove(aMacrosName);
258 PVGUI_Module::~PVGUI_Module()
260 if (myPushTraceTimer)
261 delete myPushTraceTimer;
264 // Disconnect from server
265 pqServer* server = pqActiveObjects::instance().activeServer();
266 if (server && server->isRemote())
268 MESSAGE("~PVGUI_Module(): Disconnecting from remote server ...");
269 pqServerDisconnectReaction::disconnectFromServer();
273 PARAVIS_ORB::PARAVIS_Gen_var PVGUI_Module::GetEngine()
275 // initialize PARAVIS module engine (load, if necessary)
276 if ( CORBA::is_nil( myEngine ) ) {
277 Engines::EngineComponent_var comp =
278 SalomeApp_Application::lcc()->FindOrLoad_Component( "FactoryServer", "PARAVIS" );
279 myEngine = PARAVIS_ORB::PARAVIS_Gen::_narrow( comp );
285 \brief Initialize module. Creates menus, prepares context menu, etc.
286 \param app SALOME GUI application instance
288 void PVGUI_Module::initialize( CAM_Application* app )
290 SalomeApp_Module::initialize( app );
292 // Create ParaViS actions
294 // Create ParaViS menus
297 // Uncomment to debug ParaView initialization
298 // "aa" used instead of "i" as GDB doesn't like "i" variables :)
306 // Initialize ParaView client
309 // Create GUI elements (menus, toolbars, dock widgets)
310 SalomeApp_Application* anApp = getApp();
311 SUIT_Desktop* aDesktop = anApp->desktop();
313 // Remember current state of desktop toolbars
314 QList<QToolBar*> foreignToolbars = aDesktop->findChildren<QToolBar*>();
322 QList<QDockWidget*> activeDocks = aDesktop->findChildren<QDockWidget*>();
323 QList<QMenu*> activeMenus = aDesktop->findChildren<QMenu*>();
325 PVGUI_Behaviors * behav = new PVGUI_Behaviors(this);
326 behav->instanciateAllBehaviors(aDesktop);
328 // Setup quick-launch shortcuts.
329 QShortcut *ctrlSpace = new QShortcut(Qt::CTRL + Qt::Key_Space, aDesktop);
330 QObject::connect(ctrlSpace, SIGNAL(activated()),
331 pqApplicationCore::instance(), SLOT(quickLaunch()));
333 // Find Plugin Dock Widgets
334 QList<QDockWidget*> currentDocks = aDesktop->findChildren<QDockWidget*>();
335 QList<QDockWidget*>::iterator i;
336 for (i = currentDocks.begin(); i != currentDocks.end(); ++i) {
337 if(!activeDocks.contains(*i)) {
338 myDockWidgets[*i] = false; // hidden by default
344 // [ABN] TODO: fix this - triggers a SEGFAULT at deactivation() time.
345 // QList<QMenu*> currentMenus = aDesktop->findChildren<QMenu*>();
346 // QList<QMenu*>::iterator im;
347 // for (im = currentMenus.begin(); im != currentMenus.end(); ++im) {
348 // if(!activeMenus.contains(*im)) {
349 // QString s = (*im)->title();
350 // std::cout << " MENU "<< s.toStdString() << std::endl;
351 // myMenus.append(*im);
355 SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr();
356 QString aPath = resMgr->stringValue("resources", "PARAVIS", QString());
357 if (!aPath.isNull()) {
358 MyCoreApp->loadConfiguration(aPath + QDir::separator() + "ParaViewFilters.xml");
359 MyCoreApp->loadConfiguration(aPath + QDir::separator() + "ParaViewReaders.xml");
360 MyCoreApp->loadConfiguration(aPath + QDir::separator() + "ParaViewSources.xml");
361 MyCoreApp->loadConfiguration(aPath + QDir::separator() + "ParaViewWriters.xml");
364 // Force creation of the PARAVIS engine
368 // Find created toolbars
369 QCoreApplication::processEvents();
371 QList<QToolBar*> allToolbars = aDesktop->findChildren<QToolBar*>();
372 foreach(QToolBar* aBar, allToolbars) {
373 if (!foreignToolbars.contains(aBar)) {
374 myToolbars[aBar] = true;
375 myToolbarBreaks[aBar] = false;
376 aBar->setVisible(false);
377 aBar->toggleViewAction()->setVisible(false);
383 SUIT_ResourceMgr* aResourceMgr = SUIT_Session::session()->resourceMgr();
384 bool isStop = aResourceMgr->booleanValue( "PARAVIS", "stop_trace", false );
387 // Start a timer to schedule asap:
388 // - the connection to the server
390 myInitTimer = new QTimer(aDesktop);
391 QObject::connect(myInitTimer, SIGNAL(timeout()), this, SLOT(onInitTimer()) );
392 myInitTimer->setSingleShot(true);
393 myInitTimer->start(0);
395 // Another timer to regularly push the trace onto the engine:
396 myPushTraceTimer = new QTimer(aDesktop);
397 QObject::connect(myPushTraceTimer, SIGNAL(timeout()), this, SLOT(onPushTraceTimer()) );
398 myPushTraceTimer->setSingleShot(false);
399 myPushTraceTimer->start(500);
402 this->VTKConnect = vtkEventQtSlotConnect::New();
404 vtkProcessModule* pm = vtkProcessModule::GetProcessModule();
406 vtkPVSession* pvs = dynamic_cast<vtkPVSession*>(pm->GetSession());
408 vtkPVProgressHandler* ph = pvs->GetProgressHandler();
410 this->VTKConnect->Connect(ph, vtkCommand::StartEvent,
411 this, SLOT(onStartProgress()));
412 this->VTKConnect->Connect(ph, vtkCommand::EndEvent,
413 this, SLOT(onEndProgress()));
419 bool PVGUI_Module::connectToExternalPVServer()
421 pqServer* server = pqActiveObjects::instance().activeServer();
422 if (server && server->isRemote())
424 // Already connected to an external server, do nothing
425 MESSAGE("connectToExternalPVServer(): Already connected to an external PVServer, won't reconnect.");
429 std::stringstream msg;
431 // Try to connect to the external PVServer - gives priority to an externally specified URL:
432 QString serverUrlEnv = getenv("PARAVIS_PVSERVER_URL");
433 std::string serverUrl;
434 if (!serverUrlEnv.isEmpty())
435 serverUrl = serverUrlEnv.toStdString();
438 // Get the URL from the engine (possibly starting the pvserver)
439 CORBA::String_var url = GetEngine()->FindOrStartPVServer(0); // take the first free port
440 serverUrl = (char *)url;
443 msg << "connectToExternalPVServer(): Trying to connect to the external PVServer '" << serverUrl << "' ...";
446 if (!pqServerConnectReaction::connectToServer(pqServerResource(serverUrl.c_str())))
448 std::stringstream msg2;
449 msg2 << "Error while connecting to the requested pvserver '" << serverUrl;
450 msg2 << "'. Might use default built-in connection instead!" << std::endl;
451 qWarning(msg2.str().c_str()); // will go to the ParaView console (see ParavisMessageOutput below)
452 SUIT_MessageBox::warning( getApp()->desktop(),
453 QString("Error connecting to PVServer"), QString(msg2.str().c_str()));
457 MESSAGE("connectToExternalPVServer(): Connected!");
461 void PVGUI_Module::onStartProgress()
463 QApplication::setOverrideCursor(Qt::WaitCursor);
466 void PVGUI_Module::onEndProgress()
468 QApplication::restoreOverrideCursor();
471 void PVGUI_Module::onDataRepresentationUpdated() {
472 SalomeApp_Study* activeStudy = dynamic_cast<SalomeApp_Study*>(application()->activeStudy());
473 if(!activeStudy) return;
475 activeStudy->Modified();
479 \brief Initialisation timer event - fired only once, after the GUI loop is ready.
480 See creation in initialize().
482 void PVGUI_Module::onInitTimer()
484 #ifndef PARAVIS_WITH_FULL_CORBA
485 connectToExternalPVServer();
491 \brief Get list of embedded macros files
493 QStringList PVGUI_Module::getEmbeddedMacrosList()
495 QString aRootDir = getenv("PARAVIS_ROOT_DIR");
497 QString aSourcePath = aRootDir + "/bin/salome/Macro";
502 QDir aSourceDir(aSourcePath);
503 QStringList aSourceFiles = aSourceDir.entryList(aFilter, QDir::Files);
504 QStringList aFullPathSourceFiles;
505 foreach (QString aMacrosName, aSourceFiles) {
506 aFullPathSourceFiles << aSourceDir.absoluteFilePath(aMacrosName);
508 return aFullPathSourceFiles;
511 void PVGUI_Module::updateMacros()
513 pqPythonManager* aPythonManager = pqPVApplicationCore::instance()->pythonManager();
514 if(!aPythonManager) {
518 foreach (QString aStr, getEmbeddedMacrosList()) {
519 aPythonManager->addMacro(aStr);
525 \brief Get list of compliant dockable GUI elements
526 \param m map to be filled in ("type":"default_position")
528 void PVGUI_Module::windows( QMap<int, int>& m ) const
530 m.insert( LightApp_Application::WT_ObjectBrowser, Qt::LeftDockWidgetArea );
531 m.insert( LightApp_Application::WT_PyConsole, Qt::BottomDockWidgetArea );
532 // ParaView diagnostic output redirected here
533 m.insert( LightApp_Application::WT_LogWindow, Qt::BottomDockWidgetArea );
537 \brief Static method, performs initialization of ParaView session.
538 \return \c true if ParaView has been initialized successfully, otherwise false
540 bool PVGUI_Module::pvInit()
542 // if ( !pqImplementation::Core ){
544 // Obtain command-line arguments
547 QString aOptions = getenv("PARAVIS_OPTIONS");
548 QStringList aOptList = aOptions.split(":", QString::SkipEmptyParts);
549 argv = new char*[aOptList.size() + 1];
550 QStringList args = QApplication::arguments();
551 argv[0] = (args.size() > 0)? strdup(args[0].toLatin1().constData()) : strdup("paravis");
554 foreach (QString aStr, aOptList) {
555 argv[argc] = strdup( aStr.toLatin1().constData() );
558 MyCoreApp = new pqPVApplicationCore (argc, argv);
559 if (MyCoreApp->getOptions()->GetHelpSelected() ||
560 MyCoreApp->getOptions()->GetUnknownArgument() ||
561 MyCoreApp->getOptions()->GetErrorMessage() ||
562 MyCoreApp->getOptions()->GetTellVersion()) {
565 // Connect VTK log messages to SALOME messages (TODO: review this)
566 vtkOutputWindow::SetInstance(PVGUI_OutputWindowAdapter::New());
568 // Create render view:
569 new pqTabbedMultiViewWidget(); // it registers as "MULTIVIEW_WIDGET" on creation
571 for (int i = 0; i < argc; i++)
580 \brief Shows (toShow = true) or hides ParaView view window
582 void PVGUI_Module::showView( bool toShow )
584 SalomeApp_Application* anApp = getApp();
585 PVGUI_ViewManager* viewMgr =
586 dynamic_cast<PVGUI_ViewManager*>( anApp->getViewManager( PVGUI_Viewer::Type(), false ) );
588 viewMgr = new PVGUI_ViewManager( anApp->activeStudy(), anApp->desktop() );
589 anApp->addViewManager( viewMgr );
590 connect( viewMgr, SIGNAL( lastViewClosed( SUIT_ViewManager* ) ),
591 anApp, SLOT( onCloseView( SUIT_ViewManager* ) ) );
594 PVGUI_ViewWindow* pvWnd = dynamic_cast<PVGUI_ViewWindow*>( viewMgr->getActiveView() );
596 pvWnd = dynamic_cast<PVGUI_ViewWindow*>( viewMgr->createViewWindow() );
599 pvWnd->setShown( toShow );
600 if ( toShow ) pvWnd->setFocus();
604 \brief Slot to show help for proxy.
606 void PVGUI_Module::showHelpForProxy( const QString& groupname, const QString& proxyname )
608 pqHelpReaction::showProxyHelp(groupname, proxyname);
613 \brief Slot to show the waiting state.
615 void PVGUI_Module::onPreAccept()
617 getApp()->desktop()->statusBar()->showMessage(tr("STB_PREACCEPT"));
618 QApplication::setOverrideCursor(QCursor(Qt::WaitCursor));
622 \brief Slot to show the ready state.
624 void PVGUI_Module::onPostAccept()
626 getApp()->desktop()->statusBar()->showMessage(tr("STB_POSTACCEPT"), 2000);
627 QTimer::singleShot(0, this, SLOT(endWaitCursor()));
631 \brief Slot to switch off wait cursor.
633 void PVGUI_Module::endWaitCursor()
635 QApplication::restoreOverrideCursor();
639 // \brief Returns the ParaView multi-view manager.
641 //pqTabbedMultiViewWidget* PVGUI_Module::getMultiViewManager() const
643 // return qobject_cast<pqTabbedMultiViewWidget*>(pqApplicationCore::instance()->manager("MULTIVIEW_WIDGET"));
647 static void ParavisMessageOutput(QtMsgType type, const char *msg)
652 vtkOutputWindow::GetInstance()->DisplayText(msg);
655 vtkOutputWindow::GetInstance()->DisplayErrorText(msg);
658 vtkOutputWindow::GetInstance()->DisplayErrorText(msg);
661 vtkOutputWindow::GetInstance()->DisplayErrorText(msg);
669 \brief Activate module.
670 \param study current study
671 \return \c true if activaion is done successfully or 0 to prevent
674 bool PVGUI_Module::activateModule( SUIT_Study* study )
676 myOldMsgHandler = qInstallMsgHandler(ParavisMessageOutput);
678 SUIT_ExceptionHandler::addCleanUpRoutine( paravisCleanUp );
680 storeCommonWindowsState();
682 bool isDone = SalomeApp_Module::activateModule( study );
683 if ( !isDone ) return false;
686 if ( mySourcesMenuId != -1 ) menuMgr()->show(mySourcesMenuId);
687 if ( myFiltersMenuId != -1 ) menuMgr()->show(myFiltersMenuId);
688 if ( myFiltersMenuId != -1 ) menuMgr()->show(myMacrosMenuId);
689 if ( myFiltersMenuId != -1 ) menuMgr()->show(myToolbarsMenuId);
690 setMenuShown( true );
691 setToolShown( true );
693 restoreDockWidgetsState();
695 QMenu* aMenu = menuMgr()->findMenu( myRecentMenuId );
697 QList<QAction*> anActns = aMenu->actions();
698 for (int i = 0; i < anActns.size(); ++i) {
699 QAction* a = anActns.at(i);
705 QList<QMenu*>::iterator it;
706 for (it = myMenus.begin(); it != myMenus.end(); ++it) {
707 QAction* a = (*it)->menuAction();
712 if ( myRecentMenuId != -1 ) menuMgr()->show(myRecentMenuId);
714 // ClientFindOrCreateParavisComponent(PARAVIS::GetCStudy(this));
721 \brief Deactivate module.
722 \param study current study
723 \return \c true if deactivaion is done successfully or 0 to prevent
724 deactivation on error
726 bool PVGUI_Module::deactivateModule( SUIT_Study* study )
728 MESSAGE("PARAVIS deactivation ...")
730 QMenu* aMenu = menuMgr()->findMenu( myRecentMenuId );
732 QList<QAction*> anActns = aMenu->actions();
733 for (int i = 0; i < anActns.size(); ++i) {
734 QAction* a = anActns.at(i);
736 a->setVisible(false);
740 QList<QMenu*>::iterator it;
741 for (it = myMenus.begin(); it != myMenus.end(); ++it) {
742 QAction* a = (*it)->menuAction();
744 a->setVisible(false);
747 QList<QDockWidget*> aStreamingViews = application()->desktop()->findChildren<QDockWidget*>("pqStreamingControls");
748 foreach(QDockWidget* aView, aStreamingViews) {
749 if (!myDockWidgets.contains(aView))
750 myDockWidgets[aView] = aView->isVisible();
753 /*if (pqImplementation::helpWindow) {
754 pqImplementation::helpWindow->hide();
758 menuMgr()->hide(myRecentMenuId);
759 menuMgr()->hide(mySourcesMenuId);
760 menuMgr()->hide(myFiltersMenuId);
761 menuMgr()->hide(myMacrosMenuId);
762 menuMgr()->hide(myToolbarsMenuId);
763 setMenuShown( false );
764 setToolShown( false );
766 saveDockWidgetsState();
768 SUIT_ExceptionHandler::removeCleanUpRoutine( paravisCleanUp );
771 qInstallMsgHandler(myOldMsgHandler);
773 restoreCommonWindowsState();
775 return SalomeApp_Module::deactivateModule( study );
780 \brief Called when application is closed.
782 Process finalize application functionality from ParaView in order to save server settings
783 and nullify application pointer if the application is being closed.
785 \param theApp application
787 void PVGUI_Module::onApplicationClosed( SUIT_Application* theApp )
789 pqApplicationCore::instance()->settings()->sync();
790 int aAppsNb = SUIT_Session::session()->applications().size();
792 deleteTemporaryFiles();
793 MyCoreApp->deleteLater();
795 CAM_Module::onApplicationClosed(theApp);
800 \brief Deletes temporary files created during import operation from VISU
802 void PVGUI_Module::deleteTemporaryFiles()
804 foreach(QString aFile, myTemporaryFiles) {
805 if (QFile::exists(aFile)) {
806 QFile::remove(aFile);
813 \brief Called when study is closed.
815 Removes data model from the \a study.
817 \param study study being closed
819 void PVGUI_Module::studyClosed(SUIT_Study* study)
821 clearParaviewState();
823 SalomeApp_Module::studyClosed(study);
827 \brief Called when study is opened.
829 void PVGUI_Module::onModelOpened()
831 _PTR(Study) studyDS = PARAVIS::GetCStudy(this);
836 _PTR(SComponent) paravisComp =
837 studyDS->FindComponent(GetEngine()->ComponentDataType());
842 _PTR(ChildIterator) anIter(studyDS->NewChildIterator(paravisComp));
843 for (; anIter->More(); anIter->Next()) {
844 _PTR(SObject) aSObj = anIter->Value();
845 _PTR(GenericAttribute) anAttr;
846 if (!aSObj->FindAttribute(anAttr, "AttributeLocalID")) {
849 _PTR(AttributeLocalID) anID(anAttr);
850 if (anID->Value() == PVSTATEID) {
857 \brief Returns IOR of current engine
859 QString PVGUI_Module::engineIOR() const
861 CORBA::String_var anIOR = GetEngine()->GetIOR();
862 return QString(anIOR.in());
867 \brief Open file of format supported by ParaView
869 void PVGUI_Module::openFile(const char* theName)
873 pqLoadDataReaction::loadData(aFiles);
877 * Start trace invoking the newly introduced C++ API (PV 4.2)
878 * (inspired from pqTraceReaction::start())
880 void PVGUI_Module::startTrace()
882 vtkSMSessionProxyManager* pxm = pqActiveObjects::instance().activeServer()->proxyManager();
884 vtkSmartPointer<vtkSMProxy> proxy;
885 proxy.TakeReference(pxm->NewProxy("pythontracing", "PythonTraceOptions"));
888 vtkNew<vtkSMParaViewPipelineController> controller;
889 controller->InitializeProxy(proxy);
891 vtkSMTrace* trace = vtkSMTrace::StartTrace();
894 // Set manually the properties entered via the dialog box poping-up when requiring
895 // a trace start in PV4.2 (trace options)
896 trace->SetPropertiesToTraceOnCreate(vtkSMTrace::RECORD_USER_MODIFIED_PROPERTIES);
897 trace->SetFullyTraceSupplementalProxies(false);
901 void PVGUI_Module::stopTrace()
903 vtkSMTrace::StopTrace();
906 void PVGUI_Module::executeScript(const char *script)
909 pqPythonManager* manager = qobject_cast<pqPythonManager*>(
910 pqApplicationCore::instance()->manager("PYTHON_MANAGER"));
912 pqPythonDialog* pyDiag = manager->pythonShellDialog();
914 pyDiag->runString(script);
921 // * Debug function printing out the given interpreter's execution context
923 //void printInterpContext(PyInterp_Interp * interp )
925 // // Extract __smtraceString from interpreter's context
926 // const PyObject* ctxt = interp->getExecutionContext();
928 // PyObject* lst = PyDict_Keys((PyObject *)ctxt);
929 // Py_ssize_t siz = PyList_GET_SIZE(lst);
930 // for (Py_ssize_t i = 0; i < siz; i++)
932 // PyObject * elem = PyList_GetItem(lst, i);
933 // if (PyString_Check(elem))
935 // std::cout << "At pos:" << i << ", " << PyString_AsString(elem) << std::endl;
938 // std::cout << "At pos:" << i << ", not a string!" << std::endl;
944 \brief Returns trace string
946 static const QString MYReplaceStr("paraview.simple");
947 static const QString MYReplaceImportStr("except: from pvsimple import *");
948 QString PVGUI_Module::getTraceString()
950 vtkSMTrace *tracer = vtkSMTrace::GetActiveTracer();
951 if (!tracer) // trace is not started
954 QString traceString(tracer->GetCurrentTrace());
956 // Replace import "paraview.simple" by "pvsimple"
957 if ((!traceString.isNull()) && traceString.length() != 0) {
958 int aPos = traceString.indexOf(MYReplaceStr);
960 traceString = traceString.replace(aPos, MYReplaceStr.length(), "pvsimple");
961 aPos = traceString.indexOf(MYReplaceStr, aPos);
963 int aImportPos = traceString.indexOf(MYReplaceImportStr);
966 traceString = traceString.replace(aImportPos, MYReplaceImportStr.length(), "except:\n import pvsimple\n from pvsimple import *");
974 \brief Saves trace string to disk file
976 void PVGUI_Module::saveTrace(const char* theName)
979 if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
980 MESSAGE( "Could not open file:" << theName );
983 QTextStream out(&file);
984 out << getTraceString();
989 \brief Saves ParaView state to a disk file
991 void PVGUI_Module::saveParaviewState(const char* theFileName)
993 pqApplicationCore::instance()->saveState(theFileName);
997 \brief Delete all objects for Paraview Pipeline Browser
999 void PVGUI_Module::clearParaviewState()
1001 QAction* deleteAllAction = action(DeleteAllId);
1002 if (deleteAllAction) {
1003 deleteAllAction->activate(QAction::Trigger);
1008 \brief Restores ParaView state from a disk file
1010 If toClear == true, the current ojects will be deleted
1012 void PVGUI_Module::loadParaviewState(const char* theFileName)
1014 pqApplicationCore::instance()->loadState(theFileName, getActiveServer());
1018 \brief Returns current active ParaView server
1020 pqServer* PVGUI_Module::getActiveServer()
1022 return pqApplicationCore::instance()->getActiveServer();
1027 \brief Creates PARAVIS preference pane
1029 void PVGUI_Module::createPreferences()
1031 // Paraview settings tab
1032 int aParaViewSettingsTab = addPreference( tr( "TIT_PVIEWSETTINGS" ) );
1033 int aPanel = addPreference(QString(), aParaViewSettingsTab, LightApp_Preferences::UserDefined, "PARAVIS", "");
1034 setPreferenceProperty(aPanel, "content", (qint64)(new PVGUI_ParaViewSettingsPane()));
1036 // Paravis settings tab
1037 int aParaVisSettingsTab = addPreference( tr( "TIT_PVISSETTINGS" ) );
1038 addPreference( tr( "PREF_STOP_TRACE" ), aParaVisSettingsTab, LightApp_Preferences::Bool, "PARAVIS", "stop_trace");
1040 int aSaveType = addPreference(tr( "PREF_SAVE_TYPE_LBL" ), aParaVisSettingsTab,
1041 LightApp_Preferences::Selector,
1042 "PARAVIS", "savestate_type");
1043 QList<QVariant> aIndices;
1044 QStringList aStrings;
1046 aStrings<<tr("PREF_SAVE_TYPE_0");
1047 aStrings<<tr("PREF_SAVE_TYPE_1");
1048 aStrings<<tr("PREF_SAVE_TYPE_2");
1049 setPreferenceProperty(aSaveType, "strings", aStrings);
1050 setPreferenceProperty(aSaveType, "indexes", aIndices);
1054 \brief Creates ParaViS context menu popup
1056 void PVGUI_Module::contextMenuPopup(const QString& theClient, QMenu* theMenu, QString& theTitle)
1058 SalomeApp_Module::contextMenuPopup(theClient, theMenu, theTitle);
1060 // Check if we are in Object Browser
1061 SUIT_DataBrowser* ob = getApp()->objectBrowser();
1062 bool isOBClient = (ob && theClient == ob->popupClientType());
1067 // Get list of selected objects
1068 LightApp_SelectionMgr* aSelectionMgr = getApp()->selectionMgr();
1069 SALOME_ListIO aListIO;
1070 aSelectionMgr->selectedObjects(aListIO);
1071 if (aListIO.Extent() == 1 && aListIO.First()->hasEntry()) {
1072 QString entry = QString(aListIO.First()->getEntry());
1075 SalomeApp_Study* activeStudy =
1076 dynamic_cast<SalomeApp_Study*>(getApp()->activeStudy());
1081 // Get SALOMEDS client study
1082 _PTR(Study) studyDS = activeStudy->studyDS();
1087 QString paravisDataType(GetEngine()->ComponentDataType());
1088 if(activeStudy && activeStudy->isComponent(entry) &&
1089 activeStudy->componentDataType(entry) == paravisDataType) {
1090 // ParaViS module object
1091 theMenu->addSeparator();
1092 theMenu->addAction(action(SaveStatePopupId));
1095 // Try to get state object
1096 _PTR(SObject) stateSObj =
1097 studyDS->FindObjectID(entry.toLatin1().constData());
1103 _PTR(GenericAttribute) anAttr;
1104 if (!stateSObj->FindAttribute(anAttr, "AttributeLocalID")) {
1108 _PTR(AttributeLocalID) anID(anAttr);
1110 if (anID->Value() == PVSTATEID) {
1111 // Paraview state object
1112 theMenu->addSeparator();
1113 theMenu->addAction(action(AddStatePopupId));
1114 theMenu->addAction(action(CleanAndAddStatePopupId));
1115 theMenu->addSeparator();
1116 theMenu->addAction(action(ParaVisRenameId));
1117 theMenu->addAction(action(ParaVisDeleteId));
1124 \brief. Show ParaView python trace.
1126 void PVGUI_Module::onShowTrace()
1128 if (!myTraceWindow) {
1129 myTraceWindow = new pqPythonScriptEditor(getApp()->desktop());
1131 myTraceWindow->setText(getTraceString());
1132 myTraceWindow->show();
1133 myTraceWindow->raise();
1134 myTraceWindow->activateWindow();
1139 \brief. Re-initialize ParaView python trace.
1141 void PVGUI_Module::onRestartTrace()
1148 \brief Show ParaView view.
1150 void PVGUI_Module::onNewParaViewWindow()
1156 \brief Save state under the module root object.
1158 void PVGUI_Module::onSaveMultiState()
1160 // Create state study object
1162 // Get SALOMEDS client study
1163 _PTR(Study) studyDS = PARAVIS::GetCStudy(this);
1168 _PTR(SComponent) paravisComp =
1169 studyDS->FindComponent(GetEngine()->ComponentDataType());
1174 // Unlock the study if it is locked
1175 bool isLocked = studyDS->GetProperties()->IsLocked();
1177 studyDS->GetProperties()->SetLocked(false);
1180 QString stateName = tr("SAVED_PARAVIEW_STATE_NAME") +
1181 QString::number(myStateCounter + 1);
1183 _PTR(StudyBuilder) studyBuilder = studyDS->NewBuilder();
1184 _PTR(SObject) newSObj = studyBuilder->NewObject(paravisComp);
1187 _PTR(GenericAttribute) anAttr;
1188 anAttr = studyBuilder->FindOrCreateAttribute(newSObj, "AttributeName");
1189 _PTR(AttributeName) nameAttr(anAttr);
1191 nameAttr->SetValue(stateName.toLatin1().constData());
1194 anAttr = studyBuilder->FindOrCreateAttribute(newSObj, "AttributeLocalID");
1195 _PTR(AttributeLocalID) localIdAttr(anAttr);
1197 localIdAttr->SetValue(PVSTATEID);
1200 QString stateEntry = QString::fromStdString(newSObj->GetID());
1202 // File name for state saving
1203 QString tmpDir = QString::fromStdString(SALOMEDS_Tool::GetTmpDir());
1204 QString fileName = QString("%1_paravisstate:%2").arg(tmpDir, stateEntry);
1206 anAttr = studyBuilder->FindOrCreateAttribute(newSObj, "AttributeString");
1207 _PTR(AttributeString) stringAttr(anAttr);
1209 stringAttr->SetValue(fileName.toLatin1().constData());
1211 // Lock the study back if necessary
1213 studyDS->GetProperties()->SetLocked(true);
1217 saveParaviewState(fileName.toLatin1().constData());
1218 myTemporaryFiles.append(fileName);
1220 // Increment the counter
1227 \brief Restore the selected state by merging with the current one.
1229 void PVGUI_Module::onAddState()
1231 loadSelectedState(false);
1235 \brief Clean the current state and restore the selected one.
1237 void PVGUI_Module::onCleanAddState()
1239 loadSelectedState(true);
1243 \brief Rename the selected object.
1245 void PVGUI_Module::onRename()
1247 LightApp_SelectionMgr* aSelectionMgr = getApp()->selectionMgr();
1248 SALOME_ListIO aListIO;
1249 aSelectionMgr->selectedObjects(aListIO);
1251 if (aListIO.Extent() == 1 && aListIO.First()->hasEntry()) {
1252 std::string entry = aListIO.First()->getEntry();
1254 // Get SALOMEDS client study
1255 _PTR(Study) studyDS = PARAVIS::GetCStudy(this);
1260 // Unlock the study if it is locked
1261 bool isLocked = studyDS->GetProperties()->IsLocked();
1263 studyDS->GetProperties()->SetLocked(false);
1266 // Rename the selected state object
1267 _PTR(SObject) stateSObj = studyDS->FindObjectID(entry);
1272 _PTR(GenericAttribute) anAttr;
1273 if (stateSObj->FindAttribute(anAttr, "AttributeName")) {
1274 _PTR(AttributeName) nameAttr (anAttr);
1276 LightApp_NameDlg::getName(getApp()->desktop(), nameAttr->Value().c_str());
1277 if (!newName.isEmpty()) {
1278 nameAttr->SetValue(newName.toLatin1().constData());
1279 aListIO.First()->setName(newName.toLatin1().constData());
1283 // Lock the study back if necessary
1285 studyDS->GetProperties()->SetLocked(true);
1288 // Update object browser
1295 \brief Delete the selected objects.
1297 void PVGUI_Module::onDelete()
1299 LightApp_SelectionMgr* aSelectionMgr = getApp()->selectionMgr();
1300 SALOME_ListIO aListIO;
1301 aSelectionMgr->selectedObjects(aListIO);
1303 if (aListIO.Extent() == 1 && aListIO.First()->hasEntry()) {
1304 std::string entry = aListIO.First()->getEntry();
1306 // Get SALOMEDS client study
1307 _PTR(Study) studyDS = PARAVIS::GetCStudy(this);
1312 // Unlock the study if it is locked
1313 bool isLocked = studyDS->GetProperties()->IsLocked();
1315 studyDS->GetProperties()->SetLocked(false);
1318 // Remove the selected state from the study
1319 _PTR(StudyBuilder) studyBuilder = studyDS->NewBuilder();
1320 _PTR(SObject) stateSObj = studyDS->FindObjectID(entry);
1321 studyBuilder->RemoveObject(stateSObj);
1323 // Lock the study back if necessary
1325 studyDS->GetProperties()->SetLocked(true);
1328 // Update object browser
1333 void PVGUI_Module::onPushTraceTimer()
1335 // MESSAGE("onPushTraceTimer(): Pushing trace to engine...");
1336 GetEngine()->PutPythonTraceStringToEngine(getTraceString().toStdString().c_str());
1340 \brief Discover help project files from the resources.
1341 \return name of the help file.
1343 QString PVGUI_Module::getHelpFileName() {
1344 QString aPVHome(getenv("PVHOME"));
1345 if (aPVHome.isNull()) {
1346 qWarning("Wariable PVHOME is not defined");
1349 QChar aSep = QDir::separator();
1350 //PARAVIEW_VERSION from the vtkPVConfig.h file
1351 QString aFileName = aPVHome + aSep + "share" + aSep + "doc" + aSep + "paraview-"+ PARAVIEW_VERSION + aSep + "paraview.qch";
1357 \brief Load selected paraview state
1359 If toClear == true, the current state will be cleared
1361 void PVGUI_Module::loadSelectedState(bool toClear)
1365 LightApp_SelectionMgr* aSelectionMgr = getApp()->selectionMgr();
1366 SALOME_ListIO aListIO;
1367 aSelectionMgr->selectedObjects(aListIO);
1369 if (aListIO.Extent() == 1 && aListIO.First()->hasEntry()) {
1370 std::string entry = aListIO.First()->getEntry();
1372 // Get SALOMEDS client study
1373 _PTR(Study) studyDS = PARAVIS::GetCStudy(this);
1379 _PTR(SObject) stateSObj = studyDS->FindObjectID(entry);
1380 _PTR(GenericAttribute) anAttr;
1381 if (!stateSObj->FindAttribute(anAttr, "AttributeLocalID")) {
1384 _PTR(AttributeLocalID) anID(anAttr);
1385 if (!anID->Value() == PVSTATEID) {
1389 // Get state file name
1390 if (stateSObj->FindAttribute(anAttr, "AttributeString")) {
1391 _PTR(AttributeString) aStringAttr(anAttr);
1392 QString stringValue(aStringAttr->Value().c_str());
1394 if (QFile::exists(stringValue)) {
1395 fileName = stringValue;
1400 if (!fileName.isEmpty()) {
1402 clearParaviewState();
1405 loadParaviewState(fileName.toLatin1().constData());
1408 SUIT_MessageBox::critical(getApp()->desktop(),
1410 tr("ERR_STATE_CANNOT_BE_RESTORED"));
1415 \fn CAM_Module* createModule();
1416 \brief Export module instance (factory function).
1417 \return new created instance of the module
1421 #define PVGUI_EXPORT __declspec(dllexport)
1423 #define PVGUI_EXPORT
1429 PVGUI_EXPORT CAM_Module* createModule() {
1430 return new PVGUI_Module();
1433 PVGUI_EXPORT char* getModuleVersion() {
1434 return (char*)PARAVIS_VERSION_STR;