X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FPVGUI%2FPVGUI_Module.cxx;h=7ff12a68a8311e789869b864545f866292f72bad;hb=9a125c36043b04592000f5f18078236fb829a65a;hp=0a558e42b785ed81f6981762b7c32d80a078fd78;hpb=5688ded91e1ba4c8c71ab220fb273aa76af5df01;p=modules%2Fparavis.git diff --git a/src/PVGUI/PVGUI_Module.cxx b/src/PVGUI/PVGUI_Module.cxx index 0a558e42..7ff12a68 100644 --- a/src/PVGUI/PVGUI_Module.cxx +++ b/src/PVGUI/PVGUI_Module.cxx @@ -1,12 +1,11 @@ // PARAVIS : ParaView wrapper SALOME module // -// Copyright (C) 2003 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, -// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS +// Copyright (C) 2010-2014 CEA/DEN, EDF R&D // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either -// version 2.1 of the License. +// version 2.1 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -20,25 +19,58 @@ // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com // // File : PVGUI_Module.cxx -// Author : Julia DOROVSKIKH -// +#include // E.A. must be included before Python.h to fix compilation on windows +#ifdef HAVE_FINITE +#undef HAVE_FINITE // VSR: avoid compilation warning on Linux : "HAVE_FINITE" redefined +#endif +#include // Python first #include "PVGUI_Module.h" -#include "PVGUI_Module_impl.h" -#include "PVGUI_ProcessModuleHelper.h" + +#ifdef PARAVIS_WITH_FULL_CORBA +# include "PARAVIS_Gen_i.hh" +#endif + +#include CORBA_SERVER_HEADER(SALOME_ModuleCatalog) +#include CORBA_SERVER_HEADER(SALOMEDS) + #include "PVGUI_ViewModel.h" #include "PVGUI_ViewManager.h" #include "PVGUI_ViewWindow.h" +#include "PVGUI_Tools.h" +#include "PVGUI_ParaViewSettingsPane.h" +#include "PVGUI_OutputWindowAdapter.h" +#include "PVGUI_Behaviors.h" +// SALOME Includes +#include #include #include #include #include -#include +#include +#include + +#include +#include + #include +#include +#include +#include +#include +#include +#include +#include + #include #include +#include + +// External includes +#include + #include #include #include @@ -47,98 +79,62 @@ #include #include #include +#include #include #include #include #include #include +#include +#include +#include +#include + +// Paraview includes +#include // for symbol PARAVIEW_VERSION +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include -#include +#include #include -#include #include #include -#include -#include +#include #include -#include -#include #include -#include -#include -#include -#include - -/* - * Make sure all the kits register their classes with vtkInstantiator. - * Since ParaView uses Tcl wrapping, all of VTK is already compiled in - * anyway. The instantiators will add no more code for the linker to - * collect. - */ - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include -#include -#include -#include - +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include //---------------------------------------------------------------------------- -// ClientServer wrapper initialization functions. -// Taken from ParaView sources (file pqMain.cxx) -extern "C" void vtkCommonCS_Initialize(vtkClientServerInterpreter*); -extern "C" void vtkFilteringCS_Initialize(vtkClientServerInterpreter*); -extern "C" void vtkGenericFilteringCS_Initialize(vtkClientServerInterpreter*); -extern "C" void vtkImagingCS_Initialize(vtkClientServerInterpreter*); -extern "C" void vtkInfovisCS_Initialize(vtkClientServerInterpreter*); -extern "C" void vtkGraphicsCS_Initialize(vtkClientServerInterpreter*); -extern "C" void vtkIOCS_Initialize(vtkClientServerInterpreter*); -extern "C" void vtkRenderingCS_Initialize(vtkClientServerInterpreter*); -extern "C" void vtkVolumeRenderingCS_Initialize(vtkClientServerInterpreter*); -extern "C" void vtkHybridCS_Initialize(vtkClientServerInterpreter*); -extern "C" void vtkWidgetsCS_Initialize(vtkClientServerInterpreter*); -extern "C" void vtkParallelCS_Initialize(vtkClientServerInterpreter*); -extern "C" void vtkPVServerCommonCS_Initialize(vtkClientServerInterpreter*); -extern "C" void vtkPVFiltersCS_Initialize(vtkClientServerInterpreter*); -extern "C" void vtkXdmfCS_Initialize(vtkClientServerInterpreter *); +pqPVApplicationCore* PVGUI_Module::MyCoreApp = 0; -//---------------------------------------------------------------------------- -void ParaViewInitializeInterpreter(vtkProcessModule* pm) -{ - // Initialize built-in wrapper modules. - vtkCommonCS_Initialize(pm->GetInterpreter()); - vtkFilteringCS_Initialize(pm->GetInterpreter()); - vtkGenericFilteringCS_Initialize(pm->GetInterpreter()); - vtkImagingCS_Initialize(pm->GetInterpreter()); - vtkInfovisCS_Initialize(pm->GetInterpreter()); - vtkGraphicsCS_Initialize(pm->GetInterpreter()); - vtkIOCS_Initialize(pm->GetInterpreter()); - vtkRenderingCS_Initialize(pm->GetInterpreter()); - vtkVolumeRenderingCS_Initialize(pm->GetInterpreter()); - vtkHybridCS_Initialize(pm->GetInterpreter()); - vtkWidgetsCS_Initialize(pm->GetInterpreter()); - vtkParallelCS_Initialize(pm->GetInterpreter()); - vtkPVServerCommonCS_Initialize(pm->GetInterpreter()); - vtkPVFiltersCS_Initialize(pm->GetInterpreter()); - vtkXdmfCS_Initialize(pm->GetInterpreter()); -} - -vtkPVMain* PVGUI_Module::pqImplementation::myPVMain = 0; -pqOptions* PVGUI_Module::pqImplementation::myPVOptions = 0; -PVGUI_ProcessModuleHelper* PVGUI_Module::pqImplementation::myPVHelper = 0; +PVGUI_Module* ParavisModule = 0; + +PARAVIS_ORB::PARAVIS_Gen_var PVGUI_Module::myEngine; /*! \mainpage @@ -147,29 +143,13 @@ PVGUI_ProcessModuleHelper* PVGUI_Module::pqImplementation::myPVHelper = 0; As any other SALOME module, PARAVIS requires PARAVIS_ROOT_DIR environment variable to be set to PARAVIS installation directory. Other variables needed for correct detection of ParaView location: - \li PVSRCHOME - points at the root of ParaView source directory tree - \li PVINSTALLHOME - points at the top of ParaView build tree (currently, due to some drawbacks in its buld procedure - ParaView should not be installed, its build directory is used instead). + \li PVHOME - points at the ParaView installation directory tree + \li PVVERSION - number of ParaView version It also requires common SALOME environment including GUI_ROOT_DIR and other prerequsites. - As soon as the environment is set, excute the following commands in a shell: - \code - mkdir PARAVIS_BUILD - cd PARAVIS_BUILD - ../PARAVIS_SRC/build_configure - ../PARAVIS_SRC/configure --prefix=${PARAVIS_ROOT_DIR} - make - make docs - make install - \endcode PARAVIS module can be launched using the following commands: - \li Light SALOME configuration - \code - runLightSalome.sh --modules="PARAVIS" - \endcode - or \li Full SALOME configuration \code runSalome --modules="PARAVIS" @@ -193,33 +173,7 @@ PVGUI_ProcessModuleHelper* PVGUI_Module::pqImplementation::myPVHelper = 0; ParaView client initalization is performed when an instance of PVGUI_Module class has been created and \link PVGUI_Module::initialize() PVGUI_Module::initialize()\endlink method is called by SALOME GUI. The actual client start-up is done in \link PVGUI_Module::pvInit() PVGUI_Module::pvInit()\endlink method. - It simulates actions perfomed by pqMain::Run( QApplication&, pqProcessModuleGUIHelper* ) method. - Custom PVGUI_ProcessModuleHelper class derived from %pqProcessModuleGUIHelper base is the main actor in ParaView - client initialization. It initializes the client that uses the main window (SALOME desktop) supplied from the outside, - it does not start Qt event loop as this is done in SALOME GUI executable (SUITApp or SALOME_Session_Server), and after all - it redirects ParaView diagnostic output to SALOME LogWindow with help of PVGUI_OutputWindowAdapter class. - This is achieved by reimplementing \link PVGUI_ProcessModuleHelper::InitializeApplication() InitializeApplication()\endlink, - \link PVGUI_ProcessModuleHelper::appExec() appExec()\endlink, \link PVGUI_ProcessModuleHelper::postAppExec() postAppExec()\endlink - virtual methods as well as those responsible for main window management. - -

