X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;ds=sidebyside;f=src%2FSALOME_PYQT%2FSALOME_PYQT_GUI%2FSALOME_PYQT_Module.cxx;h=4b73279a700c3c34c38c8323852d078342d20d0c;hb=6516e549128fb08e3cc3ae16bddea0345e083d24;hp=8213a19ce81539b0cab7c15ffde296f31da427bb;hpb=e07448c48ea5b2127e34fc7b8c3427d01c7ce17b;p=modules%2Fgui.git diff --git a/src/SALOME_PYQT/SALOME_PYQT_GUI/SALOME_PYQT_Module.cxx b/src/SALOME_PYQT/SALOME_PYQT_GUI/SALOME_PYQT_Module.cxx index 8213a19ce..4b73279a7 100644 --- a/src/SALOME_PYQT/SALOME_PYQT_GUI/SALOME_PYQT_Module.cxx +++ b/src/SALOME_PYQT/SALOME_PYQT_GUI/SALOME_PYQT_Module.cxx @@ -1,4 +1,4 @@ -// Copyright (C) 2007-2012 CEA/DEN, EDF R&D, OPEN CASCADE +// Copyright (C) 2007-2014 CEA/DEN, EDF R&D, OPEN CASCADE // // Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS @@ -6,7 +6,7 @@ // 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 @@ -22,20 +22,25 @@ // File : SALOME_PYQT_Module.cxx // Author : Vadim SANDLER, Open CASCADE S.A.S. (vadim.sandler@opencascade.com) -#include - #include "SALOME_PYQT_Module.h" +#include "SALOME_PYQT_PyModule.h" #include "SalomeApp_Application.h" -#include "SALOME_PYQT_ModuleLight.h" #include #include -#include +#include +// +// NB: Python requests. +// General rule for Python requests created by Python-based GUI modules +// (SALOME_PYQT_Module and other ones): +// all requests should be executed SYNCHRONOUSLY within the main GUI thread. +// However, it is obligatory that ANY Python call is wrapped with a request object, +// so that ALL Python API calls are serialized with PyInterp_Dispatcher. // // NB: Library initialization -// Since the SalomePyQtGUILight library is not imported in Python it's initialization function +// Since the SalomePyQtGUI library is not imported in Python it's initialization function // should be called manually (and only once) in order to initialize global sip data // and to get C API from sip : sipBuildResult for example // @@ -59,198 +64,224 @@ PyMODINIT_FUNC INIT_FUNCTION(); */ extern "C" { - SALOME_PYQT_EXPORT CAM_Module* createModule() { + SALOME_PYQT_EXPORT CAM_Module* createModule() + { + QCoreApplication* app = QCoreApplication::instance(); + bool alreadyInitialized = app && app->property( "salome_pyqt_gui_light_initialized" ).toBool(); - static bool alreadyInitialized = false; if ( !alreadyInitialized ) { - // call only once (see comment above) ! - - PyEval_RestoreThread( KERNEL_PYTHON::_gtstate); + PyLockWrapper lck; // GIL acquisition INIT_FUNCTION(); - PyEval_ReleaseThread( KERNEL_PYTHON::_gtstate); - alreadyInitialized = !alreadyInitialized; + if ( app ) app->setProperty( "salome_pyqt_gui_light_initialized", true ); } + return new SALOME_PYQT_Module(); } } - /*! - \var __DEFAULT_NAME__ - Default name of the module, replaced at the moment of module creation + \class SALOME_PYQT_Module + \brief This class implements GUI module for CORBA engine-based Python SALOME modules. */ -const char* __DEFAULT_NAME__ = "SALOME_PYQT_Module"; /*! - * Constructor - */ + \brief Constructor +*/ SALOME_PYQT_Module::SALOME_PYQT_Module() - : SalomeApp_Module(__DEFAULT_NAME__), - LightApp_Module(__DEFAULT_NAME__), - SALOME_PYQT_ModuleLight() + : SalomeApp_Module( "noname" ) // name is set explicitly at the module initialization { + // initialize helper + myHelper = new PyModuleHelper( this ); } /*! - * Destructor - */ + \brief Destructor +*/ SALOME_PYQT_Module::~SALOME_PYQT_Module() { + // as myHelper is a QObject, it should be deleted automatically } /*! - * Get module engine, returns nil var if engine is not found in LifeCycleCORBA - */ -Engines::EngineComponent_var SALOME_PYQT_Module::getEngine() const -{ - Engines::EngineComponent_var comp; - // temporary solution - try { - comp = getApp()->lcc()->FindOrLoad_Component( "FactoryServerPy", name().toLatin1() ); - } - catch (CORBA::Exception&) { - } - return comp; -} - -/*! - * Get module engine IOR, returns empty string if engine is not found in LifeCycleCORBA - */ + \brief Get module engine IOR + + This function tries to get engine IOR from the Python module using engineIOR() function. + That function can load module engine using appropriate container if required. + If this function is not available in Python module, the default implementation + is used which loads engine to the default FactoryServer container. +*/ QString SALOME_PYQT_Module::engineIOR() const { - class EngineIORReq : public PyInterp_LockRequest - { - public: - EngineIORReq( PyInterp_Interp* _py_interp, - SALOME_PYQT_Module* _obj ) - : PyInterp_LockRequest( _py_interp, 0, true ), // this request should be processed synchronously (sync == true) - myObj( _obj ) {} + // call helper to get IOR from Python module + static QString ior; - protected: - virtual void execute() - { - myObj->getEngineIOR(); + if ( ior.isEmpty() ) { + // first call helper to get IOR from Python module + ior = myHelper->engineIOR(); + } + if ( ior.isEmpty() ) { + // if IOR is still not specified, try default implementation + // which loads engine to the default FactoryServer container. + Engines::EngineComponent_var comp; + // temporary solution + try { + comp = getApp()->lcc()->FindOrLoad_Component( "FactoryServer", name().toLatin1() ); } + catch (CORBA::Exception&) { + } + if ( !CORBA::is_nil( comp ) ) + ior = QString( getApp()->orb()->object_to_string( comp.in() ) ); + } - private: - SALOME_PYQT_Module* myObj; - }; - - // post request - PyInterp_Dispatcher::Get()->Exec( new EngineIORReq( myInterp, const_cast( this ) ) ); - - return myIOR; + return ior; } - /*! - * Redefined to invokec correct version - */ -bool SALOME_PYQT_Module::activateModule( SUIT_Study* theStudy ) + \brief Initialization of the module. + \param app parent application object + \sa PyModuleHelper::initialize() +*/ +void SALOME_PYQT_Module::initialize( CAM_Application* app ) { // call base implementation - bool res = SalomeApp_Module::activateModule( theStudy ); - - if ( !res ) - return res; + SalomeApp_Module::initialize( app ); - // internal activation - return activateModuleInternal( theStudy ); + // ... then call helper + myHelper->initialize( app ); } /*! - * Tries to get engine IOR from the Python module using engineIOR() function. - * That function can load module engine using appropriate container if required. - * If this function is not available in Python module, the default implementation - * is used which loads engine to the default FactoryServerPy container. - */ -void SALOME_PYQT_Module::getEngineIOR() + \brief Activation of the module. + \param study parent study + \return \c true if activation is successful and \c false otherwise + \sa PyModuleHelper::activate() +*/ +bool SALOME_PYQT_Module::activateModule( SUIT_Study* study ) { - myIOR = ""; - - // Python interpreter should be initialized and Python module should be - // import first - if ( !myInterp || !myModule ) - return; + // call base implementation and then helper + return SalomeApp_Module::activateModule( study ) && myHelper->activate( study ); +} - if ( PyObject_HasAttrString( myModule , "engineIOR" ) ) { - PyObjWrapper res( PyObject_CallMethod( myModule, (char*)"engineIOR", (char*)"" ) ); - if ( !res ) { - PyErr_Print(); - } - else { - // parse the return value, result chould be string - if ( PyString_Check( res ) ) { - myIOR = PyString_AsString( res ); - } - } - } - else if ( !CORBA::is_nil( getEngine() ) ) - myIOR = QString( getApp()->orb()->object_to_string( getEngine() ) ); +/*! + \brief Deactivation of the module. + \param study parent study + \return \c true if deactivation is successful and \c false otherwise + \sa PyModuleHelper::deactivate() +*/ +bool SALOME_PYQT_Module::deactivateModule( SUIT_Study* study ) +{ + // call helper + bool res = myHelper->deactivate( study ); + + // ... then call base implementation + return SalomeApp_Module::deactivateModule( study ) && res; } -CAM_DataModel* SALOME_PYQT_Module::createDataModel() +/*! + \brief Get the dockable windows associated with the module. + \param winMap output map of dockable windows in form { : } + \sa PyModuleHelper::windows() +*/ +void SALOME_PYQT_Module::windows( QMap& winMap ) const { - MESSAGE( "SALOME_PYQT_Module::createDataModel()" ); - CAM_DataModel * dm = SalomeApp_Module::createDataModel(); - return dm; + // get list of dockable windows from helper + winMap = myHelper->windows(); } /*! - \brief Process GUI action (from main menu, toolbar or - context popup menu action). + \brief Define the compatible view windows associated with the module. + \param viewList output list of view windows types + \sa PyModuleHelper::viewManagers() */ -void SALOME_PYQT_Module::onGUIEvent(){ - SALOME_PYQT_ModuleLight::onGUIEvent(); +void SALOME_PYQT_Module::viewManagers( QStringList& viewList ) const +{ + // get list of view types from helper + viewList = myHelper->viewManagers(); } /*! - \brief Signal handler closing(SUIT_ViewWindow*) of a view - \param pview view being closed + \brief Process study activation. + \sa PyModuleHelper::studyActivated() */ -void SALOME_PYQT_Module::onViewClosed( SUIT_ViewWindow* pview ) +void SALOME_PYQT_Module::studyActivated() { - SALOME_PYQT_ModuleLight::onViewClosed( pview ); + // call helper + myHelper->studyActivated( application()->activeStudy() ); } /*! - \brief Signal handler tryClose(SUIT_ViewWindow*) of a view - \param pview view user tries to close + \brief Process context popup menu request. + \param context popup menu context (e.g. "ObjectBrowser") + \param menu popup menu + \param title popup menu title (not used) + \sa PyModuleHelper::contextMenu() */ -void SALOME_PYQT_Module::onViewTryClose( SUIT_ViewWindow* pview ) +void SALOME_PYQT_Module::contextMenuPopup( const QString& context, + QMenu* menu, + QString& /*title*/ ) { - SALOME_PYQT_ModuleLight::onViewTryClose( pview ); + // call helper + myHelper->contextMenu( context, menu ); } /*! - \breif Process application preferences changing. + \brief Export preferences for the Python module. + \sa PyModuleHelper::createPreferences() +*/ +void SALOME_PYQT_Module::createPreferences() +{ + // call helper + myHelper->createPreferences(); +} - Called when any application setting is changed. +/*! + \brief Process module's preferences changing. + \param section preference resources section + \param parameter preference resources parameter name + \sa PyModuleHelper::preferencesChanged() +*/ +void SALOME_PYQT_Module::preferencesChanged( const QString& section, const QString& parameter ) +{ + // call helper + myHelper->preferencesChanged( section, parameter ); +} - \param module preference module - \param section preference resource file section - \param setting preference resource name +/*! + \brief Test if object \a what can be dragged by the user. + \param what data object being tested + \return \c true if object can be dragged or \c false otherwise + \sa PyModuleHelper::isDraggable() */ -void SALOME_PYQT_Module::preferenceChanged( const QString& module, - const QString& section, - const QString& setting ) +bool SALOME_PYQT_Module::isDraggable( const SUIT_DataObject* what ) const { - SALOME_PYQT_ModuleLight::preferenceChanged(module,section,setting); + // call helper + return myHelper->isDraggable( what ); } /*! - \brief Signal handler windowActivated(SUIT_ViewWindow*) of SUIT_Desktop - \param pview view being activated + \brief Test if drop operation can be done on the \a where object. + \param where data object being tested + \return \c true if if drop operation is supported by object or \c false otherwise + \sa PyModuleHelper::isDropAccepted() */ -void SALOME_PYQT_Module::onActiveViewChanged( SUIT_ViewWindow* pview ) +bool SALOME_PYQT_Module::isDropAccepted( const SUIT_DataObject* where ) const { - SALOME_PYQT_ModuleLight::onActiveViewChanged(pview); + // call helper + return myHelper->isDropAccepted( where ); } /*! - \brief Signal handler cloneView() of OCCViewer_ViewWindow - \param pview view being cloned + \brief Perform drop operation + \param what list of data objects being dropped + \param where target data object for drop operation + \param row line (child item index) where drop operation is performed to + \param action current drop action (copy or move) + \sa PyModuleHelper::dropObjects() */ -void SALOME_PYQT_Module::onViewCloned( SUIT_ViewWindow* pview ) +void SALOME_PYQT_Module::dropObjects( const DataObjectList& what, SUIT_DataObject* where, + const int row, Qt::DropAction action ) { - SALOME_PYQT_ModuleLight::onViewCloned(pview); + // call helper + myHelper->dropObjects( what, where, row, action ); } +