X-Git-Url: http://git.salome-platform.org/gitweb/?a=blobdiff_plain;f=src%2FSALOME_PYQT%2FSALOME_PYQT_GUILight%2FSALOME_PYQT_PyModule.cxx;h=ce5f82caf5df1fc2dc56a52627c726091e380a8c;hb=8d986a56d8745aba15e2241a252c02bf30b53999;hp=914c5c45a71872e751634b9d255db848ac17a5e4;hpb=034a705024b224972c148e1e3834c5ee38df184b;p=modules%2Fgui.git diff --git a/src/SALOME_PYQT/SALOME_PYQT_GUILight/SALOME_PYQT_PyModule.cxx b/src/SALOME_PYQT/SALOME_PYQT_GUILight/SALOME_PYQT_PyModule.cxx index 914c5c45a..ce5f82caf 100644 --- a/src/SALOME_PYQT/SALOME_PYQT_GUILight/SALOME_PYQT_PyModule.cxx +++ b/src/SALOME_PYQT/SALOME_PYQT_GUILight/SALOME_PYQT_PyModule.cxx @@ -1,4 +1,4 @@ -// Copyright (C) 2007-2014 CEA/DEN, EDF R&D, OPEN CASCADE +// Copyright (C) 2007-2016 CEA/DEN, EDF R&D, OPEN CASCADE // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public @@ -65,6 +65,9 @@ const int DEFAULT_GROUP = 40; */ QMutex myInitMutex; +/*! DEBUG mode */ +const bool DEBUG = false; + /*! \var IsCallOldMethods \brief Allow calling obsolete callback methods. @@ -75,7 +78,7 @@ QMutex myInitMutex; etc. is blocked. CALL_OLD_METHODS macro can be defined, for example, by adding - -DCALL_OLD_METHODS compilation option to the Makefile. + -DCALL_OLD_METHODS compilation option to the CMakeLists.txt. */ #ifdef CALL_OLD_METHODS const bool IsCallOldMethods = true; @@ -165,15 +168,18 @@ public: FuncMsg( const QString& funcName ) { myName = funcName; - MESSAGE( qPrintable( myName ) << " [ begin ]" ); + if ( DEBUG ) + MESSAGE( qPrintable( myName ) << " [ begin ]" ); } ~FuncMsg() { - MESSAGE( qPrintable( myName ) << " [ end ]" ); + if ( DEBUG ) + MESSAGE( qPrintable( myName ) << " [ end ]" ); } void message( const QString& msg ) { - MESSAGE( qPrintable( myName ) << " : " << qPrintable( msg ) ); + if ( DEBUG ) + MESSAGE( qPrintable( myName ) << " : " << qPrintable( msg ) ); } private: QString myName; @@ -228,9 +234,9 @@ public: XmlHandler( PyModuleHelper* helper, const QString& fileName ); void createActions(); void createPopup( QMenu* menu, - const QString& context, - const QString& parent, - const QString& object ); + const QString& context, + const QString& parent, + const QString& object ); void activateMenus( bool ); private: @@ -238,11 +244,11 @@ private: QIcon loadIcon( const QString& fileName ); void createMenu( QDomNode& parentNode, - const int parentMenuId = -1, - QMenu* parentPopup = 0 ); + const int parentMenuId = -1, + QMenu* parentPopup = 0 ); void createToolBar( QDomNode& parentNode ); void insertPopupItems( QDomNode& parentNode, - QMenu* menu ); + QMenu* menu ); private: PyModuleHelper* myHelper; @@ -258,7 +264,7 @@ private: \param fileName path to the XML menu description file */ PyModuleHelper::XmlHandler::XmlHandler( PyModuleHelper* helper, - const QString& fileName ) + const QString& fileName ) : myHelper( helper ) { if ( !fileName.isEmpty() ) { @@ -305,9 +311,9 @@ void PyModuleHelper::XmlHandler::createActions() \param context popup menu object name */ void PyModuleHelper::XmlHandler::createPopup( QMenu* menu, - const QString& context, - const QString& parent, - const QString& object ) + const QString& context, + const QString& parent, + const QString& object ) { // get document element QDomElement aDocElem = myDoc.documentElement(); @@ -364,10 +370,10 @@ QIcon PyModuleHelper::XmlHandler::loadIcon( const QString& fileName ) if ( module() && !fileName.isEmpty() ) { SUIT_ResourceMgr* resMgr = module()->getApp()->resourceMgr(); QPixmap pixmap = resMgr->loadPixmap( module()->name(), - QApplication::translate( module()->name().toLatin1().data(), - fileName.toLatin1().data() ) ); - if ( !pixmap.isNull() ) - icon = QIcon( pixmap ); + QApplication::translate( module()->name().toLatin1().data(), + fileName.toLatin1().data() ) ); + if ( !pixmap.isNull() ) + icon = QIcon( pixmap ); } return icon; @@ -381,8 +387,8 @@ QIcon PyModuleHelper::XmlHandler::loadIcon( const QString& fileName ) \param parentPopup parent popup menu (0 for top-level menu) */ void PyModuleHelper::XmlHandler::createMenu( QDomNode& parentNode, - const int parentMenuId, - QMenu* parentPopup ) + const int parentMenuId, + QMenu* parentPopup ) { if ( !module() || parentNode.isNull() ) return; @@ -425,14 +431,14 @@ void PyModuleHelper::XmlHandler::createMenu( QDomNode& parentNode, if ( id != -1 ) { // create menu action QAction* action = module()->createAction( id, // ID - tooltip, // tooltip - icon, // icon - label, // menu text - tooltip, // status-bar text - QKeySequence( accel ), // keyboard accelerator - module(), // action owner - toggle ); // toogled action - myHelper->connectAction( action ); + tooltip, // tooltip + icon, // icon + label, // menu text + tooltip, // status-bar text + QKeySequence( accel ), // keyboard accelerator + module(), // action owner + toggle ); // toogled action + myHelper->connectAction( action ); module()->createMenu( action, // action menuId, // parent menu ID id, // ID (same as for createAction()) @@ -476,9 +482,10 @@ void PyModuleHelper::XmlHandler::createToolBar( QDomNode& parentNode ) QDomElement parentElement = parentNode.toElement(); if ( !parentElement.isNull() ) { QString aLabel = attribute( parentElement, "label-id" ); + QString aName = attribute( parentElement, "name-id" ); if ( !aLabel.isEmpty() ) { // create toolbar - int tbId = module()->createTool( aLabel ); + int tbId = module()->createTool( aLabel, aName ); QDomNode node = parentNode.firstChild(); while ( !node.isNull() ) { if ( node.isElement() ) { @@ -496,17 +503,17 @@ void PyModuleHelper::XmlHandler::createToolBar( QDomNode& parentNode ) // -1 action ID is not allowed : it means that attribute is missed in the XML file! // also check if the action with given ID is already created if ( id != -1 ) { - // create toolbar action - QAction* action = module()->createAction( id, // ID - tooltip, // tooltip - icon, // icon - label, // menu text - tooltip, // status-bar text - QKeySequence( accel ), // keyboard accelerator - module(), // action owner - toggle ); // toogled action - myHelper->connectAction( action ); - module()->createTool( action, tbId, -1, pos ); + // create toolbar action + QAction* action = module()->createAction( id, // ID + tooltip, // tooltip + icon, // icon + label, // menu text + tooltip, // status-bar text + QKeySequence( accel ), // keyboard accelerator + module(), // action owner + toggle ); // toogled action + myHelper->connectAction( action ); + module()->createTool( action, tbId, -1, pos ); } } else if ( aTagName == "separatorTB" || aTagName == "separator" ) { @@ -552,15 +559,15 @@ void PyModuleHelper::XmlHandler::insertPopupItems( QDomNode& parentNode, QMenu* // -1 action ID is not allowed : it means that attribute is missed in the XML file! // also check if the action with given ID is already created if ( id != -1 ) { - QAction* action = module()->createAction( id, // ID - tooltip, // tooltip - icon, // icon - label, // menu text - tooltip, // status-bar text - QKeySequence( accel ), // keyboard accelerator - module(), // action owner - toggle ); // toogled action - myHelper->connectAction( action ); + QAction* action = module()->createAction( id, // ID + tooltip, // tooltip + icon, // icon + label, // menu text + tooltip, // status-bar text + QKeySequence( accel ), // keyboard accelerator + module(), // action owner + toggle ); // toogled action + myHelper->connectAction( action ); QAction* before = ( pos >= 0 && pos < actions.count() ) ? actions[ pos ] : 0; menu->insertAction( before, action ); } @@ -602,7 +609,6 @@ void PyModuleHelper::XmlHandler::insertPopupItems( QDomNode& parentNode, QMenu* SALOME GUI modules. */ -PyModuleHelper::InterpMap PyModuleHelper::myInterpMap; LightApp_Module* PyModuleHelper::myInitModule = 0; /*! @@ -627,7 +633,7 @@ PyModuleHelper::~PyModuleHelper() { delete myXmlHandler; if ( myInterp && myPyModule ) { - PyLockWrapper aLock = myInterp->GetLockWrapper(); + PyLockWrapper aLock; // Acquire GIL Py_XDECREF( myPyModule ); } } @@ -691,8 +697,8 @@ void PyModuleHelper::connectAction( QAction* a ) { if ( myModule && a ) QObject::connect( a, SIGNAL( triggered( bool ) ), - this, SLOT( actionActivated() ), - Qt::UniqueConnection ); + this, SLOT( actionActivated() ), + Qt::UniqueConnection ); } /*! @@ -747,11 +753,11 @@ QStringList PyModuleHelper::viewManagers() const \brief Initialization of the Python-based SALOME module. This method can be used for creation of the menus, toolbars and - other such staff. + other such stuff. There are two ways to do this: - 1) for obsolete modules implementatino this method first tries to read - _.xml resource file which contains a menu, + 1) for obsolete modules, the implementation of this method first tries to read + the _.xml resource file which contains a menu, toolbars and popup menus description; 2) new modules can create menus by direct calling of the corresponding methods of SalomePyQt Python API in the Python @@ -759,7 +765,7 @@ QStringList PyModuleHelper::viewManagers() const \note SALOME supports two modes of modules loading: - immediate (all the modules are created and initialized - immediately when the application object is created; + immediately when the application object is created); - postponed modules loading (used currently); in this mode the module is loaded only by explicit request. If postponed modules loading is not used, the active @@ -798,10 +804,10 @@ void PyModuleHelper::initialize( CAM_Application* app ) { public: InitializeReq( PyModuleHelper* _helper, - CAM_Application* _app ) + CAM_Application* _app ) : PyInterp_Request( 0, true ), // this request should be processed synchronously (sync == true) myHelper( _helper ), - myApp( _app ) + myApp( _app ) {} protected: virtual void execute() @@ -841,21 +847,21 @@ bool PyModuleHelper::activate( SUIT_Study* study ) { public: ActivateReq( PyModuleHelper* _helper, - SUIT_Study* _study, - bool _customize ) - : PyInterp_Request( 0, true ), // this request should be processed synchronously (sync == true) - myHelper( _helper ), - myStudy ( _study ), - myCustomize( _customize ) - {} + SUIT_Study* _study, + bool _customize ) + : PyInterp_Request( 0, true ), // this request should be processed synchronously (sync == true) + myHelper( _helper ), + myStudy ( _study ), + myCustomize( _customize ) + {} protected: virtual void execute() - { - if ( !myCustomize ) - myHelper->internalActivate( myStudy ); // first activation stage - else - myHelper->internalCustomize( myStudy ); // second activation stage - } + { + if ( !myCustomize ) + myHelper->internalActivate( myStudy ); // first activation stage + else + myHelper->internalCustomize( myStudy ); // second activation stage + } private: PyModuleHelper* myHelper; SUIT_Study* myStudy; @@ -881,12 +887,12 @@ bool PyModuleHelper::activate( SUIT_Study* study ) if ( myLastActivateStatus ) { // connect preferences changing signal connect( myModule->getApp(), SIGNAL( preferenceChanged( const QString&, const QString&, const QString& ) ), - this, SLOT( preferenceChanged( const QString&, const QString&, const QString& ) ) ); + this, SLOT( preferenceChanged( const QString&, const QString&, const QString& ) ) ); // connect active view change signal SUIT_Desktop* d = study->application()->desktop(); connect( d, SIGNAL( windowActivated( SUIT_ViewWindow* ) ), - this, SLOT( activeViewChanged( SUIT_ViewWindow* ) ) ); + this, SLOT( activeViewChanged( SUIT_ViewWindow* ) ) ); // if active window exists, call activeViewChanged() function; // temporary solution: if a getActiveView() in SalomePyQt available // we no longer need this @@ -924,11 +930,11 @@ bool PyModuleHelper::deactivate( SUIT_Study* study ) { public: DeactivateReq( PyInterp_Interp* _py_interp, - PyModuleHelper* _helper, + PyModuleHelper* _helper, SUIT_Study* _study ) : PyInterp_LockRequest( _py_interp, 0, true ), // this request should be processed synchronously (sync == true) myHelper( _helper ), - myStudy ( _study ) + myStudy ( _study ) {} protected: virtual void execute() @@ -950,7 +956,7 @@ bool PyModuleHelper::deactivate( SUIT_Study* study ) // disconnect the SUIT_Desktop signal windowActivated() SUIT_Desktop* d = study->application()->desktop(); disconnect( d, SIGNAL( windowActivated( SUIT_ViewWindow* ) ), - this, SLOT( activeViewChanged( SUIT_ViewWindow* ) ) ); + this, SLOT( activeViewChanged( SUIT_ViewWindow* ) ) ); // deactivate menus, toolbars, etc if ( myXmlHandler ) myXmlHandler->activateMenus( false ); @@ -1023,7 +1029,7 @@ void PyModuleHelper::modelClosed( SUIT_Study* study ) \param parameter preference resources parameter name */ void PyModuleHelper::preferencesChanged( const QString& section, - const QString& parameter ) + const QString& parameter ) { FuncMsg fmsg( "PyModuleHelper::preferencesChanged()" ); @@ -1031,9 +1037,9 @@ void PyModuleHelper::preferencesChanged( const QString& section, { public: PrefChangeReq( PyInterp_Interp* _py_interp, - PyModuleHelper* _helper, - const QString& _section, - const QString& _parameter ) + PyModuleHelper* _helper, + const QString& _section, + const QString& _parameter ) : PyInterp_LockRequest( _py_interp, 0, true ), // this request should be processed synchronously (sync == true) myHelper ( _helper ), mySection( _section ), @@ -1065,8 +1071,8 @@ void PyModuleHelper::preferencesChanged( const QString& section, \param parameter preference resources parameter name */ void PyModuleHelper::preferenceChanged( const QString& module, - const QString& section, - const QString& parameter ) + const QString& section, + const QString& parameter ) { FuncMsg fmsg( "PyModuleHelper::preferenceChanged()" ); @@ -1094,10 +1100,10 @@ void PyModuleHelper::studyActivated( SUIT_Study* study ) { public: StudyChangedReq( PyModuleHelper* _helper, - SUIT_Study* _study ) - : PyInterp_Request( 0, true ), // this request should be processed synchronously (sync == true) + SUIT_Study* _study ) + : PyInterp_Request(0, true ), // this request should be processed synchronously (sync == true) myHelper( _helper ), - myStudy ( _study ) + myStudy ( _study ) {} protected: virtual void execute() @@ -1130,8 +1136,8 @@ void PyModuleHelper::actionActivated() { public: ActionReq( PyInterp_Interp* _py_interp, - PyModuleHelper* _helper, - int _id ) + PyModuleHelper* _helper, + int _id ) : PyInterp_LockRequest( _py_interp, 0, true ), // this request should be processed synchronously (sync == true) myHelper( _helper ), myId ( _id ) @@ -1155,6 +1161,44 @@ void PyModuleHelper::actionActivated() PyInterp_Dispatcher::Get()->Exec( new ActionReq( myInterp, this, myModule->actionId( action ) ) ); } +/*! + \brief update selection from other views or modules. + + Called when selection is modified outside. +*/ +void PyModuleHelper::selectionUpdated(const QStringList& entries) +{ + FuncMsg fmsg( "PyModuleHelper::selectionUpdated()" ); + MESSAGE("selectionUpdated"); + + // perform synchronous request to Python event dispatcher + class SelectionReq : public PyInterp_LockRequest + { + public: + SelectionReq( PyInterp_Interp* _py_interp, + PyModuleHelper* _helper, + const QStringList& _entries ) + : PyInterp_LockRequest( _py_interp, 0, true ), // this request should be processed synchronously (sync == true) + myHelper( _helper ), + myEntries( _entries ) + { + MESSAGE("SelectionReq"); + } + protected: + virtual void execute() + { + MESSAGE("execute"); + myHelper->internalSelectionUpdated( myEntries ); + } + private: + PyModuleHelper* myHelper; + const QStringList& myEntries; + }; + + // post request + PyInterp_Dispatcher::Get()->Exec( new SelectionReq( myInterp, this, entries ) ); +} + /*! \brief Process context popup menu request. @@ -1176,7 +1220,7 @@ void PyModuleHelper::contextMenu( const QString& context, QMenu* menu ) const QString& _context, QMenu* _menu ) : PyInterp_LockRequest( _py_interp, 0, true ), // this request should be processed synchronously (sync == true) - myHelper ( _helper ), + myHelper ( _helper ), myContext( _context ), myMenu ( _menu ) {} @@ -1214,7 +1258,7 @@ void PyModuleHelper::createPreferences() { public: CreatePrefReq( PyInterp_Interp* _py_interp, - PyModuleHelper* _helper ) + PyModuleHelper* _helper ) : PyInterp_LockRequest( _py_interp, 0, true ), // this request should be processed synchronously (sync == true) myHelper( _helper ) {} @@ -1249,11 +1293,11 @@ void PyModuleHelper::activeViewChanged( SUIT_ViewWindow* view ) { public: ActiveViewChangeReq( PyInterp_Interp* _py_interp, - PyModuleHelper* _helper, - SUIT_ViewWindow* _view ) + PyModuleHelper* _helper, + SUIT_ViewWindow* _view ) : PyInterp_LockRequest( _py_interp, 0, true ), myHelper( _helper ), - myView( _view ) + myView( _view ) {} protected: virtual void execute() @@ -1283,11 +1327,11 @@ void PyModuleHelper::tryCloseView( SUIT_ViewWindow* view ) { public: TryCloseViewReq( PyInterp_Interp* _py_interp, - PyModuleHelper* _helper, - SUIT_ViewWindow* _view ) + PyModuleHelper* _helper, + SUIT_ViewWindow* _view ) : PyInterp_LockRequest( _py_interp, 0, true ), myHelper( _helper ), - myView( _view ) + myView( _view ) {} protected: virtual void execute() @@ -1314,8 +1358,8 @@ void PyModuleHelper::closeView( SUIT_ViewWindow* view ) { public: CloseViewReq( PyInterp_Interp* _py_interp, - PyModuleHelper* _helper, - SUIT_ViewWindow* _view ) + PyModuleHelper* _helper, + SUIT_ViewWindow* _view ) : PyInterp_LockRequest( _py_interp, 0, true ), myHelper( _helper ), myView( _view ) @@ -1345,11 +1389,11 @@ void PyModuleHelper::cloneView( SUIT_ViewWindow* view ) { public: CloneViewReq( PyInterp_Interp* _py_interp, - PyModuleHelper* _helper, - SUIT_ViewWindow* _view ) + PyModuleHelper* _helper, + SUIT_ViewWindow* _view ) : PyInterp_LockRequest( _py_interp, 0, true ), myHelper( _helper ), - myView( _view ) + myView( _view ) {} protected: virtual void execute() @@ -1367,8 +1411,9 @@ void PyModuleHelper::cloneView( SUIT_ViewWindow* view ) /*! \brief Save module data. Called when user saves study. \param files output list of files where module stores data + \param url study URL */ -void PyModuleHelper::save( QStringList& files ) +void PyModuleHelper::save( QStringList& files, const QString& url ) { FuncMsg fmsg( "PyModuleHelper::save()" ); @@ -1383,34 +1428,39 @@ void PyModuleHelper::save( QStringList& files ) { public: SaveReq( PyInterp_Interp* _py_interp, - PyModuleHelper* _helper, - QStringList& _files ) + PyModuleHelper* _helper, + QStringList& _files, + const QString& _url ) : PyInterp_LockRequest( _py_interp, 0, true ), // this request should be processed synchronously (sync == true) myHelper( _helper ) , - myFiles( _files ) + myFiles( _files ), + myUrl( _url ) {} protected: virtual void execute() { - myHelper->internalSave( myFiles ); + myHelper->internalSave( myFiles, myUrl ); } private: PyModuleHelper* myHelper; QStringList& myFiles; + QString myUrl; }; // Posting the request only if dispatcher is not busy! // Executing the request synchronously if ( !PyInterp_Dispatcher::Get()->IsBusy() ) - PyInterp_Dispatcher::Get()->Exec( new SaveReq( myInterp, this, files ) ); + PyInterp_Dispatcher::Get()->Exec( new SaveReq( myInterp, this, files, url ) ); } /* - \brief Load module data. Called when user opens study - and activates module. - \param files list of files where module data is stored + \brief Load module data. Called when user opens study + and activates module. + \param files list of files where module data is stored + \param url study URL + \return \c true if loading has been finished successfully or \c false otherwise */ -bool PyModuleHelper::load( const QStringList& files ) +bool PyModuleHelper::load( const QStringList& files, const QString& url ) { FuncMsg fmsg( "PyModuleHelper::load()" ); @@ -1420,29 +1470,32 @@ bool PyModuleHelper::load( const QStringList& files ) { public: LoadReq( PyInterp_Interp* _py_interp, - PyModuleHelper* _helper, - QStringList _files, - bool& _loaded ) + PyModuleHelper* _helper, + QStringList _files, + const QString& _url, + bool& _loaded ) : PyInterp_LockRequest( _py_interp, 0, true ), // this request should be processed synchronously (sync == true) myHelper( _helper ) , myFiles( _files ), + myUrl( _url ), myLoaded( _loaded ) {} protected: virtual void execute() { - myHelper->internalLoad( myFiles, myLoaded ); + myHelper->internalLoad( myFiles, myUrl, myLoaded ); } private: PyModuleHelper* myHelper; QStringList myFiles; + QString myUrl; bool& myLoaded; }; // Posting the request only if dispatcher is not busy! // Executing the request synchronously if ( !PyInterp_Dispatcher::Get()->IsBusy() ) - PyInterp_Dispatcher::Get()->Exec( new LoadReq( myInterp, this, files, loaded ) ); + PyInterp_Dispatcher::Get()->Exec( new LoadReq( myInterp, this, files, url, loaded ) ); return loaded; } @@ -1466,8 +1519,8 @@ void PyModuleHelper::dumpPython( QStringList& files ) { public: DumpPythonReq( PyInterp_Interp* _py_interp, - PyModuleHelper* _helper, - QStringList& _files ) + PyModuleHelper* _helper, + QStringList& _files ) : PyInterp_LockRequest( _py_interp, 0, true ), // this request should be processed synchronously (sync == true) myHelper( _helper ) , myFiles( _files ) @@ -1504,9 +1557,9 @@ bool PyModuleHelper::isDraggable( const SUIT_DataObject* what ) const { public: IsDraggableReq( PyInterp_Interp* _py_interp, - PyModuleHelper* _helper, - LightApp_DataObject* _data_object, - bool& _is_draggable ) + PyModuleHelper* _helper, + LightApp_DataObject* _data_object, + bool& _is_draggable ) : PyInterp_LockRequest( _py_interp, 0, true ), // this request should be processed synchronously (sync == true) myHelper( _helper ) , myDataObject( _data_object ), @@ -1529,9 +1582,9 @@ bool PyModuleHelper::isDraggable( const SUIT_DataObject* what ) const // Executing the request synchronously if ( !PyInterp_Dispatcher::Get()->IsBusy() ) PyInterp_Dispatcher::Get()->Exec( new IsDraggableReq( myInterp, - const_cast( this ), - const_cast( data_object ), - draggable ) ); + const_cast( this ), + const_cast( data_object ), + draggable ) ); } return draggable; @@ -1553,9 +1606,9 @@ bool PyModuleHelper::isDropAccepted( const SUIT_DataObject* where ) const { public: IsDropAcceptedReq( PyInterp_Interp* _py_interp, - PyModuleHelper* _helper, - LightApp_DataObject* _data_object, - bool& _is_drop_accepted ) + PyModuleHelper* _helper, + LightApp_DataObject* _data_object, + bool& _is_drop_accepted ) : PyInterp_LockRequest( _py_interp, 0, true ), // this request should be processed synchronously (sync == true) myHelper( _helper ) , myDataObject( _data_object ), @@ -1578,9 +1631,9 @@ bool PyModuleHelper::isDropAccepted( const SUIT_DataObject* where ) const // Executing the request synchronously if ( !PyInterp_Dispatcher::Get()->IsBusy() ) PyInterp_Dispatcher::Get()->Exec( new IsDropAcceptedReq( myInterp, - const_cast( this ), - const_cast( data_object ), - dropAccepted ) ); + const_cast( this ), + const_cast( data_object ), + dropAccepted ) ); } return dropAccepted; @@ -1594,7 +1647,7 @@ bool PyModuleHelper::isDropAccepted( const SUIT_DataObject* where ) const \param action current drop action (copy or move) */ void PyModuleHelper::dropObjects( const DataObjectList& what, SUIT_DataObject* where, - const int row, Qt::DropAction action ) + const int row, Qt::DropAction action ) { FuncMsg fmsg( "PyModuleHelper::dropObjects()" ); @@ -1603,17 +1656,17 @@ void PyModuleHelper::dropObjects( const DataObjectList& what, SUIT_DataObject* w { public: DropObjectsReq( PyInterp_Interp* _py_interp, - PyModuleHelper* _helper, - const DataObjectList& _what, - SUIT_DataObject* _where, - const int _row, - Qt::DropAction _action ) + PyModuleHelper* _helper, + const DataObjectList& _what, + SUIT_DataObject* _where, + const int _row, + Qt::DropAction _action ) : PyInterp_LockRequest( _py_interp, 0, true ), // this request should be processed synchronously (sync == true) myHelper( _helper ) , myWhat( _what ), - myWhere( _where ), - myRow( _row ), - myAction ( _action ) + myWhere( _where ), + myRow( _row ), + myAction ( _action ) {} protected: virtual void execute() @@ -1647,10 +1700,10 @@ QString PyModuleHelper::engineIOR() const public: EngineIORReq( PyInterp_Interp* _py_interp, PyModuleHelper* _helper, - QString& _ior ) + QString& _ior ) : PyInterp_LockRequest( _py_interp, 0, true ), // this request should be processed synchronously (sync == true) myHelper( _helper ), - myIOR( _ior ) + myIOR( _ior ) {} protected: virtual void execute() @@ -1667,8 +1720,8 @@ QString PyModuleHelper::engineIOR() const if ( anIOR.isEmpty() ) { // post request PyInterp_Dispatcher::Get()->Exec( new EngineIORReq( myInterp, - const_cast( this ), - anIOR ) ); + const_cast( this ), + anIOR ) ); } return anIOR; @@ -1677,38 +1730,22 @@ QString PyModuleHelper::engineIOR() const /*! \brief Initialize python subinterpreter (one per study). \internal - \param studyId study ID */ -void PyModuleHelper::initInterp( int studyId ) +void PyModuleHelper::initInterp() { FuncMsg fmsg( "--- PyModuleHelper::initInterp()" ); - // check study Id - if ( !studyId ) { - // Error! Study Id must not be 0! - myInterp = 0; - return; - } - QMutexLocker ml( &myInitMutex ); - // try to find the subinterpreter - if ( myInterpMap.contains( studyId ) ) { - // found! - myInterp = myInterpMap[ studyId ]; - return; - } - myInterp = new SALOME_PYQT_PyInterp(); myInterp->initialize(); - myInterpMap[ studyId ] = myInterp; #ifndef GUI_DISABLE_CORBA if ( !SUIT_PYTHON::initialized ) { // import 'salome' module and call 'salome_init' method; // do it only once on interpreter creation // ... first get python lock - PyLockWrapper aLock = myInterp->GetLockWrapper(); + PyLockWrapper aLock; // Acquire GIL // ... then import a module PyObjWrapper aMod = PyImport_ImportModule( "salome" ); if ( !aMod ) { @@ -1718,7 +1755,7 @@ void PyModuleHelper::initInterp( int studyId ) } // ... then call a method int embedded = 1; - PyObjWrapper aRes( PyObject_CallMethod( aMod, (char*)"salome_init", (char*)"ii", studyId, embedded ) ); + PyObjWrapper aRes( PyObject_CallMethod( aMod, (char*)"salome_init", (char*)"i", embedded ) ); if ( !aRes ) { // Error! PyErr_Print(); @@ -1732,7 +1769,7 @@ void PyModuleHelper::initInterp( int studyId ) \brief Import Python GUI module and store reference to the module. \internal - Attention! initInterp() should be called first!!! + Warning! initInterp() should be called first!!! */ void PyModuleHelper::importModule() { @@ -1747,7 +1784,7 @@ void PyModuleHelper::importModule() // import Python GUI module and put it in attribute // ... first get python lock - PyLockWrapper aLock = myInterp->GetLockWrapper(); + PyLockWrapper aLock; // Acquire GIL // ... then import a module QString aMod = QString( "%1GUI" ).arg( myModule->name() ); try { @@ -1787,7 +1824,7 @@ void PyModuleHelper::setWorkSpace() // call setWorkSpace() method // ... first get python lock - PyLockWrapper aLock = myInterp->GetLockWrapper(); + PyLockWrapper aLock; // Acquire GIL // ... then try to import SalomePyQt module. If it's not possible don't go on. PyObjWrapper aQtModule( PyImport_ImportModule( "SalomePyQt" ) ); @@ -1809,11 +1846,12 @@ void PyModuleHelper::setWorkSpace() if ( d ) aWorkspace = d->workstack(); } -#if SIP_VERSION < 0x040800 - PyObjWrapper pyws( sipBuildResult( 0, "M", aWorkspace, sipClass_QWidget) ); -#else - PyObjWrapper pyws( sipBuildResult( 0, "D", aWorkspace, sipType_QWidget , NULL) ); +#if SIP_VERSION >= 0x041300 + static const sipTypeDef *sipType_QWidget = 0; + if (!sipType_QWidget) + sipType_QWidget = sipFindType("QWidget"); #endif + PyObjWrapper pyws( sipBuildResult( 0, "D", aWorkspace, sipType_QWidget , NULL) ); // ... and finally call Python module's setWorkSpace() method (obsolete) if ( PyObject_HasAttrString( myPyModule, (char*)"setWorkSpace" ) ) { PyObjWrapper res( PyObject_CallMethod( myPyModule, (char*)"setWorkSpace", (char*)"O", pyws.get() ) ); @@ -1851,10 +1889,9 @@ void PyModuleHelper::internalInitialize( CAM_Application* app ) LightApp_Study* aStudy = dynamic_cast( app->activeStudy() ); if ( !aStudy ) return; - int aStudyId = aStudy ? aStudy->id() : 0; // initialize Python subinterpreter (on per study) and put it in variable - initInterp( aStudyId ); + initInterp(); if ( !myInterp ) return; // Error @@ -1865,7 +1902,7 @@ void PyModuleHelper::internalInitialize( CAM_Application* app ) // then call Python module's initialize() method // ... first get python lock - PyLockWrapper aLock = myInterp->GetLockWrapper(); + PyLockWrapper aLock; // Acquire GIL // ... (the Python module is already imported) // ... finally call Python module's initialize() method @@ -1898,9 +1935,9 @@ void PyModuleHelper::internalInitialize( CAM_Application* app ) // parse the return value // it should be a map: {integer:integer} int aKey, aValue; - if( key && PyInt_Check( key ) && value && PyInt_Check( value ) ) { - aKey = PyInt_AsLong( key ); - aValue = PyInt_AsLong( value ); + if( key && PyLong_Check( key ) && value && PyLong_Check( value ) ) { + aKey = PyLong_AsLong( key ); + aValue = PyLong_AsLong( value ); myWindowsMap[ aKey ] = aValue; } } @@ -1918,16 +1955,16 @@ void PyModuleHelper::internalInitialize( CAM_Application* app ) else { // parse the return value // result can be one string... - if ( PyString_Check( res2 ) ) { - myViewMgrList.append( PyString_AsString( res2 ) ); + if ( PyUnicode_Check( res2 ) ) { + myViewMgrList.append( PyUnicode_AsUTF8( res2 ) ); } // ... or list of strings else if ( PyList_Check( res2 ) ) { int size = PyList_Size( res2 ); for ( int i = 0; i < size; i++ ) { PyObject* value = PyList_GetItem( res2, i ); - if( value && PyString_Check( value ) ) { - myViewMgrList.append( PyString_AsString( value ) ); + if( value && PyUnicode_Check( value ) ) { + myViewMgrList.append( PyUnicode_AsUTF8( value ) ); } } } @@ -1952,10 +1989,11 @@ void PyModuleHelper::internalActivate( SUIT_Study* study ) // get study Id LightApp_Study* aStudy = dynamic_cast( study ); - int aStudyId = aStudy ? aStudy->id() : 0; + if ( !aStudy ) + return; // initialize Python subinterpreter (on per study) and put it in variable - initInterp( aStudyId ); + initInterp(); if ( !myInterp ) { myLastActivateStatus = false; return; // Error @@ -1969,7 +2007,7 @@ void PyModuleHelper::internalActivate( SUIT_Study* study ) } // get python lock - PyLockWrapper aLock = myInterp->GetLockWrapper(); + PyLockWrapper aLock; // Acquire GIL // call Python module's activate() method (for the new modules) if ( PyObject_HasAttrString( myPyModule , (char*)"activate" ) ) { @@ -2004,10 +2042,11 @@ void PyModuleHelper::internalCustomize( SUIT_Study* study ) // get study Id LightApp_Study* aStudy = dynamic_cast( study ); - int aStudyId = aStudy ? aStudy->id() : 0; + if ( !aStudy ) + return; // initialize Python subinterpreter (on per study) and put it in variable - initInterp( aStudyId ); + initInterp(); if ( !myInterp ) { myLastActivateStatus = false; return; // Error @@ -2024,7 +2063,7 @@ void PyModuleHelper::internalCustomize( SUIT_Study* study ) setWorkSpace(); // get python lock - PyLockWrapper aLock = myInterp->GetLockWrapper(); + PyLockWrapper aLock; // Acquire GIL if ( IsCallOldMethods ) { // call Python module's setSettings() method (obsolete) @@ -2080,7 +2119,8 @@ void PyModuleHelper::internalClosedStudy( SUIT_Study* theStudy ) // Get study Id // get study Id LightApp_Study* aStudy = dynamic_cast( theStudy ); - int aStudyId = aStudy ? aStudy->id() : 0; + if ( !aStudy ) + return; // check that Python subinterpreter is initialized and Python module is imported if ( !myInterp || !myPyModule ) { @@ -2089,7 +2129,7 @@ void PyModuleHelper::internalClosedStudy( SUIT_Study* theStudy ) } // then call Python module's deactivate() method if ( PyObject_HasAttrString( myPyModule , (char*)"closeStudy" ) ) { - PyObjWrapper res( PyObject_CallMethod( myPyModule, (char*)"closeStudy", (char*)"i", aStudyId ) ); + PyObjWrapper res( PyObject_CallMethod( myPyModule, (char*)"closeStudy", (char*)"i" ) ); if( !res ) { PyErr_Print(); } @@ -2148,12 +2188,11 @@ void PyModuleHelper::internalStudyChanged( SUIT_Study* study ) // get study Id LightApp_Study* aStudy = dynamic_cast( study ); - int id = aStudy ? aStudy->id() : 0; - - fmsg.message( QString( "study id = %1" ).arg( id ) ); + if ( !aStudy ) + return; // initialize Python subinterpreter (on per study) and put it in variable - initInterp( id ); + initInterp(); if ( !myInterp ) return; // Error @@ -2166,11 +2205,11 @@ void PyModuleHelper::internalStudyChanged( SUIT_Study* study ) setWorkSpace(); // get python lock - PyLockWrapper aLock = myInterp->GetLockWrapper(); + PyLockWrapper aLock; // Acquire GIL // call Python module's activeStudyChanged() method if ( PyObject_HasAttrString( myPyModule, (char*)"activeStudyChanged" ) ) { - PyObjWrapper res( PyObject_CallMethod( myPyModule, (char*)"activeStudyChanged", (char*)"i", id ) ); + PyObjWrapper res( PyObject_CallMethod( myPyModule, (char*)"activeStudyChanged", (char*)"i" ) ); if( !res ) { PyErr_Print(); } @@ -2204,6 +2243,44 @@ void PyModuleHelper::internalActionActivated( int id ) } } +/*! + \brief update selection from other views or modules + \internal + + Performs the following actions: + - calls Python module's onSelectionpdated(entries) method + + \param list of entries +*/ +void PyModuleHelper::internalSelectionUpdated(const QStringList& entries) +{ + FuncMsg fmsg("--- PyModuleHelper::internalSelectionUpdated()"); + MESSAGE("internalSelectionUpdated"); + + // Python interpreter should be initialized and Python module should be imported first + if (!myInterp || !myPyModule) + return; // Error + + QStringList* theList = new QStringList(entries); + +#if SIP_VERSION >= 0x041300 + static const sipTypeDef *sipType_QStringList = 0; + if (!sipType_QStringList) + sipType_QStringList = sipFindType("QStringList"); +#endif + PyObjWrapper sipList( sipBuildResult( 0, "D", theList, sipType_QStringList, NULL ) ); + if (PyObject_HasAttrString(myPyModule, (char*) "onSelectionUpdated")) + { + MESSAGE("call onSelectionUpdated"); + PyObjWrapper res(PyObject_CallMethod(myPyModule, (char*) "onSelectionUpdated", (char*) "O", sipList.get())); + + if (!res) + { + PyErr_Print(); + } + } +} + /*! \brief Context popup menu handling callback function \internal @@ -2260,11 +2337,12 @@ void PyModuleHelper::internalContextMenu( const QString& context, QMenu* menu ) if ( myXmlHandler ) myXmlHandler->createPopup( menu, aContext, aParent, aObject ); -#if SIP_VERSION < 0x040800 - PyObjWrapper sipPopup( sipBuildResult( 0, "M", menu, sipClass_QMenu ) ); -#else - PyObjWrapper sipPopup( sipBuildResult( 0, "D", menu, sipType_QMenu, NULL ) ); +#if SIP_VERSION >= 0x041300 + static const sipTypeDef *sipType_QMenu = 0; + if (!sipType_QMenu) + sipType_QMenu = sipFindType("QMenu"); #endif + PyObjWrapper sipPopup( sipBuildResult( 0, "D", menu, sipType_QMenu, NULL ) ); // then call Python module's createPopupMenu() method (for new modules) if ( PyObject_HasAttrString( myPyModule, (char*)"createPopupMenu" ) ) { @@ -2414,8 +2492,9 @@ void PyModuleHelper::internalCloneView( SUIT_ViewWindow* view ) \brief Module data saving callback function. \internal \param files output list of files where module stores data + \param url study URL */ -void PyModuleHelper::internalSave( QStringList& files ) +void PyModuleHelper::internalSave( QStringList& files, const QString& url ) { FuncMsg fmsg( "--- PyModuleHelper::internalSave()" ); @@ -2427,17 +2506,24 @@ void PyModuleHelper::internalSave( QStringList& files ) if ( PyObject_HasAttrString(myPyModule, (char*)"saveFiles") ) { + // try with two parameters (new syntax) PyObjWrapper res( PyObject_CallMethod( myPyModule, (char*)"saveFiles", - (char*)"s", files.first().toLatin1().constData() ) ); - + (char*)"ss", + files.first().toLatin1().constData(), + url.toLatin1().constData() ) ); + if ( !res ) + // try with single parameter (old syntax) + res = PyObject_CallMethod( myPyModule, (char*)"saveFiles", + (char*)"s", files.first().toLatin1().constData() ); + if ( !res ) { PyErr_Print(); } else { // parse the return value // result can be one string... - if ( PyString_Check( res ) ) { - QString astr = PyString_AsString( res ); + if ( PyUnicode_Check( res ) ) { + QString astr = PyUnicode_AsUTF8( res ); files.append( astr ); } //also result can be a list... @@ -2445,8 +2531,8 @@ void PyModuleHelper::internalSave( QStringList& files ) int size = PyList_Size( res ); for ( int i = 0; i < size; i++ ) { PyObject* value = PyList_GetItem( res, i ); - if ( value && PyString_Check( value ) ) { - files.append( PyString_AsString( value ) ); + if ( value && PyUnicode_Check( value ) ) { + files.append( PyUnicode_AsUTF8( value ) ); } } } @@ -2458,9 +2544,10 @@ void PyModuleHelper::internalSave( QStringList& files ) \brief Module data loading callback function. \internal \param files list of files where module data is stored + \param url study URL \param opened output success flag */ -void PyModuleHelper::internalLoad( const QStringList& files, bool& opened ) +void PyModuleHelper::internalLoad( const QStringList& files, const QString& url, bool& opened ) { FuncMsg fmsg( "--- PyModuleHelper::internalLoad()" ); @@ -2471,19 +2558,29 @@ void PyModuleHelper::internalLoad( const QStringList& files, bool& opened ) QStringList* theList = new QStringList( files ); -#if SIP_VERSION < 0x040800 - PyObjWrapper sipList( sipBuildResult( 0, "M", theList, sipClass_QStringList ) ); -#else - PyObjWrapper sipList( sipBuildResult( 0, "D", theList, sipType_QStringList, NULL ) ); +#if SIP_VERSION >= 0x041300 + static const sipTypeDef *sipType_QStringList = 0; + if (!sipType_QStringList) + sipType_QStringList = sipFindType("QStringList"); #endif + PyObjWrapper sipList( sipBuildResult( 0, "D", theList, sipType_QStringList, NULL ) ); if ( PyObject_HasAttrString(myPyModule , (char*)"openFiles") ) { + + // try with two parameters (new syntax) PyObjWrapper res( PyObject_CallMethod( myPyModule, (char*)"openFiles", - (char*)"O", sipList.get())); - if( !res || !PyBool_Check( res )) { + (char*)"Os", sipList.get(), + url.toLatin1().constData() ) ); + + if ( !res ) + // try with single parameter (old syntax) + res = PyObject_CallMethod( myPyModule, (char*)"openFiles", + (char*)"O", sipList.get() ); + + if ( !res || !PyBool_Check( res ) ) { PyErr_Print(); opened = false; } - else{ + else { opened = PyObject_IsTrue( res ); } } @@ -2514,8 +2611,8 @@ void PyModuleHelper::internalDumpPython( QStringList& files ) else { // parse the return value // result can be one string... - if ( PyString_Check( res ) ) { - QString astr = PyString_AsString( res ); + if ( PyUnicode_Check( res ) ) { + QString astr = PyUnicode_AsUTF8( res ); //SCRUTE(astr); files.append(astr); } @@ -2524,8 +2621,8 @@ void PyModuleHelper::internalDumpPython( QStringList& files ) int size = PyList_Size( res ); for ( int i = 0; i < size; i++ ) { PyObject* value = PyList_GetItem( res, i ); - if( value && PyString_Check( value ) ) { - files.append( PyString_AsString( value ) ); + if( value && PyUnicode_Check( value ) ) { + files.append( PyUnicode_AsUTF8( value ) ); } } } @@ -2552,7 +2649,7 @@ bool PyModuleHelper::internalIsDraggable( LightApp_DataObject* what ) if ( PyObject_HasAttrString(myPyModule , (char*)"isDraggable") ) { PyObjWrapper res( PyObject_CallMethod( myPyModule, (char*)"isDraggable", - (char*)"s", what->entry().toLatin1().constData() ) ); + (char*)"s", what->entry().toLatin1().constData() ) ); if( !res || !PyBool_Check( res )) { PyErr_Print(); draggable = false; @@ -2584,7 +2681,7 @@ bool PyModuleHelper::internalIsDropAccepted( LightApp_DataObject* where ) if ( PyObject_HasAttrString(myPyModule , (char*)"isDropAccepted") ) { PyObjWrapper res( PyObject_CallMethod( myPyModule, (char*)"isDropAccepted", - (char*)"s", where->entry().toLatin1().constData() ) ); + (char*)"s", where->entry().toLatin1().constData() ) ); if( !res || !PyBool_Check( res )) { PyErr_Print(); dropAccepted = false; @@ -2606,7 +2703,7 @@ bool PyModuleHelper::internalIsDropAccepted( LightApp_DataObject* where ) \param action current drop action (copy or move) */ void PyModuleHelper::internalDropObjects( const DataObjectList& what, SUIT_DataObject* where, - const int row, Qt::DropAction action ) + const int row, Qt::DropAction action ) { FuncMsg fmsg( "--- PyModuleHelper::internalDropObjects()" ); @@ -2625,16 +2722,17 @@ void PyModuleHelper::internalDropObjects( const DataObjectList& what, SUIT_DataO if ( dataObject ) theList->append( dataObject->entry() ); } -#if SIP_VERSION < 0x040800 - PyObjWrapper sipList( sipBuildResult( 0, "M", theList, sipClass_QStringList) ); -#else - PyObjWrapper sipList( sipBuildResult( 0, "D", theList, sipType_QStringList, NULL) ); +#if SIP_VERSION >= 0x041300 + static const sipTypeDef *sipType_QStringList = 0; + if (!sipType_QStringList) + sipType_QStringList = sipFindType("QStringList"); #endif + PyObjWrapper sipList( sipBuildResult( 0, "D", theList, sipType_QStringList, NULL) ); if ( PyObject_HasAttrString(myPyModule, (char*)"dropObjects") ) { - PyObjWrapper res( PyObject_CallMethod( myPyModule, (char*)"dropObjects", (char*)"Osii", - sipList.get(), - whereObject->entry().toLatin1().constData(), - row, action ) ); + PyObjWrapper res( PyObject_CallMethod( myPyModule, (char*)"dropObjects", (char*)"Osii", + sipList.get(), + whereObject->entry().toLatin1().constData(), + row, action ) ); if( !res ) { PyErr_Print(); @@ -2663,13 +2761,13 @@ QString PyModuleHelper::internalEngineIOR() const if ( PyObject_HasAttrString( myPyModule , "engineIOR" ) ) { PyObjWrapper res( PyObject_CallMethod( myPyModule, (char*)"engineIOR", (char*)"" ) ); if ( !res ) { - PyErr_Print(); + PyErr_Print(); } else { - // parse the return value, result chould be string - if ( PyString_Check( res ) ) { - ior = PyString_AsString( res ); - } + // parse the return value, result chould be string + if ( PyUnicode_Check( res ) ) { + ior = PyUnicode_AsUTF8( res ); + } } } } @@ -2688,24 +2786,24 @@ void PyModuleHelper::connectView( SUIT_ViewWindow* view ) // Connect tryCloseView() and deleteView() signals if ( viewMgr ) { connect( viewMgr, SIGNAL( tryCloseView( SUIT_ViewWindow* ) ), - this, SLOT( tryCloseView( SUIT_ViewWindow* ) ), - Qt::UniqueConnection ); + this, SLOT( tryCloseView( SUIT_ViewWindow* ) ), + Qt::UniqueConnection ); connect( viewMgr, SIGNAL( deleteView( SUIT_ViewWindow* ) ), this, SLOT( closeView( SUIT_ViewWindow* ) ), - Qt::UniqueConnection ); + Qt::UniqueConnection ); } // Connect cloneView() signal of an OCC View if ( view->inherits( "OCCViewer_ViewWindow" ) ) { connect( view, SIGNAL( viewCloned( SUIT_ViewWindow* ) ), this, SLOT( cloneView( SUIT_ViewWindow* ) ), - Qt::UniqueConnection ); + Qt::UniqueConnection ); } // Connect cloneView() signal of Plot2d View else if ( viewModel && viewModel->inherits( "Plot2d_Viewer" ) ) { connect( viewModel, SIGNAL( viewCloned( SUIT_ViewWindow* ) ), this, SLOT( cloneView( SUIT_ViewWindow* ) ), - Qt::UniqueConnection ); + Qt::UniqueConnection ); } }