ParaView GUI connection to SALOME desktop

- - ParaView Qt components include pqMainWindowCore class that handles most ParaView GUI client actions, - updates menu states and connects many GUI components. - After the client initalization \link PVGUI_Module::initialize() PVGUI_Module::initialize()\endlink method creates - an instance of internal PVGUI_Module::pqImplementation class (declared PVGUI_Module_impl.h) that wraps some ParaView GUI components: - pqMainWindowCore, pqServer, etc. Instance of SALOME desktop widget is passed to pqMainWindowCore instead of ParaView main window. - - Basically it simulates constructor of ParaView client's %MainWindow class (src/Applications/Client/MainWindow.cxx). It creates the same - menu and toolbar commands using SALOME menu and toolbar managers, connecting the actions to %pqMainWindowCore slots or to the module's - slots in some cases. It also sets up dock widgets for ParaView widgets, such as object inspector, pipeline browser, etc. - - ParaView GUI resources (icons) are reused directly from the ParaView resource directory, they are loaded into SALOME GUI - resource manager, the path to these icons is specified in PARAVIS configuration XML files (LightApp.xml and SlomeApp.xml). - - As both SALOME destop and ParaView main window classes inherit QMainWindow and %pqMainWindowCore deals with QMainWindow API to control - menus, tollbars and dock widgets, its integration into SALOME GUI is straightforward and smooth.

Multi-view manager

@@ -241,29 +195,61 @@ PVGUI_ProcessModuleHelper* PVGUI_Module::pqImplementation::myPVHelper = 0;

ParaView plugins

ParaView server and client plugins are managed by %pqMainWindowCore slots that has full access to PARAVIS menus and toolbars. As a result they appears automatically in PARAVIS menus and toolbars if loaded successfully. - -

Limitations of 2008 year prototype

- \li SALOME persistence (possibility to save the module data into a tsudy file) is not implemented for PARAVIS module. - \li As a light module, PARAVIS does not have a CORBA engine that follows SALOME rules, however PARAVIS can use load a CORBA engine - on its own if needed. */ /*! \class PVGUI_Module - \brief Implementation of light (no-CORBA-engine) + \brief Implementation SALOME module wrapping ParaView GUI. */ +/*! + Clean up function; used to stop ParaView progress events when + exception is caught by global exception handler. +*/ +void paravisCleanUp() +{ + if ( pqApplicationCore::instance() ) { + pqServer* s = pqApplicationCore::instance()->getActiveServer(); + if ( s ) s->session()->GetProgressHandler()->CleanupPendingProgress(); + } +} + /*! \brief Constructor. Sets the default name for the module. */ PVGUI_Module::PVGUI_Module() - : LightApp_Module( "PARAVIS" ), - Implementation( 0 ), + : SalomeApp_Module( "PARAVIS" ), mySelectionControlsTb( -1 ), mySourcesMenuId( -1 ), - myFiltersMenuId( -1 ) + myFiltersMenuId( -1 ), + myMacrosMenuId(-1), + myToolbarsMenuId(-1), + myRecentMenuId(-1), + myOldMsgHandler(0), + myTraceWindow(0), + myStateCounter(0), + myInitTimer(0), + myPushTraceTimer(0) { +#ifdef HAS_PV_DOC + Q_INIT_RESOURCE( PVGUI ); +#endif + ParavisModule = this; + + // Clear old copies of embedded macros files + QString aDestPath = QString( "%1/.config/%2/Macros" ).arg( QDir::homePath() ).arg( QApplication::applicationName() ); + QStringList aFilter; + aFilter << "*.py"; + + QDir aDestDir(aDestPath); + QStringList aDestFiles = aDestDir.entryList(aFilter, QDir::Files); + foreach (QString aMacrosPath, getEmbeddedMacrosList()) { + QString aMacrosName = QFileInfo(aMacrosPath).fileName(); + if (aDestFiles.contains(aMacrosName)) { + aDestDir.remove(aMacrosName); + } + } } /*! @@ -271,6 +257,28 @@ PVGUI_Module::PVGUI_Module() */ PVGUI_Module::~PVGUI_Module() { + if (myPushTraceTimer) + delete myPushTraceTimer; + if (myInitTimer) + delete myInitTimer; + // Disconnect from server + pqServer* server = pqActiveObjects::instance().activeServer(); + if (server && server->isRemote()) + { + MESSAGE("~PVGUI_Module(): Disconnecting from remote server ..."); + pqServerDisconnectReaction::disconnectFromServer(); + } +} + +PARAVIS_ORB::PARAVIS_Gen_var PVGUI_Module::GetEngine() +{ + // initialize PARAVIS module engine (load, if necessary) + if ( CORBA::is_nil( myEngine ) ) { + Engines::EngineComponent_var comp = + SalomeApp_Application::lcc()->FindOrLoad_Component( "FactoryServer", "PARAVIS" ); + myEngine = PARAVIS_ORB::PARAVIS_Gen::_narrow( comp ); + } + return myEngine; } /*! @@ -279,7 +287,12 @@ PVGUI_Module::~PVGUI_Module() */ void PVGUI_Module::initialize( CAM_Application* app ) { - LightApp_Module::initialize( app ); + SalomeApp_Module::initialize( app ); + + // Create ParaViS actions + createActions(); + // Create ParaViS menus + createMenus(); // Uncomment to debug ParaView initialization // "aa" used instead of "i" as GDB doesn't like "i" variables :) @@ -294,25 +307,220 @@ void PVGUI_Module::initialize( CAM_Application* app ) pvInit(); // Create GUI elements (menus, toolbars, dock widgets) - if ( !Implementation ){ - LightApp_Application* anApp = getApp(); + SalomeApp_Application* anApp = getApp(); + SUIT_Desktop* aDesktop = anApp->desktop(); - // Simulate ParaView client main window - Implementation = new pqImplementation( anApp->desktop() ); + // Remember current state of desktop toolbars + QList foreignToolbars = aDesktop->findChildren(); - setupDockWidgets(); - - pvCreateActions(); - pvCreateMenus(); - pvCreateToolBars(); - - setupDockWidgetsContextMenu(); + setupDockWidgets(); - // Now that we're ready, initialize everything ... - Implementation->Core.initializeStates(); + pvCreateActions(); + pvCreateToolBars(); + pvCreateMenus(); + + QList activeDocks = aDesktop->findChildren(); + QList activeMenus = aDesktop->findChildren(); + + PVGUI_Behaviors * behav = new PVGUI_Behaviors(this); + behav->instanciateAllBehaviors(aDesktop); + + // Setup quick-launch shortcuts. + QShortcut *ctrlSpace = new QShortcut(Qt::CTRL + Qt::Key_Space, aDesktop); + QObject::connect(ctrlSpace, SIGNAL(activated()), + pqApplicationCore::instance(), SLOT(quickLaunch())); + + // Find Plugin Dock Widgets + QList currentDocks = aDesktop->findChildren(); + QList::iterator i; + for (i = currentDocks.begin(); i != currentDocks.end(); ++i) { + if(!activeDocks.contains(*i)) { + myDockWidgets[*i] = false; // hidden by default + (*i)->hide(); + } + } + + // Find Plugin Menus + // [ABN] TODO: fix this - triggers a SEGFAULT at deactivation() time. +// QList currentMenus = aDesktop->findChildren(); +// QList::iterator im; +// for (im = currentMenus.begin(); im != currentMenus.end(); ++im) { +// if(!activeMenus.contains(*im)) { +// QString s = (*im)->title(); +// std::cout << " MENU "<< s.toStdString() << std::endl; +// myMenus.append(*im); +// } +// } + + SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr(); + QString aPath = resMgr->stringValue("resources", "PARAVIS", QString()); + if (!aPath.isNull()) { + MyCoreApp->loadConfiguration(aPath + QDir::separator() + "ParaViewFilters.xml"); + MyCoreApp->loadConfiguration(aPath + QDir::separator() + "ParaViewReaders.xml"); + MyCoreApp->loadConfiguration(aPath + QDir::separator() + "ParaViewSources.xml"); + MyCoreApp->loadConfiguration(aPath + QDir::separator() + "ParaViewWriters.xml"); + } + + // Force creation of the PARAVIS engine + GetEngine(); + updateObjBrowser(); + + // Find created toolbars + QCoreApplication::processEvents(); + + QList allToolbars = aDesktop->findChildren(); + foreach(QToolBar* aBar, allToolbars) { + if (!foreignToolbars.contains(aBar)) { + myToolbars[aBar] = true; + myToolbarBreaks[aBar] = false; + aBar->setVisible(false); + aBar->toggleViewAction()->setVisible(false); + } + } + + updateMacros(); + + SUIT_ResourceMgr* aResourceMgr = SUIT_Session::session()->resourceMgr(); + bool isStop = aResourceMgr->booleanValue( "PARAVIS", "stop_trace", false ); + if(!isStop) + { + // Start a timer to schedule asap: + // - the connection to the server + // - the trace start + myInitTimer = new QTimer(aDesktop); + QObject::connect(myInitTimer, SIGNAL(timeout()), this, SLOT(onInitTimer()) ); + myInitTimer->setSingleShot(true); + myInitTimer->start(0); + + // Another timer to regularly push the trace onto the engine: + myPushTraceTimer = new QTimer(aDesktop); + QObject::connect(myPushTraceTimer, SIGNAL(timeout()), this, SLOT(onPushTraceTimer()) ); + myPushTraceTimer->setSingleShot(false); + myPushTraceTimer->start(500); + } + + this->VTKConnect = vtkEventQtSlotConnect::New(); + + vtkProcessModule* pm = vtkProcessModule::GetProcessModule(); + if(pm) { + vtkPVSession* pvs = dynamic_cast(pm->GetSession()); + if(pvs) { + vtkPVProgressHandler* ph = pvs->GetProgressHandler(); + if(ph) { + this->VTKConnect->Connect(ph, vtkCommand::StartEvent, + this, SLOT(onStartProgress())); + this->VTKConnect->Connect(ph, vtkCommand::EndEvent, + this, SLOT(onEndProgress())); + } + } } } +bool PVGUI_Module::connectToExternalPVServer() +{ + pqServer* server = pqActiveObjects::instance().activeServer(); + if (server && server->isRemote()) + { + // Already connected to an external server, do nothing + MESSAGE("connectToExternalPVServer(): Already connected to an external PVServer, won't reconnect."); + return false; + } + + std::stringstream msg; + + // Try to connect to the external PVServer - gives priority to an externally specified URL: + QString serverUrlEnv = getenv("PARAVIS_PVSERVER_URL"); + std::string serverUrl; + if (!serverUrlEnv.isEmpty()) + serverUrl = serverUrlEnv.toStdString(); + else + { + // Get the URL from the engine (possibly starting the pvserver) + CORBA::String_var url = GetEngine()->FindOrStartPVServer(0); // take the first free port + serverUrl = (char *)url; + } + + msg << "connectToExternalPVServer(): Trying to connect to the external PVServer '" << serverUrl << "' ..."; + MESSAGE(msg.str()); + + if (!pqServerConnectReaction::connectToServer(pqServerResource(serverUrl.c_str()))) + { + std::stringstream msg2; + msg2 << "Error while connecting to the requested pvserver '" << serverUrl; + msg2 << "'. Might use default built-in connection instead!" << std::endl; + qWarning(msg2.str().c_str()); // will go to the ParaView console (see ParavisMessageOutput below) + SUIT_MessageBox::warning( getApp()->desktop(), + QString("Error connecting to PVServer"), QString(msg2.str().c_str())); + return false; + } + else + MESSAGE("connectToExternalPVServer(): Connected!"); + return true; +} + +void PVGUI_Module::onStartProgress() +{ + QApplication::setOverrideCursor(Qt::WaitCursor); +} + +void PVGUI_Module::onEndProgress() +{ + QApplication::restoreOverrideCursor(); +} + +void PVGUI_Module::onDataRepresentationUpdated() { + SalomeApp_Study* activeStudy = dynamic_cast(application()->activeStudy()); + if(!activeStudy) return; + + activeStudy->Modified(); +} + +/*! + \brief Initialisation timer event - fired only once, after the GUI loop is ready. + See creation in initialize(). +*/ +void PVGUI_Module::onInitTimer() +{ +#ifndef PARAVIS_WITH_FULL_CORBA + connectToExternalPVServer(); +#endif + startTrace(); +} + +/*! + \brief Get list of embedded macros files +*/ +QStringList PVGUI_Module::getEmbeddedMacrosList() +{ + QString aRootDir = getenv("PARAVIS_ROOT_DIR"); + + QString aSourcePath = aRootDir + "/bin/salome/Macro"; + + QStringList aFilter; + aFilter << "*.py"; + + QDir aSourceDir(aSourcePath); + QStringList aSourceFiles = aSourceDir.entryList(aFilter, QDir::Files); + QStringList aFullPathSourceFiles; + foreach (QString aMacrosName, aSourceFiles) { + aFullPathSourceFiles << aSourceDir.absoluteFilePath(aMacrosName); + } + return aFullPathSourceFiles; +} + +void PVGUI_Module::updateMacros() +{ + pqPythonManager* aPythonManager = pqPVApplicationCore::instance()->pythonManager(); + if(!aPythonManager) { + return; + } + + foreach (QString aStr, getEmbeddedMacrosList()) { + aPythonManager->addMacro(aStr); + } +} + + /*! \brief Get list of compliant dockable GUI elements \param m map to be filled in ("type":"default_position") @@ -331,62 +539,51 @@ void PVGUI_Module::windows( QMap& m ) const */ bool PVGUI_Module::pvInit() { - if ( !pqImplementation::myPVMain ){ + // if ( !pqImplementation::Core ){ + if ( ! MyCoreApp) { // Obtain command-line arguments int argc = 0; + char** argv = 0; + QString aOptions = getenv("PARAVIS_OPTIONS"); + QStringList aOptList = aOptions.split(":", QString::SkipEmptyParts); + argv = new char*[aOptList.size() + 1]; QStringList args = QApplication::arguments(); - char** argv = new char*[args.size()]; - for ( QStringList::const_iterator it = args.begin(); argc < 1 && it != args.end(); it++, argc++ ) - argv[argc] = strdup( (*it).toLatin1().constData() ); + argv[0] = (args.size() > 0)? strdup(args[0].toLatin1().constData()) : strdup("paravis"); + argc++; - vtkPVMain::SetInitializeMPI(0); // pvClient never runs with MPI. - vtkPVMain::Initialize(&argc, &argv); // Perform any initializations. - - // TODO: Set plugin dir from preferences - //QApplication::setLibraryPaths(QStringList(dir.absolutePath())); - - pqImplementation::myPVMain = vtkPVMain::New(); - if ( !pqImplementation::myPVOptions ) - pqImplementation::myPVOptions = pqOptions::New(); - if ( !pqImplementation::myPVHelper ) - pqImplementation::myPVHelper = PVGUI_ProcessModuleHelper::New(); - - pqImplementation::myPVOptions->SetProcessType(vtkPVOptions::PVCLIENT); - - // This creates the Process Module and initializes it. - int ret = pqImplementation::myPVMain->Initialize(pqImplementation::myPVOptions, - pqImplementation::myPVHelper, - ParaViewInitializeInterpreter, - argc, argv); - if (!ret){ - // Tell process module that we support Multiple connections. - // This must be set before starting the event loop. - vtkProcessModule::GetProcessModule()->SupportMultipleConnectionsOn(); - ret = pqImplementation::myPVHelper->Run(pqImplementation::myPVOptions); + foreach (QString aStr, aOptList) { + argv[argc] = strdup( aStr.toLatin1().constData() ); + argc++; } - + MyCoreApp = new pqPVApplicationCore (argc, argv); + if (MyCoreApp->getOptions()->GetHelpSelected() || + MyCoreApp->getOptions()->GetUnknownArgument() || + MyCoreApp->getOptions()->GetErrorMessage() || + MyCoreApp->getOptions()->GetTellVersion()) { + return false; + } + // Connect VTK log messages to SALOME messages (TODO: review this) + vtkOutputWindow::SetInstance(PVGUI_OutputWindowAdapter::New()); + + // Create render view: + new pqTabbedMultiViewWidget(); // it registers as "MULTIVIEW_WIDGET" on creation + + for (int i = 0; i < argc; i++) + free(argv[i]); delete[] argv; - return !ret; } return true; } -/*! - \brief Static method, cleans up ParaView session at application exit. Not yet implemented. -*/ -void PVGUI_Module::pvShutdown() -{ - // TODO... -} - /*! \brief Shows (toShow = true) or hides ParaView view window */ void PVGUI_Module::showView( bool toShow ) { - LightApp_Application* anApp = getApp(); - PVGUI_ViewManager* viewMgr = dynamic_cast( anApp->getViewManager( PVGUI_Viewer::Type(), false ) ); + SalomeApp_Application* anApp = getApp(); + PVGUI_ViewManager* viewMgr = + dynamic_cast( anApp->getViewManager( PVGUI_Viewer::Type(), false ) ); if ( !viewMgr ) { viewMgr = new PVGUI_ViewManager( anApp->activeStudy(), anApp->desktop() ); anApp->addViewManager( viewMgr ); @@ -397,429 +594,821 @@ void PVGUI_Module::showView( bool toShow ) PVGUI_ViewWindow* pvWnd = dynamic_cast( viewMgr->getActiveView() ); if ( !pvWnd ) { pvWnd = dynamic_cast( viewMgr->createViewWindow() ); - pvWnd->setMultiViewManager( &Implementation->Core.multiViewManager() ); } pvWnd->setShown( toShow ); + if ( toShow ) pvWnd->setFocus(); } /*! - \brief Manage the label of Undo operation. + \brief Slot to show help for proxy. */ -void PVGUI_Module::onUndoLabel( const QString& label ) +void PVGUI_Module::showHelpForProxy( const QString& groupname, const QString& proxyname ) { - action(UndoId)->setText( - label.isEmpty() ? tr("MEN_CANTUNDO") : QString(tr("MEN_UNDO_ACTION")).arg(label)); - action(UndoId)->setStatusTip( - label.isEmpty() ? tr("MEN_CANTUNDO") : QString(tr("MEN_UNDO_ACTION_TIP")).arg(label)); + pqHelpReaction::showProxyHelp(groupname, proxyname); } + /*! - \brief Manage the label of Redo operation. + \brief Slot to show the waiting state. */ -void PVGUI_Module::onRedoLabel( const QString& label ) +void PVGUI_Module::onPreAccept() { - action(RedoId)->setText( - label.isEmpty() ? tr("MEN_CANTREDO") : QString(tr("MEN_REDO_ACTION")).arg(label)); - action(RedoId)->setStatusTip( - label.isEmpty() ? tr("MEN_CANTREDO") : QString(tr("MEN_REDO_ACTION_TIP")).arg(label)); + getApp()->desktop()->statusBar()->showMessage(tr("STB_PREACCEPT")); + QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); } /*! - \brief Manage the label of Undo Camera operation. + \brief Slot to show the ready state. */ -void PVGUI_Module::onCameraUndoLabel( const QString& label ) +void PVGUI_Module::onPostAccept() { - action(CameraUndoId)->setText( - label.isEmpty() ? tr("MEN_CANT_CAMERA_UNDO") : QString(tr("MEN_CAMERA_UNDO_ACTION")).arg(label)); - action(CameraUndoId)->setStatusTip( - label.isEmpty() ? tr("MEN_CANT_CAMERA_UNDO") : QString(tr("MEN_CAMERA_UNDO_ACTION_TIP")).arg(label)); + getApp()->desktop()->statusBar()->showMessage(tr("STB_POSTACCEPT"), 2000); + QTimer::singleShot(0, this, SLOT(endWaitCursor())); } /*! - \brief Manage the label of Redo Camera operation. + \brief Slot to switch off wait cursor. */ -void PVGUI_Module::onCameraRedoLabel( const QString& label ) +void PVGUI_Module::endWaitCursor() { - action(CameraRedoId)->setText( - label.isEmpty() ? tr("MEN_CANT_CAMERA_REDO") : QString(tr("MEN_CAMERA_REDO_ACTION")).arg(label)); - action(CameraRedoId)->setStatusTip( - label.isEmpty() ? tr("MEN_CANT_CAMERA_REDO") : QString(tr("MEN_CAMERA_REDO_ACTION_TIP")).arg(label)); + QApplication::restoreOverrideCursor(); } +///*! +// \brief Returns the ParaView multi-view manager. +//*/ +//pqTabbedMultiViewWidget* PVGUI_Module::getMultiViewManager() const +//{ +// return qobject_cast(pqApplicationCore::instance()->manager("MULTIVIEW_WIDGET")); +//} + + +static void ParavisMessageOutput(QtMsgType type, const char *msg) +{ + switch(type) + { + case QtDebugMsg: + vtkOutputWindow::GetInstance()->DisplayText(msg); + break; + case QtWarningMsg: + vtkOutputWindow::GetInstance()->DisplayErrorText(msg); + break; + case QtCriticalMsg: + vtkOutputWindow::GetInstance()->DisplayErrorText(msg); + break; + case QtFatalMsg: + vtkOutputWindow::GetInstance()->DisplayErrorText(msg); + break; + } +} + + + /*! - \brief Slot to delete all objects. + \brief Activate module. + \param study current study + \return \c true if activaion is done successfully or 0 to prevent + activation on error */ -void PVGUI_Module::onDeleteAll() +bool PVGUI_Module::activateModule( SUIT_Study* study ) { - pqObjectBuilder* builder = pqApplicationCore::instance()->getObjectBuilder(); - Implementation->Core.getApplicationUndoStack()->beginUndoSet("Delete All"); - builder->destroyPipelineProxies(); - Implementation->Core.getApplicationUndoStack()->endUndoSet(); + myOldMsgHandler = qInstallMsgHandler(ParavisMessageOutput); + + SUIT_ExceptionHandler::addCleanUpRoutine( paravisCleanUp ); + + storeCommonWindowsState(); + + bool isDone = SalomeApp_Module::activateModule( study ); + if ( !isDone ) return false; + + showView( true ); + if ( mySourcesMenuId != -1 ) menuMgr()->show(mySourcesMenuId); + if ( myFiltersMenuId != -1 ) menuMgr()->show(myFiltersMenuId); + if ( myFiltersMenuId != -1 ) menuMgr()->show(myMacrosMenuId); + if ( myFiltersMenuId != -1 ) menuMgr()->show(myToolbarsMenuId); + setMenuShown( true ); + setToolShown( true ); + + restoreDockWidgetsState(); + + QMenu* aMenu = menuMgr()->findMenu( myRecentMenuId ); + if(aMenu) { + QList anActns = aMenu->actions(); + for (int i = 0; i < anActns.size(); ++i) { + QAction* a = anActns.at(i); + if(a) + a->setVisible(true); + } + } + + QList::iterator it; + for (it = myMenus.begin(); it != myMenus.end(); ++it) { + QAction* a = (*it)->menuAction(); + if(a) + a->setVisible(true); + } + + if ( myRecentMenuId != -1 ) menuMgr()->show(myRecentMenuId); + +// ClientFindOrCreateParavisComponent(PARAVIS::GetCStudy(this)); + + return isDone; } + /*! - \brief Slot to check/uncheck the action for corresponding selection mode. + \brief Deactivate module. + \param study current study + \return \c true if deactivaion is done successfully or 0 to prevent + deactivation on error */ -void PVGUI_Module::onSelectionModeChanged( int mode ) +bool PVGUI_Module::deactivateModule( SUIT_Study* study ) { - if( toolMgr()->toolBar( mySelectionControlsTb )->isEnabled() ) { - if(mode == pqRubberBandHelper::SELECT) //surface selection - action(SelectCellsOnId)->setChecked(true); - else if(mode == pqRubberBandHelper::SELECT_POINTS) //surface selection - action(SelectPointsOnId)->setChecked(true); - else if(mode == pqRubberBandHelper::FRUSTUM) - action(SelectCellsThroughId)->setChecked(true); - else if(mode == pqRubberBandHelper::FRUSTUM_POINTS) - action(SelectPointsThroughId)->setChecked(true); - else if (mode == pqRubberBandHelper::BLOCKS) - action(SelectBlockId)->setChecked(true); - else // INTERACT - action(InteractId)->setChecked(true); + MESSAGE("PARAVIS deactivation ...") + + QMenu* aMenu = menuMgr()->findMenu( myRecentMenuId ); + if(aMenu) { + QList anActns = aMenu->actions(); + for (int i = 0; i < anActns.size(); ++i) { + QAction* a = anActns.at(i); + if(a) + a->setVisible(false); + } + } + + QList::iterator it; + for (it = myMenus.begin(); it != myMenus.end(); ++it) { + QAction* a = (*it)->menuAction(); + if(a) + a->setVisible(false); + } + + QList aStreamingViews = application()->desktop()->findChildren("pqStreamingControls"); + foreach(QDockWidget* aView, aStreamingViews) { + if (!myDockWidgets.contains(aView)) + myDockWidgets[aView] = aView->isVisible(); } + + /*if (pqImplementation::helpWindow) { + pqImplementation::helpWindow->hide(); + }*/ + showView( false ); + // hide menus + menuMgr()->hide(myRecentMenuId); + menuMgr()->hide(mySourcesMenuId); + menuMgr()->hide(myFiltersMenuId); + menuMgr()->hide(myMacrosMenuId); + menuMgr()->hide(myToolbarsMenuId); + setMenuShown( false ); + setToolShown( false ); + + saveDockWidgetsState(); + + SUIT_ExceptionHandler::removeCleanUpRoutine( paravisCleanUp ); + + if (myOldMsgHandler) + qInstallMsgHandler(myOldMsgHandler); + + restoreCommonWindowsState(); + + return SalomeApp_Module::deactivateModule( study ); } + /*! - \brief Slot to manage the change of axis center. + \brief Called when application is closed. + + Process finalize application functionality from ParaView in order to save server settings + and nullify application pointer if the application is being closed. + + \param theApp application */ -void PVGUI_Module::onShowCenterAxisChanged( bool enabled ) +void PVGUI_Module::onApplicationClosed( SUIT_Application* theApp ) { - action(ShowCenterId)->setEnabled(enabled); - action(ShowCenterId)->blockSignals(true); - pqRenderView* renView = qobject_cast( - pqActiveView::instance().current()); - action(ShowCenterId)->setChecked( renView ? renView->getCenterAxesVisibility() : false); - action(ShowCenterId)->blockSignals(false); + pqApplicationCore::instance()->settings()->sync(); + int aAppsNb = SUIT_Session::session()->applications().size(); + if (aAppsNb == 1) { + deleteTemporaryFiles(); + MyCoreApp->deleteLater(); + } + CAM_Module::onApplicationClosed(theApp); } + /*! - \brief Slot to set tooltips for the first anf the last frames, i.e. a time range of animation. + \brief Deletes temporary files created during import operation from VISU */ -void PVGUI_Module::setTimeRanges( double start, double end ) +void PVGUI_Module::deleteTemporaryFiles() { - action(FirstFrameId)->setToolTip(QString("First Frame (%1)").arg(start, 0, 'g')); - action(LastFrameId)->setToolTip(QString("Last Frame (%1)").arg(end, 0, 'g')); + foreach(QString aFile, myTemporaryFiles) { + if (QFile::exists(aFile)) { + QFile::remove(aFile); + } + } } + /*! - \brief Slot to manage the plaing process of animation. + \brief Called when study is closed. + + Removes data model from the \a study. + + \param study study being closed */ -void PVGUI_Module::onPlaying( bool playing ) +void PVGUI_Module::studyClosed(SUIT_Study* study) { - SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr(); - if(playing) { - disconnect( action(PlayId), SIGNAL( triggered() ), - &Implementation->Core.VCRController(), SLOT( onPlay() ) ); - connect( action(PlayId), SIGNAL( triggered() ), - &Implementation->Core.VCRController(), SLOT( onPause() ) ); - action(PlayId)->setIcon(QIcon(resMgr->loadPixmap("ParaView",tr("ICON_PAUSE"),false))); - action(PlayId)->setText("Pa&use"); - } - else { - connect( action(PlayId), SIGNAL( triggered() ), - &Implementation->Core.VCRController(), SLOT( onPlay() ) ); - disconnect( action(PlayId), SIGNAL( triggered() ), - &Implementation->Core.VCRController(), SLOT( onPause() ) ); - action(PlayId)->setIcon(QIcon(resMgr->loadPixmap("ParaView",tr("ICON_PLAY"),false))); - action(PlayId)->setText("&Play"); - } + clearParaviewState(); - Implementation->Core.setSelectiveEnabledState(!playing); + SalomeApp_Module::studyClosed(study); } /*! - \brief Slot to add camera link. + \brief Called when study is opened. */ -void PVGUI_Module::onAddCameraLink() +void PVGUI_Module::onModelOpened() { - pqView* vm = pqActiveView::instance().current(); - pqRenderView* rm = qobject_cast(vm); - if(rm) rm->linkToOtherView(); - else SUIT_MessageBox::warning(getApp()->desktop(), - tr("WARNING"), tr("WRN_ADD_CAMERA_LINK")); + _PTR(Study) studyDS = PARAVIS::GetCStudy(this); + if(!studyDS) { + return; + } + + _PTR(SComponent) paravisComp = + studyDS->FindComponent(GetEngine()->ComponentDataType()); + if(!paravisComp) { + return; + } + + _PTR(ChildIterator) anIter(studyDS->NewChildIterator(paravisComp)); + for (; anIter->More(); anIter->Next()) { + _PTR(SObject) aSObj = anIter->Value(); + _PTR(GenericAttribute) anAttr; + if (!aSObj->FindAttribute(anAttr, "AttributeLocalID")) { + continue; + } + _PTR(AttributeLocalID) anID(anAttr); + if (anID->Value() == PVSTATEID) { + myStateCounter++; + } + } } /*! - \brief Slot to show information about ParaView. + \brief Returns IOR of current engine */ -void PVGUI_Module::onHelpAbout() +QString PVGUI_Module::engineIOR() const { - pqClientAboutDialog* const dialog = new pqClientAboutDialog(getApp()->desktop()); - dialog->setAttribute(Qt::WA_DeleteOnClose); - dialog->show(); + CORBA::String_var anIOR = GetEngine()->GetIOR(); + return QString(anIOR.in()); } + /*! - \brief Slot to show help for proxy. + \brief Open file of format supported by ParaView */ -void PVGUI_Module::showHelpForProxy( const QString& proxy ) +void PVGUI_Module::openFile(const char* theName) { - // make sure assistant is ready - this->makeAssistant(); + QStringList aFiles; + aFiles<Implementation->AssistantClient) { - this->Implementation->AssistantClient->openAssistant(); - QString page("%1/Documentation/%2.html"); - page = page.arg(this->Implementation->DocumentationDir); - page = page.arg(proxy); - this->Implementation->AssistantClient->showPage(page); - } +/**! + * Start trace invoking the newly introduced C++ API (PV 4.2) + * (inspired from pqTraceReaction::start()) + */ +void PVGUI_Module::startTrace() +{ + vtkSMSessionProxyManager* pxm = pqActiveObjects::instance().activeServer()->proxyManager(); + + vtkSmartPointer proxy; + proxy.TakeReference(pxm->NewProxy("pythontracing", "PythonTraceOptions")); + if (proxy) + { + vtkNew controller; + controller->InitializeProxy(proxy); + } + vtkSMTrace* trace = vtkSMTrace::StartTrace(); + if (proxy) + { + // Set manually the properties entered via the dialog box poping-up when requiring + // a trace start in PV4.2 (trace options) + trace->SetPropertiesToTraceOnCreate(vtkSMTrace::RECORD_USER_MODIFIED_PROPERTIES); + trace->SetFullyTraceSupplementalProxies(false); + } } -QString Locate( const QString& appName ) +void PVGUI_Module::stopTrace() { - QString app_dir = QCoreApplication::applicationDirPath(); - const char* inst_dirs[] = { - "/./", - "/../bin/", - "/../../bin/", - 0 - }; - for (const char** dir = inst_dirs; *dir; ++dir) { - QString path = app_dir; - path += *dir; - path += appName; - //cout << "Checking : " << path.toAscii().data() << " ... "; - //cout.flush(); - QFileInfo finfo (path); - if (finfo.exists()) { - //cout << " Success!" << endl; - return path; + vtkSMTrace::StopTrace(); +} + +void PVGUI_Module::executeScript(const char *script) +{ +#ifndef WNT + pqPythonManager* manager = qobject_cast( + pqApplicationCore::instance()->manager("PYTHON_MANAGER")); + if (manager) { + pqPythonDialog* pyDiag = manager->pythonShellDialog(); + if (pyDiag) { + pyDiag->runString(script); + } } - //cout << " Failed" << endl; - } - return app_dir + QDir::separator() + appName; +#endif } +///** +// * Debug function printing out the given interpreter's execution context +// */ +//void printInterpContext(PyInterp_Interp * interp ) +//{ +// // Extract __smtraceString from interpreter's context +// const PyObject* ctxt = interp->getExecutionContext(); +// +// PyObject* lst = PyDict_Keys((PyObject *)ctxt); +// Py_ssize_t siz = PyList_GET_SIZE(lst); +// for (Py_ssize_t i = 0; i < siz; i++) +// { +// PyObject * elem = PyList_GetItem(lst, i); +// if (PyString_Check(elem)) +// { +// std::cout << "At pos:" << i << ", " << PyString_AsString(elem) << std::endl; +// } +// else +// std::cout << "At pos:" << i << ", not a string!" << std::endl; +// } +// Py_XDECREF(lst); +//} + /*! - \brief Initialized an assistant client. + \brief Returns trace string */ -void PVGUI_Module::makeAssistant() +static const QString MYReplaceStr("paraview.simple"); +static const QString MYReplaceImportStr("except: from pvsimple import *"); +QString PVGUI_Module::getTraceString() { - if(this->Implementation->AssistantClient) - return; - - QString assistantExe; - QString profileFile; - - const char* assistantName = "assistant"; -#ifdef WNT - const char* binDir = "\\"; - const char* binDir1 = "\\..\\"; -#else - const char* binDir = "/bin/"; - const char* binDir1 = "/bin/bin/"; -#endif - - QString helper = QString(getenv("PVHOME")) + binDir + QString("pqClientDocFinder.txt"); - if(!QFile::exists(helper)) - helper = QString(getenv("PVHOME")) + binDir1 + QString("pqClientDocFinder.txt"); - if(QFile::exists(helper)) { - QFile file(helper); - if(file.open(QIODevice::ReadOnly)) { - assistantExe = file.readLine().trimmed(); - profileFile = file.readLine().trimmed(); - // CMake escapes spaces, we need to unescape those. - assistantExe.replace("\\ ", " "); - profileFile.replace("\\ ", " "); - } - } - - if(assistantExe.isEmpty()) { - assistantExe = ::Locate(assistantName);//assistantExe = ::Locate(assistantProgName); - /* - QString assistant = QCoreApplication::applicationDirPath(); - assistant += QDir::separator(); - assistant += assistantName; - assistantExe = assistant; - */ - } - - this->Implementation->AssistantClient = new QAssistantClient(assistantExe, this); - QObject::connect(this->Implementation->AssistantClient, SIGNAL(error(const QString&)), - this, SLOT(assistantError(const QString&))); - - QStringList args; - args.append(QString("-profile")); - - if(profileFile.isEmpty()) { - // see if help is bundled up with the application - QString profile = ::Locate("pqClient.adp"); - /*QCoreApplication::applicationDirPath() + QDir::separator() - + QString("pqClient.adp");*/ - - if(QFile::exists(profile)) - profileFile = profile; + vtkSMTrace *tracer = vtkSMTrace::GetActiveTracer(); + if (!tracer) // trace is not started + return QString(""); + + QString traceString(tracer->GetCurrentTrace()); + + // Replace import "paraview.simple" by "pvsimple" + if ((!traceString.isNull()) && traceString.length() != 0) { + int aPos = traceString.indexOf(MYReplaceStr); + while (aPos != -1) { + traceString = traceString.replace(aPos, MYReplaceStr.length(), "pvsimple"); + aPos = traceString.indexOf(MYReplaceStr, aPos); + } + int aImportPos = traceString.indexOf(MYReplaceImportStr); + if(aImportPos != -1) + { + traceString = traceString.replace(aImportPos, MYReplaceImportStr.length(), "except:\n import pvsimple\n from pvsimple import *"); + } } - if(profileFile.isEmpty() && getenv("PARAVIEW_HELP")) { - // not bundled, ask for help - args.append(getenv("PARAVIEW_HELP")); - } - else if(profileFile.isEmpty()) { - // no help, error out - SUIT_MessageBox::critical(getApp()->desktop(),"Help error", "Couldn't find" - " pqClient.adp.\nTry setting the PARAVIEW_HELP environment variable which" - " points to that file"); - delete this->Implementation->AssistantClient; + return traceString; +} + +/*! + \brief Saves trace string to disk file +*/ +void PVGUI_Module::saveTrace(const char* theName) +{ + QFile file(theName); + if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) { + MESSAGE( "Could not open file:" << theName ); return; } - - QFileInfo fi(profileFile); - this->Implementation->DocumentationDir = fi.absolutePath(); - - args.append(profileFile); - - this->Implementation->AssistantClient->setArguments(args); + QTextStream out(&file); + out << getTraceString(); + file.close(); } /*! - \brief Slot to call the message handler with the critical message. + \brief Saves ParaView state to a disk file */ -void PVGUI_Module::assistantError( const QString& error ) +void PVGUI_Module::saveParaviewState(const char* theFileName) { - qCritical(error.toAscii().data()); + pqApplicationCore::instance()->saveState(theFileName); } /*! - \brief Slot to show the waiting state. + \brief Delete all objects for Paraview Pipeline Browser */ -void PVGUI_Module::onPreAccept() +void PVGUI_Module::clearParaviewState() { - getApp()->desktop()->statusBar()->showMessage(tr("STB_PREACCEPT")); - QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); + QAction* deleteAllAction = action(DeleteAllId); + if (deleteAllAction) { + deleteAllAction->activate(QAction::Trigger); + } } /*! - \brief Slot to show the ready state. + \brief Restores ParaView state from a disk file + + If toClear == true, the current ojects will be deleted */ -void PVGUI_Module::onPostAccept() +void PVGUI_Module::loadParaviewState(const char* theFileName) { - getApp()->desktop()->statusBar()->showMessage(tr("STB_POSTACCEPT"), 2000); - QTimer::singleShot(0, this, SLOT(endWaitCursor())); + pqApplicationCore::instance()->loadState(theFileName, getActiveServer()); } /*! - \brief Slot to switch off wait cursor. + \brief Returns current active ParaView server */ -void PVGUI_Module::endWaitCursor() +pqServer* PVGUI_Module::getActiveServer() { - QApplication::restoreOverrideCursor(); + return pqApplicationCore::instance()->getActiveServer(); } + /*! - \brief Returns the ParaView multi-view manager. + \brief Creates PARAVIS preference pane */ -pqViewManager* PVGUI_Module::getMultiViewManager() const +void PVGUI_Module::createPreferences() { - pqViewManager* aMVM = 0; - if ( Implementation ) - aMVM = &Implementation->Core.multiViewManager(); - return aMVM; + // Paraview settings tab + int aParaViewSettingsTab = addPreference( tr( "TIT_PVIEWSETTINGS" ) ); + int aPanel = addPreference(QString(), aParaViewSettingsTab, LightApp_Preferences::UserDefined, "PARAVIS", ""); + setPreferenceProperty(aPanel, "content", (qint64)(new PVGUI_ParaViewSettingsPane())); + + // Paravis settings tab + int aParaVisSettingsTab = addPreference( tr( "TIT_PVISSETTINGS" ) ); + addPreference( tr( "PREF_STOP_TRACE" ), aParaVisSettingsTab, LightApp_Preferences::Bool, "PARAVIS", "stop_trace"); + + int aSaveType = addPreference(tr( "PREF_SAVE_TYPE_LBL" ), aParaVisSettingsTab, + LightApp_Preferences::Selector, + "PARAVIS", "savestate_type"); + QList aIndices; + QStringList aStrings; + aIndices<<0<<1<<2; + aStrings<toolBar(tr("TOOL_LOOKMARKS")); - if ( theObject == aTB ) { + SalomeApp_Module::contextMenuPopup(theClient, theMenu, theTitle); + + // Check if we are in Object Browser + SUIT_DataBrowser* ob = getApp()->objectBrowser(); + bool isOBClient = (ob && theClient == ob->popupClientType()); + if (!isOBClient) { + return; + } + + // Get list of selected objects + LightApp_SelectionMgr* aSelectionMgr = getApp()->selectionMgr(); + SALOME_ListIO aListIO; + aSelectionMgr->selectedObjects(aListIO); + if (aListIO.Extent() == 1 && aListIO.First()->hasEntry()) { + QString entry = QString(aListIO.First()->getEntry()); - if ( theEvent->type() == QEvent::ActionAdded ) { - QList anActns = aTB->actions(); - for (int i = 0; i < anActns.size(); ++i) - if ( toolMgr()->actionId(anActns.at(i)) == -1 ) { - toolMgr()->setUpdatesEnabled(false); - createTool( anActns.at(i), tr("TOOL_LOOKMARKS") ); - toolMgr()->setUpdatesEnabled(true); - } - } - - if ( theEvent->type() == QEvent::ActionRemoved ) { - QList anActns = aTB->actions(); - QIntList aIDL = toolMgr()->idList(); - for (int i = 0; i < aIDL.size(); ++i) { - if ( toolMgr()->action(aIDL.at(i))->parent() == aTB - && - !anActns.contains( toolMgr()->action(aIDL.at(i)) ) ) { - toolMgr()->setUpdatesEnabled(false); - toolMgr()->unRegisterAction( aIDL.at(i) ); - toolMgr()->remove( aIDL.at(i), tr("TOOL_LOOKMARKS") ); - toolMgr()->setUpdatesEnabled(true); - } + // Get active study + SalomeApp_Study* activeStudy = + dynamic_cast(getApp()->activeStudy()); + if(!activeStudy) { + return; + } + + // Get SALOMEDS client study + _PTR(Study) studyDS = activeStudy->studyDS(); + if(!studyDS) { + return; + } + + QString paravisDataType(GetEngine()->ComponentDataType()); + if(activeStudy && activeStudy->isComponent(entry) && + activeStudy->componentDataType(entry) == paravisDataType) { + // ParaViS module object + theMenu->addSeparator(); + theMenu->addAction(action(SaveStatePopupId)); + } + else { + // Try to get state object + _PTR(SObject) stateSObj = + studyDS->FindObjectID(entry.toLatin1().constData()); + if (!stateSObj) { + return; + } + + // Check local id + _PTR(GenericAttribute) anAttr; + if (!stateSObj->FindAttribute(anAttr, "AttributeLocalID")) { + return; + } + + _PTR(AttributeLocalID) anID(anAttr); + + if (anID->Value() == PVSTATEID) { + // Paraview state object + theMenu->addSeparator(); + theMenu->addAction(action(AddStatePopupId)); + theMenu->addAction(action(CleanAndAddStatePopupId)); + theMenu->addSeparator(); + theMenu->addAction(action(ParaVisRenameId)); + theMenu->addAction(action(ParaVisDeleteId)); } } - } +} - return QObject::eventFilter( theObject, theEvent ); +/*! + \brief. Show ParaView python trace. +*/ +void PVGUI_Module::onShowTrace() +{ + if (!myTraceWindow) { + myTraceWindow = new pqPythonScriptEditor(getApp()->desktop()); + } + myTraceWindow->setText(getTraceString()); + myTraceWindow->show(); + myTraceWindow->raise(); + myTraceWindow->activateWindow(); } + /*! - \brief Activate module. - \param study current study - \return \c true if activaion is done successfully or 0 to prevent - activation on error + \brief. Re-initialize ParaView python trace. */ -bool PVGUI_Module::activateModule( SUIT_Study* study ) +void PVGUI_Module::onRestartTrace() { - bool isDone = LightApp_Module::activateModule( study ); - if ( !isDone ) return false; + stopTrace(); + startTrace(); +} - showView( true ); +/*! + \brief Show ParaView view. +*/ +void PVGUI_Module::onNewParaViewWindow() +{ + showView(true); +} - if ( mySourcesMenuId != -1 ) menuMgr()->show(mySourcesMenuId); - if ( myFiltersMenuId != -1 ) menuMgr()->show(myFiltersMenuId); - setMenuShown( true ); - setToolShown( true ); +/*! + \brief Save state under the module root object. +*/ +void PVGUI_Module::onSaveMultiState() +{ + // Create state study object + + // Get SALOMEDS client study + _PTR(Study) studyDS = PARAVIS::GetCStudy(this); + if(!studyDS) { + return; + } + + _PTR(SComponent) paravisComp = + studyDS->FindComponent(GetEngine()->ComponentDataType()); + if(!paravisComp) { + return; + } - toolMgr()->toolBar(tr("TOOL_LOOKMARKS"))->installEventFilter(this); + // Unlock the study if it is locked + bool isLocked = studyDS->GetProperties()->IsLocked(); + if (isLocked) { + studyDS->GetProperties()->SetLocked(false); + } + + QString stateName = tr("SAVED_PARAVIEW_STATE_NAME") + + QString::number(myStateCounter + 1); - // Make default server connection - if ( Implementation ) - Implementation->Core.makeDefaultConnectionIfNoneExists(); + _PTR(StudyBuilder) studyBuilder = studyDS->NewBuilder(); + _PTR(SObject) newSObj = studyBuilder->NewObject(paravisComp); - restoreDockWidgetsState(); + // Set name + _PTR(GenericAttribute) anAttr; + anAttr = studyBuilder->FindOrCreateAttribute(newSObj, "AttributeName"); + _PTR(AttributeName) nameAttr(anAttr); + + nameAttr->SetValue(stateName.toLatin1().constData()); - return isDone; + // Set local id + anAttr = studyBuilder->FindOrCreateAttribute(newSObj, "AttributeLocalID"); + _PTR(AttributeLocalID) localIdAttr(anAttr); + + localIdAttr->SetValue(PVSTATEID); + + // Set file name + QString stateEntry = QString::fromStdString(newSObj->GetID()); + + // File name for state saving + QString tmpDir = QString::fromStdString(SALOMEDS_Tool::GetTmpDir()); + QString fileName = QString("%1_paravisstate:%2").arg(tmpDir, stateEntry); + + anAttr = studyBuilder->FindOrCreateAttribute(newSObj, "AttributeString"); + _PTR(AttributeString) stringAttr(anAttr); + + stringAttr->SetValue(fileName.toLatin1().constData()); + + // Lock the study back if necessary + if (isLocked) { + studyDS->GetProperties()->SetLocked(true); + } + + // Save state + saveParaviewState(fileName.toLatin1().constData()); + myTemporaryFiles.append(fileName); + + // Increment the counter + myStateCounter++; + + updateObjBrowser(); } +/*! + \brief Restore the selected state by merging with the current one. +*/ +void PVGUI_Module::onAddState() +{ + loadSelectedState(false); +} /*! - \brief Deactivate module. - \param study current study - \return \c true if deactivaion is done successfully or 0 to prevent - deactivation on error + \brief Clean the current state and restore the selected one. */ -bool PVGUI_Module::deactivateModule( SUIT_Study* study ) +void PVGUI_Module::onCleanAddState() { - toolMgr()->toolBar(tr("TOOL_LOOKMARKS"))->removeEventFilter(this); + loadSelectedState(true); +} - showView( false ); +/*! + \brief Rename the selected object. +*/ +void PVGUI_Module::onRename() +{ + LightApp_SelectionMgr* aSelectionMgr = getApp()->selectionMgr(); + SALOME_ListIO aListIO; + aSelectionMgr->selectedObjects(aListIO); + + if (aListIO.Extent() == 1 && aListIO.First()->hasEntry()) { + std::string entry = aListIO.First()->getEntry(); + + // Get SALOMEDS client study + _PTR(Study) studyDS = PARAVIS::GetCStudy(this); + if(!studyDS) { + return; + } + + // Unlock the study if it is locked + bool isLocked = studyDS->GetProperties()->IsLocked(); + if (isLocked) { + studyDS->GetProperties()->SetLocked(false); + } + + // Rename the selected state object + _PTR(SObject) stateSObj = studyDS->FindObjectID(entry); + if (!stateSObj) { + return; + } + + _PTR(GenericAttribute) anAttr; + if (stateSObj->FindAttribute(anAttr, "AttributeName")) { + _PTR(AttributeName) nameAttr (anAttr); + QString newName = + LightApp_NameDlg::getName(getApp()->desktop(), nameAttr->Value().c_str()); + if (!newName.isEmpty()) { + nameAttr->SetValue(newName.toLatin1().constData()); + aListIO.First()->setName(newName.toLatin1().constData()); + } + } + + // Lock the study back if necessary + if (isLocked) { + studyDS->GetProperties()->SetLocked(true); + } + + // Update object browser + updateObjBrowser(); + + } +} - // hide menus - menuMgr()->hide(mySourcesMenuId); - menuMgr()->hide(myFiltersMenuId); - setMenuShown( false ); - setToolShown( false ); +/*! + \brief Delete the selected objects. +*/ +void PVGUI_Module::onDelete() +{ + LightApp_SelectionMgr* aSelectionMgr = getApp()->selectionMgr(); + SALOME_ListIO aListIO; + aSelectionMgr->selectedObjects(aListIO); + + if (aListIO.Extent() == 1 && aListIO.First()->hasEntry()) { + std::string entry = aListIO.First()->getEntry(); + + // Get SALOMEDS client study + _PTR(Study) studyDS = PARAVIS::GetCStudy(this); + if(!studyDS) { + return; + } + + // Unlock the study if it is locked + bool isLocked = studyDS->GetProperties()->IsLocked(); + if (isLocked) { + studyDS->GetProperties()->SetLocked(false); + } + + // Remove the selected state from the study + _PTR(StudyBuilder) studyBuilder = studyDS->NewBuilder(); + _PTR(SObject) stateSObj = studyDS->FindObjectID(entry); + studyBuilder->RemoveObject(stateSObj); + + // Lock the study back if necessary + if (isLocked) { + studyDS->GetProperties()->SetLocked(true); + } + + // Update object browser + updateObjBrowser(); + } +} - saveDockWidgetsState(); +void PVGUI_Module::onPushTraceTimer() +{ +// MESSAGE("onPushTraceTimer(): Pushing trace to engine..."); + GetEngine()->PutPythonTraceStringToEngine(getTraceString().toStdString().c_str()); +} - return LightApp_Module::deactivateModule( study ); +/*! + \brief Discover help project files from the resources. + \return name of the help file. +*/ +QString PVGUI_Module::getHelpFileName() { + QString aPVHome(getenv("PVHOME")); + if (aPVHome.isNull()) { + qWarning("Wariable PVHOME is not defined"); + return QString(); + } + QChar aSep = QDir::separator(); + //PARAVIEW_VERSION from the vtkPVConfig.h file + QString aFileName = aPVHome + aSep + "share" + aSep + "doc" + aSep + "paraview-"+ PARAVIEW_VERSION + aSep + "paraview.qch"; + return aFileName; } + /*! - \brief Compares the contents of the window with the given reference image, - returns true if they "match" within some tolerance. + \brief Load selected paraview state + + If toClear == true, the current state will be cleared */ -bool PVGUI_Module::compareView( const QString& ReferenceImage, double Threshold, - ostream& Output, const QString& TempDirectory ) +void PVGUI_Module::loadSelectedState(bool toClear) { - if ( Implementation ) - return Implementation->Core.compareView( ReferenceImage, Threshold, Output, TempDirectory ); - return false; + QString fileName; + + LightApp_SelectionMgr* aSelectionMgr = getApp()->selectionMgr(); + SALOME_ListIO aListIO; + aSelectionMgr->selectedObjects(aListIO); + + if (aListIO.Extent() == 1 && aListIO.First()->hasEntry()) { + std::string entry = aListIO.First()->getEntry(); + + // Get SALOMEDS client study + _PTR(Study) studyDS = PARAVIS::GetCStudy(this); + if(!studyDS) { + return; + } + + // Check local id + _PTR(SObject) stateSObj = studyDS->FindObjectID(entry); + _PTR(GenericAttribute) anAttr; + if (!stateSObj->FindAttribute(anAttr, "AttributeLocalID")) { + return; + } + _PTR(AttributeLocalID) anID(anAttr); + if (!anID->Value() == PVSTATEID) { + return; + } + + // Get state file name + if (stateSObj->FindAttribute(anAttr, "AttributeString")) { + _PTR(AttributeString) aStringAttr(anAttr); + QString stringValue(aStringAttr->Value().c_str()); + + if (QFile::exists(stringValue)) { + fileName = stringValue; + } + } + } + + if (!fileName.isEmpty()) { + if (toClear) { + clearParaviewState(); + } + + loadParaviewState(fileName.toLatin1().constData()); + } + else { + SUIT_MessageBox::critical(getApp()->desktop(), + tr("ERR_ERROR"), + tr("ERR_STATE_CANNOT_BE_RESTORED")); + } } /*! @@ -835,7 +1424,13 @@ bool PVGUI_Module::compareView( const QString& ReferenceImage, double Threshold, #endif // WNT extern "C" { + + bool flag = false; PVGUI_EXPORT CAM_Module* createModule() { return new PVGUI_Module(); } + + PVGUI_EXPORT char* getModuleVersion() { + return (char*)PARAVIS_VERSION_STR; + } }